mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 13:00:13 +02:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c7c0e488d | |||
| a7430dae31 | |||
| 98e8bda45d | |||
| 96221c8fa7 | |||
| 8c7cac369a | |||
| f1c011f677 | |||
| 351464c52d | |||
| da8ba31a88 | |||
| d8a8880e48 | |||
| fe36535aee | |||
| 67eec51e5f | |||
| a7f21db563 | |||
| 6c360c3c19 | |||
| 4d7779eae1 | |||
| 71b307e4a6 | |||
| a3a67d20a9 | |||
| 1c22461ee4 | |||
| 7785874605 | |||
| 9147b041f3 |
@@ -30,6 +30,7 @@ const config: UserConfig = {
|
|||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
'/@/i18n': resolve('src/i18n'),
|
||||||
'/@/main': resolve('src/main'),
|
'/@/main': resolve('src/main'),
|
||||||
'/@/shared': resolve('src/shared'),
|
'/@/shared': resolve('src/shared'),
|
||||||
},
|
},
|
||||||
@@ -39,6 +40,7 @@ const config: UserConfig = {
|
|||||||
plugins: [externalizeDepsPlugin()],
|
plugins: [externalizeDepsPlugin()],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
'/@/i18n': resolve('src/i18n'),
|
||||||
'/@/preload': resolve('src/preload'),
|
'/@/preload': resolve('src/preload'),
|
||||||
'/@/shared': resolve('src/shared'),
|
'/@/shared': resolve('src/shared'),
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ import eslintPluginReactHooks from 'eslint-plugin-react-hooks';
|
|||||||
import eslintPluginReactRefresh from 'eslint-plugin-react-refresh';
|
import eslintPluginReactRefresh from 'eslint-plugin-react-refresh';
|
||||||
|
|
||||||
export default tseslint.config(
|
export default tseslint.config(
|
||||||
{ ignores: ['**/node_modules', '**/dist', '**/out'] },
|
{ ignores: ['**/node_modules', '**/dist', '**/out', '**/*-schema.d.ts'] },
|
||||||
tseslint.configs.recommended,
|
tseslint.configs.recommended,
|
||||||
perfectionist.configs['recommended-natural'],
|
perfectionist.configs['recommended-natural'],
|
||||||
eslintPluginReact.configs.flat.recommended,
|
eslintPluginReact.configs.flat.recommended,
|
||||||
|
|||||||
+8
-3
@@ -27,6 +27,8 @@
|
|||||||
"dev": "electron-vite dev",
|
"dev": "electron-vite dev",
|
||||||
"dev:remote": "vite dev --config remote.vite.config.ts",
|
"dev:remote": "vite dev --config remote.vite.config.ts",
|
||||||
"dev:watch": "electron-vite dev --watch",
|
"dev:watch": "electron-vite dev --watch",
|
||||||
|
"generate-api": "pnpm run generate-api:subsonic",
|
||||||
|
"generate-api:subsonic": "openapi-typescript https://opensubsonic.netlify.app/docs/openapi/openapi.json -o ./src/shared/api/subsonic/subsonic-schema.d.ts",
|
||||||
"i18next": "i18next -c src/i18n/i18next-parser.config.js",
|
"i18next": "i18next -c src/i18n/i18next-parser.config.js",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"lint": "pnpm run lint-code && pnpm run lint-styles",
|
"lint": "pnpm run lint-code && pnpm run lint-styles",
|
||||||
@@ -71,9 +73,9 @@
|
|||||||
"@mantine/hooks": "^8.2.8",
|
"@mantine/hooks": "^8.2.8",
|
||||||
"@mantine/modals": "^8.2.8",
|
"@mantine/modals": "^8.2.8",
|
||||||
"@mantine/notifications": "^8.2.8",
|
"@mantine/notifications": "^8.2.8",
|
||||||
"@tanstack/react-query": "^4.32.1",
|
"@tanstack/react-query": "^5.83.0",
|
||||||
"@tanstack/react-query-devtools": "^4.32.1",
|
"@tanstack/react-query-devtools": "^5.83.0",
|
||||||
"@tanstack/react-query-persist-client": "^4.32.1",
|
"@tanstack/react-query-persist-client": "^5.83.0",
|
||||||
"@ts-rest/core": "^3.23.0",
|
"@ts-rest/core": "^3.23.0",
|
||||||
"@xhayper/discord-rpc": "^1.3.0",
|
"@xhayper/discord-rpc": "^1.3.0",
|
||||||
"audiomotion-analyzer": "^4.5.0",
|
"audiomotion-analyzer": "^4.5.0",
|
||||||
@@ -103,6 +105,7 @@
|
|||||||
"mpris-service": "^2.1.2",
|
"mpris-service": "^2.1.2",
|
||||||
"nanoid": "^3.3.3",
|
"nanoid": "^3.3.3",
|
||||||
"node-mpv": "github:jeffvli/Node-MPV#32b4d64395289ad710c41d481d2707a7acfc228f",
|
"node-mpv": "github:jeffvli/Node-MPV#32b4d64395289ad710c41d481d2707a7acfc228f",
|
||||||
|
"openapi-fetch": "^0.14.0",
|
||||||
"overlayscrollbars": "^2.11.1",
|
"overlayscrollbars": "^2.11.1",
|
||||||
"overlayscrollbars-react": "^0.5.6",
|
"overlayscrollbars-react": "^0.5.6",
|
||||||
"qs": "^6.14.0",
|
"qs": "^6.14.0",
|
||||||
@@ -135,6 +138,7 @@
|
|||||||
"@types/lodash": "^4.17.18",
|
"@types/lodash": "^4.17.18",
|
||||||
"@types/md5": "^2.3.5",
|
"@types/md5": "^2.3.5",
|
||||||
"@types/node": "^22.15.32",
|
"@types/node": "^22.15.32",
|
||||||
|
"@types/qs": "^6.14.0",
|
||||||
"@types/react": "^18.3.23",
|
"@types/react": "^18.3.23",
|
||||||
"@types/react-dom": "^18.3.7",
|
"@types/react-dom": "^18.3.7",
|
||||||
"@types/react-window": "^1.8.5",
|
"@types/react-window": "^1.8.5",
|
||||||
@@ -155,6 +159,7 @@
|
|||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.19",
|
"eslint-plugin-react-refresh": "^0.4.19",
|
||||||
"i18next-parser": "^9.0.2",
|
"i18next-parser": "^9.0.2",
|
||||||
|
"openapi-typescript": "^7.8.0",
|
||||||
"postcss-preset-mantine": "^1.17.0",
|
"postcss-preset-mantine": "^1.17.0",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prettier-plugin-packagejson": "^2.5.14",
|
"prettier-plugin-packagejson": "^2.5.14",
|
||||||
|
|||||||
Generated
+226
-122
@@ -60,14 +60,14 @@ importers:
|
|||||||
specifier: ^8.2.8
|
specifier: ^8.2.8
|
||||||
version: 8.2.8(@mantine/core@8.2.8(@mantine/hooks@8.2.8(react@19.1.0))(@types/react@18.3.23)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.2.8(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 8.2.8(@mantine/core@8.2.8(@mantine/hooks@8.2.8(react@19.1.0))(@types/react@18.3.23)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mantine/hooks@8.2.8(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^4.32.1
|
specifier: ^5.83.0
|
||||||
version: 4.36.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 5.83.0(react@19.1.0)
|
||||||
'@tanstack/react-query-devtools':
|
'@tanstack/react-query-devtools':
|
||||||
specifier: ^4.32.1
|
specifier: ^5.83.0
|
||||||
version: 4.36.1(@tanstack/react-query@4.36.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(react@19.1.0)
|
||||||
'@tanstack/react-query-persist-client':
|
'@tanstack/react-query-persist-client':
|
||||||
specifier: ^4.32.1
|
specifier: ^5.83.0
|
||||||
version: 4.36.1(@tanstack/react-query@4.36.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0))
|
version: 5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(react@19.1.0)
|
||||||
'@ts-rest/core':
|
'@ts-rest/core':
|
||||||
specifier: ^3.23.0
|
specifier: ^3.23.0
|
||||||
version: 3.52.1(@types/node@22.15.32)(zod@3.25.23)
|
version: 3.52.1(@types/node@22.15.32)(zod@3.25.23)
|
||||||
@@ -155,6 +155,9 @@ importers:
|
|||||||
node-mpv:
|
node-mpv:
|
||||||
specifier: github:jeffvli/Node-MPV#32b4d64395289ad710c41d481d2707a7acfc228f
|
specifier: github:jeffvli/Node-MPV#32b4d64395289ad710c41d481d2707a7acfc228f
|
||||||
version: https://codeload.github.com/jeffvli/Node-MPV/tar.gz/32b4d64395289ad710c41d481d2707a7acfc228f
|
version: https://codeload.github.com/jeffvli/Node-MPV/tar.gz/32b4d64395289ad710c41d481d2707a7acfc228f
|
||||||
|
openapi-fetch:
|
||||||
|
specifier: ^0.14.0
|
||||||
|
version: 0.14.0
|
||||||
overlayscrollbars:
|
overlayscrollbars:
|
||||||
specifier: ^2.11.1
|
specifier: ^2.11.1
|
||||||
version: 2.11.3
|
version: 2.11.3
|
||||||
@@ -246,6 +249,9 @@ importers:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.15.32
|
specifier: ^22.15.32
|
||||||
version: 22.15.32
|
version: 22.15.32
|
||||||
|
'@types/qs':
|
||||||
|
specifier: ^6.14.0
|
||||||
|
version: 6.14.0
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^18.3.23
|
specifier: ^18.3.23
|
||||||
version: 18.3.23
|
version: 18.3.23
|
||||||
@@ -266,7 +272,7 @@ importers:
|
|||||||
version: 8.18.1
|
version: 8.18.1
|
||||||
'@vitejs/plugin-react':
|
'@vitejs/plugin-react':
|
||||||
specifier: ^4.3.4
|
specifier: ^4.3.4
|
||||||
version: 4.5.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2))
|
version: 4.5.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0))
|
||||||
concurrently:
|
concurrently:
|
||||||
specifier: ^7.1.0
|
specifier: ^7.1.0
|
||||||
version: 7.6.0
|
version: 7.6.0
|
||||||
@@ -284,7 +290,7 @@ importers:
|
|||||||
version: 3.2.1
|
version: 3.2.1
|
||||||
electron-vite:
|
electron-vite:
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2))
|
version: 3.1.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0))
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^9.24.0
|
specifier: ^9.24.0
|
||||||
version: 9.27.0
|
version: 9.27.0
|
||||||
@@ -306,6 +312,9 @@ importers:
|
|||||||
i18next-parser:
|
i18next-parser:
|
||||||
specifier: ^9.0.2
|
specifier: ^9.0.2
|
||||||
version: 9.3.0
|
version: 9.3.0
|
||||||
|
openapi-typescript:
|
||||||
|
specifier: ^7.8.0
|
||||||
|
version: 7.8.0(typescript@5.8.3)
|
||||||
postcss-preset-mantine:
|
postcss-preset-mantine:
|
||||||
specifier: ^1.17.0
|
specifier: ^1.17.0
|
||||||
version: 1.17.0(postcss@8.5.3)
|
version: 1.17.0(postcss@8.5.3)
|
||||||
@@ -335,7 +344,7 @@ importers:
|
|||||||
version: 5.8.3
|
version: 5.8.3
|
||||||
vite:
|
vite:
|
||||||
specifier: ^6.3.5
|
specifier: ^6.3.5
|
||||||
version: 6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)
|
version: 6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0)
|
||||||
vite-plugin-conditional-import:
|
vite-plugin-conditional-import:
|
||||||
specifier: ^0.1.7
|
specifier: ^0.1.7
|
||||||
version: 0.1.7
|
version: 0.1.7
|
||||||
@@ -344,7 +353,7 @@ importers:
|
|||||||
version: 1.6.0
|
version: 1.6.0
|
||||||
vite-plugin-ejs:
|
vite-plugin-ejs:
|
||||||
specifier: ^1.7.0
|
specifier: ^1.7.0
|
||||||
version: 1.7.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2))
|
version: 1.7.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0))
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@@ -1040,6 +1049,16 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8 || ^17.0 || ^18.0
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
|
||||||
|
'@redocly/ajv@8.11.2':
|
||||||
|
resolution: {integrity: sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==}
|
||||||
|
|
||||||
|
'@redocly/config@0.22.2':
|
||||||
|
resolution: {integrity: sha512-roRDai8/zr2S9YfmzUfNhKjOF0NdcOIqF7bhf4MVC5UxpjIysDjyudvlAiVbpPHp3eDRWbdzUgtkK1a7YiDNyQ==}
|
||||||
|
|
||||||
|
'@redocly/openapi-core@1.34.3':
|
||||||
|
resolution: {integrity: sha512-3arRdUp1fNx55itnjKiUhO6t4Mf91TsrTIYINDNLAZPS0TPd5YpiXRctwjel0qqWoOOhjA34cZ3m4dksLDFUYg==}
|
||||||
|
engines: {node: '>=18.17.0', npm: '>=9.5.0'}
|
||||||
|
|
||||||
'@remix-run/router@1.23.0':
|
'@remix-run/router@1.23.0':
|
||||||
resolution: {integrity: sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==}
|
resolution: {integrity: sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@@ -1163,39 +1182,31 @@ packages:
|
|||||||
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
|
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
'@tanstack/match-sorter-utils@8.19.4':
|
'@tanstack/query-core@5.83.0':
|
||||||
resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==}
|
resolution: {integrity: sha512-0M8dA+amXUkyz5cVUm/B+zSk3xkQAcuXuz5/Q/LveT4ots2rBpPTZOzd7yJa2Utsf8D2Upl5KyjhHRY+9lB/XA==}
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
'@tanstack/query-core@4.36.1':
|
'@tanstack/query-devtools@5.81.2':
|
||||||
resolution: {integrity: sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==}
|
resolution: {integrity: sha512-jCeJcDCwKfoyyBXjXe9+Lo8aTkavygHHsUHAlxQKKaDeyT0qyQNLKl7+UyqYH2dDF6UN/14873IPBHchcsU+Zg==}
|
||||||
|
|
||||||
'@tanstack/query-persist-client-core@4.36.1':
|
'@tanstack/query-persist-client-core@5.83.0':
|
||||||
resolution: {integrity: sha512-eocgCeI7D7TRv1IUUBMfVwOI0wdSmMkBIbkKhqEdTrnUHUQEeOaYac8oeZk2cumAWJdycu6P/wB+WqGynTnzXg==}
|
resolution: {integrity: sha512-hdKgHkr1MYnwZX+QHj/9JjXZx9gL2RUCD5xSX0EHZiqUQhMk4Gcryq9xosn8LmYRMlhkjk7n9uV+X4UXRvgoIg==}
|
||||||
|
|
||||||
'@tanstack/react-query-devtools@4.36.1':
|
'@tanstack/react-query-devtools@5.83.0':
|
||||||
resolution: {integrity: sha512-WYku83CKP3OevnYSG8Y/QO9g0rT75v1om5IvcWUwiUZJ4LanYGLVCZ8TdFG5jfsq4Ej/lu2wwDAULEUnRIMBSw==}
|
resolution: {integrity: sha512-yfp8Uqd3I1jgx8gl0lxbSSESu5y4MO2ThOPBnGNTYs0P+ZFu+E9g5IdOngyUGuo6Uz6Qa7p9TLdZEX3ntik2fQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tanstack/react-query': ^4.36.1
|
'@tanstack/react-query': ^5.83.0
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react: ^18 || ^19
|
||||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
|
|
||||||
'@tanstack/react-query-persist-client@4.36.1':
|
'@tanstack/react-query-persist-client@5.83.0':
|
||||||
resolution: {integrity: sha512-32I5b9aAu4NCiXZ7Te/KEQLfHbYeTNriVPrKYcvEThnZ9tlW01vLcSoxpUIsMYRsembvJUUAkzYBAiZHLOd6pQ==}
|
resolution: {integrity: sha512-uEqJnSbqlvzlhYJ+RU+2c2DmbbT7cw6eFjiewEXZFXaSGWNjvUG02LePrwL8cdLlRQFcZKas30IdckboOoVg9Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tanstack/react-query': ^4.36.1
|
'@tanstack/react-query': ^5.83.0
|
||||||
|
react: ^18 || ^19
|
||||||
|
|
||||||
'@tanstack/react-query@4.36.1':
|
'@tanstack/react-query@5.83.0':
|
||||||
resolution: {integrity: sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==}
|
resolution: {integrity: sha512-/XGYhZ3foc5H0VM2jLSD/NyBRIOK4q9kfeml4+0x2DlL6xVuAcVEW+hTlTapAmejObg0i3eNqhkr2dT+eciwoQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react: ^18 || ^19
|
||||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
react-native: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
react-dom:
|
|
||||||
optional: true
|
|
||||||
react-native:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@tootallnate/once@2.0.0':
|
'@tootallnate/once@2.0.0':
|
||||||
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
|
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
|
||||||
@@ -1269,6 +1280,9 @@ packages:
|
|||||||
'@types/prop-types@15.7.14':
|
'@types/prop-types@15.7.14':
|
||||||
resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==}
|
resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==}
|
||||||
|
|
||||||
|
'@types/qs@6.14.0':
|
||||||
|
resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
|
||||||
|
|
||||||
'@types/react-dom@18.3.7':
|
'@types/react-dom@18.3.7':
|
||||||
resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==}
|
resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1428,6 +1442,10 @@ packages:
|
|||||||
ajv@8.17.1:
|
ajv@8.17.1:
|
||||||
resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
|
resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
|
||||||
|
|
||||||
|
ansi-colors@4.1.3:
|
||||||
|
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
ansi-regex@5.0.1:
|
ansi-regex@5.0.1:
|
||||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1674,6 +1692,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
change-case@5.4.4:
|
||||||
|
resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==}
|
||||||
|
|
||||||
charenc@0.0.2:
|
charenc@0.0.2:
|
||||||
resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==}
|
resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==}
|
||||||
|
|
||||||
@@ -1752,6 +1773,9 @@ packages:
|
|||||||
colord@2.9.3:
|
colord@2.9.3:
|
||||||
resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
|
resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
|
||||||
|
|
||||||
|
colorette@1.4.0:
|
||||||
|
resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==}
|
||||||
|
|
||||||
colorjs.io@0.5.2:
|
colorjs.io@0.5.2:
|
||||||
resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
|
resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
|
||||||
|
|
||||||
@@ -1800,10 +1824,6 @@ packages:
|
|||||||
convert-source-map@2.0.0:
|
convert-source-map@2.0.0:
|
||||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||||
|
|
||||||
copy-anything@3.0.5:
|
|
||||||
resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
|
|
||||||
engines: {node: '>=12.13'}
|
|
||||||
|
|
||||||
core-util-is@1.0.2:
|
core-util-is@1.0.2:
|
||||||
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
|
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
|
||||||
|
|
||||||
@@ -2701,6 +2721,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
|
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
index-to-position@1.1.0:
|
||||||
|
resolution: {integrity: sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
infer-owner@1.0.4:
|
infer-owner@1.0.4:
|
||||||
resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==}
|
resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==}
|
||||||
|
|
||||||
@@ -2870,10 +2894,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
|
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
is-what@4.1.16:
|
|
||||||
resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
|
|
||||||
engines: {node: '>=12.13'}
|
|
||||||
|
|
||||||
isarray@1.0.0:
|
isarray@1.0.0:
|
||||||
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
|
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
|
||||||
|
|
||||||
@@ -2903,6 +2923,10 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
js-levenshtein@1.1.6:
|
||||||
|
resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
js-tokens@4.0.0:
|
js-tokens@4.0.0:
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||||
|
|
||||||
@@ -3339,6 +3363,18 @@ packages:
|
|||||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
openapi-fetch@0.14.0:
|
||||||
|
resolution: {integrity: sha512-PshIdm1NgdLvb05zp8LqRQMNSKzIlPkyMxYFxwyHR+UlKD4t2nUjkDhNxeRbhRSEd3x5EUNh2w5sJYwkhOH4fg==}
|
||||||
|
|
||||||
|
openapi-typescript-helpers@0.0.15:
|
||||||
|
resolution: {integrity: sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==}
|
||||||
|
|
||||||
|
openapi-typescript@7.8.0:
|
||||||
|
resolution: {integrity: sha512-1EeVWmDzi16A+siQlo/SwSGIT7HwaFAVjvMA7/jG5HMLSnrUOzPL7uSTRZZa4v/LCRxHTApHKtNY6glApEoiUQ==}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
typescript: ^5.x
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -3402,6 +3438,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
parse-json@8.3.0:
|
||||||
|
resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
parse5-htmlparser2-tree-adapter@7.1.0:
|
parse5-htmlparser2-tree-adapter@7.1.0:
|
||||||
resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==}
|
resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==}
|
||||||
|
|
||||||
@@ -3470,6 +3510,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==}
|
resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==}
|
||||||
engines: {node: '>=10.4.0'}
|
engines: {node: '>=10.4.0'}
|
||||||
|
|
||||||
|
pluralize@8.0.0:
|
||||||
|
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
possible-typed-array-names@1.1.0:
|
possible-typed-array-names@1.1.0:
|
||||||
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -3797,9 +3841,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
|
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
remove-accents@0.5.0:
|
|
||||||
resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==}
|
|
||||||
|
|
||||||
remove-trailing-separator@1.1.0:
|
remove-trailing-separator@1.1.0:
|
||||||
resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==}
|
resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==}
|
||||||
|
|
||||||
@@ -4288,9 +4329,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==}
|
resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==}
|
||||||
engines: {node: '>= 8.0'}
|
engines: {node: '>= 8.0'}
|
||||||
|
|
||||||
superjson@1.13.3:
|
supports-color@10.0.0:
|
||||||
resolution: {integrity: sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==}
|
resolution: {integrity: sha512-HRVVSbCCMbj7/kdWF9Q+bbckjBHLtHMEoJWlkmYzzdwhYMkjkOwubLM6t7NbWKjgKamGDrWL1++KrjUO1t9oAQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
supports-color@7.2.0:
|
supports-color@7.2.0:
|
||||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||||
@@ -4489,6 +4530,9 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
browserslist: '>= 4.21.0'
|
browserslist: '>= 4.21.0'
|
||||||
|
|
||||||
|
uri-js-replace@1.0.1:
|
||||||
|
resolution: {integrity: sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==}
|
||||||
|
|
||||||
uri-js@4.4.1:
|
uri-js@4.4.1:
|
||||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||||
|
|
||||||
@@ -4744,6 +4788,14 @@ packages:
|
|||||||
yallist@4.0.0:
|
yallist@4.0.0:
|
||||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||||
|
|
||||||
|
yaml-ast-parser@0.0.43:
|
||||||
|
resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==}
|
||||||
|
|
||||||
|
yaml@2.8.0:
|
||||||
|
resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==}
|
||||||
|
engines: {node: '>= 14.6'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
yargs-parser@21.1.1:
|
yargs-parser@21.1.1:
|
||||||
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
|
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -4851,7 +4903,7 @@ snapshots:
|
|||||||
'@babel/traverse': 7.27.1
|
'@babel/traverse': 7.27.1
|
||||||
'@babel/types': 7.27.1
|
'@babel/types': 7.27.1
|
||||||
convert-source-map: 2.0.0
|
convert-source-map: 2.0.0
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
gensync: 1.0.0-beta.2
|
gensync: 1.0.0-beta.2
|
||||||
json5: 2.2.3
|
json5: 2.2.3
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
@@ -4937,7 +4989,7 @@ snapshots:
|
|||||||
'@babel/parser': 7.27.2
|
'@babel/parser': 7.27.2
|
||||||
'@babel/template': 7.27.2
|
'@babel/template': 7.27.2
|
||||||
'@babel/types': 7.27.1
|
'@babel/types': 7.27.1
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
globals: 11.12.0
|
globals: 11.12.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -5039,7 +5091,7 @@ snapshots:
|
|||||||
|
|
||||||
'@electron/get@2.0.3':
|
'@electron/get@2.0.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
env-paths: 2.2.1
|
env-paths: 2.2.1
|
||||||
fs-extra: 8.1.0
|
fs-extra: 8.1.0
|
||||||
got: 11.8.6
|
got: 11.8.6
|
||||||
@@ -5069,7 +5121,7 @@ snapshots:
|
|||||||
|
|
||||||
'@electron/notarize@2.5.0':
|
'@electron/notarize@2.5.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
fs-extra: 9.1.0
|
fs-extra: 9.1.0
|
||||||
promise-retry: 2.0.1
|
promise-retry: 2.0.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -5078,7 +5130,7 @@ snapshots:
|
|||||||
'@electron/osx-sign@1.3.1':
|
'@electron/osx-sign@1.3.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
compare-version: 0.1.2
|
compare-version: 0.1.2
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
fs-extra: 10.1.0
|
fs-extra: 10.1.0
|
||||||
isbinaryfile: 4.0.10
|
isbinaryfile: 4.0.10
|
||||||
minimist: 1.2.8
|
minimist: 1.2.8
|
||||||
@@ -5091,7 +5143,7 @@ snapshots:
|
|||||||
'@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2
|
'@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2
|
||||||
'@malept/cross-spawn-promise': 2.0.0
|
'@malept/cross-spawn-promise': 2.0.0
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
detect-libc: 2.0.4
|
detect-libc: 2.0.4
|
||||||
fs-extra: 10.1.0
|
fs-extra: 10.1.0
|
||||||
got: 11.8.6
|
got: 11.8.6
|
||||||
@@ -5110,7 +5162,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@electron/asar': 3.2.18
|
'@electron/asar': 3.2.18
|
||||||
'@malept/cross-spawn-promise': 2.0.0
|
'@malept/cross-spawn-promise': 2.0.0
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
dir-compare: 4.2.0
|
dir-compare: 4.2.0
|
||||||
fs-extra: 11.3.1
|
fs-extra: 11.3.1
|
||||||
minimatch: 9.0.5
|
minimatch: 9.0.5
|
||||||
@@ -5121,7 +5173,7 @@ snapshots:
|
|||||||
'@electron/windows-sign@1.2.2':
|
'@electron/windows-sign@1.2.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
cross-dirname: 0.1.0
|
cross-dirname: 0.1.0
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
fs-extra: 11.3.1
|
fs-extra: 11.3.1
|
||||||
minimist: 1.2.8
|
minimist: 1.2.8
|
||||||
postject: 1.0.0-alpha.6
|
postject: 1.0.0-alpha.6
|
||||||
@@ -5214,7 +5266,7 @@ snapshots:
|
|||||||
'@eslint/config-array@0.20.0':
|
'@eslint/config-array@0.20.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint/object-schema': 2.1.6
|
'@eslint/object-schema': 2.1.6
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -5232,7 +5284,7 @@ snapshots:
|
|||||||
'@eslint/eslintrc@3.3.1':
|
'@eslint/eslintrc@3.3.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
espree: 10.3.0
|
espree: 10.3.0
|
||||||
globals: 14.0.0
|
globals: 14.0.0
|
||||||
ignore: 5.3.2
|
ignore: 5.3.2
|
||||||
@@ -5337,7 +5389,7 @@ snapshots:
|
|||||||
|
|
||||||
'@malept/flatpak-bundler@0.4.0':
|
'@malept/flatpak-bundler@0.4.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
fs-extra: 9.1.0
|
fs-extra: 9.1.0
|
||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
tmp-promise: 3.0.3
|
tmp-promise: 3.0.3
|
||||||
@@ -5547,6 +5599,29 @@ snapshots:
|
|||||||
'@babel/runtime': 7.27.1
|
'@babel/runtime': 7.27.1
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
|
|
||||||
|
'@redocly/ajv@8.11.2':
|
||||||
|
dependencies:
|
||||||
|
fast-deep-equal: 3.1.3
|
||||||
|
json-schema-traverse: 1.0.0
|
||||||
|
require-from-string: 2.0.2
|
||||||
|
uri-js-replace: 1.0.1
|
||||||
|
|
||||||
|
'@redocly/config@0.22.2': {}
|
||||||
|
|
||||||
|
'@redocly/openapi-core@1.34.3(supports-color@10.0.0)':
|
||||||
|
dependencies:
|
||||||
|
'@redocly/ajv': 8.11.2
|
||||||
|
'@redocly/config': 0.22.2
|
||||||
|
colorette: 1.4.0
|
||||||
|
https-proxy-agent: 7.0.6(supports-color@10.0.0)
|
||||||
|
js-levenshtein: 1.1.6
|
||||||
|
js-yaml: 4.1.0
|
||||||
|
minimatch: 5.1.6
|
||||||
|
pluralize: 8.0.0
|
||||||
|
yaml-ast-parser: 0.0.43
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@remix-run/router@1.23.0': {}
|
'@remix-run/router@1.23.0': {}
|
||||||
|
|
||||||
'@rolldown/pluginutils@1.0.0-beta.9': {}
|
'@rolldown/pluginutils@1.0.0-beta.9': {}
|
||||||
@@ -5621,37 +5696,30 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect: 2.0.1
|
defer-to-connect: 2.0.1
|
||||||
|
|
||||||
'@tanstack/match-sorter-utils@8.19.4':
|
'@tanstack/query-core@5.83.0': {}
|
||||||
dependencies:
|
|
||||||
remove-accents: 0.5.0
|
|
||||||
|
|
||||||
'@tanstack/query-core@4.36.1': {}
|
'@tanstack/query-devtools@5.81.2': {}
|
||||||
|
|
||||||
'@tanstack/query-persist-client-core@4.36.1':
|
'@tanstack/query-persist-client-core@5.83.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/query-core': 4.36.1
|
'@tanstack/query-core': 5.83.0
|
||||||
|
|
||||||
'@tanstack/react-query-devtools@4.36.1(@tanstack/react-query@4.36.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
'@tanstack/react-query-devtools@5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(react@19.1.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/match-sorter-utils': 8.19.4
|
'@tanstack/query-devtools': 5.81.2
|
||||||
'@tanstack/react-query': 4.36.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
'@tanstack/react-query': 5.83.0(react@19.1.0)
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
react-dom: 19.1.0(react@19.1.0)
|
|
||||||
superjson: 1.13.3
|
|
||||||
use-sync-external-store: 1.5.0(react@19.1.0)
|
|
||||||
|
|
||||||
'@tanstack/react-query-persist-client@4.36.1(@tanstack/react-query@4.36.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0))':
|
'@tanstack/react-query-persist-client@5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(react@19.1.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/query-persist-client-core': 4.36.1
|
'@tanstack/query-persist-client-core': 5.83.0
|
||||||
'@tanstack/react-query': 4.36.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
'@tanstack/react-query': 5.83.0(react@19.1.0)
|
||||||
|
react: 19.1.0
|
||||||
'@tanstack/react-query@4.36.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
|
||||||
dependencies:
|
'@tanstack/react-query@5.83.0(react@19.1.0)':
|
||||||
'@tanstack/query-core': 4.36.1
|
dependencies:
|
||||||
|
'@tanstack/query-core': 5.83.0
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
use-sync-external-store: 1.5.0(react@19.1.0)
|
|
||||||
optionalDependencies:
|
|
||||||
react-dom: 19.1.0(react@19.1.0)
|
|
||||||
|
|
||||||
'@tootallnate/once@2.0.0': {}
|
'@tootallnate/once@2.0.0': {}
|
||||||
|
|
||||||
@@ -5732,6 +5800,8 @@ snapshots:
|
|||||||
|
|
||||||
'@types/prop-types@15.7.14': {}
|
'@types/prop-types@15.7.14': {}
|
||||||
|
|
||||||
|
'@types/qs@6.14.0': {}
|
||||||
|
|
||||||
'@types/react-dom@18.3.7(@types/react@18.3.23)':
|
'@types/react-dom@18.3.7(@types/react@18.3.23)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 18.3.23
|
'@types/react': 18.3.23
|
||||||
@@ -5798,7 +5868,7 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 8.32.1
|
'@typescript-eslint/types': 8.32.1
|
||||||
'@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
|
'@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.32.1
|
'@typescript-eslint/visitor-keys': 8.32.1
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
eslint: 9.27.0
|
eslint: 9.27.0
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -5813,7 +5883,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
|
'@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
|
||||||
'@typescript-eslint/utils': 8.32.1(eslint@9.27.0)(typescript@5.8.3)
|
'@typescript-eslint/utils': 8.32.1(eslint@9.27.0)(typescript@5.8.3)
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
eslint: 9.27.0
|
eslint: 9.27.0
|
||||||
ts-api-utils: 2.1.0(typescript@5.8.3)
|
ts-api-utils: 2.1.0(typescript@5.8.3)
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
@@ -5826,7 +5896,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.32.1
|
'@typescript-eslint/types': 8.32.1
|
||||||
'@typescript-eslint/visitor-keys': 8.32.1
|
'@typescript-eslint/visitor-keys': 8.32.1
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
fast-glob: 3.3.3
|
fast-glob: 3.3.3
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
minimatch: 9.0.5
|
minimatch: 9.0.5
|
||||||
@@ -5852,7 +5922,7 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 8.32.1
|
'@typescript-eslint/types': 8.32.1
|
||||||
eslint-visitor-keys: 4.2.0
|
eslint-visitor-keys: 4.2.0
|
||||||
|
|
||||||
'@vitejs/plugin-react@4.5.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2))':
|
'@vitejs/plugin-react@4.5.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.27.1
|
'@babel/core': 7.27.1
|
||||||
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.1)
|
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.1)
|
||||||
@@ -5860,7 +5930,7 @@ snapshots:
|
|||||||
'@rolldown/pluginutils': 1.0.0-beta.9
|
'@rolldown/pluginutils': 1.0.0-beta.9
|
||||||
'@types/babel__core': 7.20.5
|
'@types/babel__core': 7.20.5
|
||||||
react-refresh: 0.17.0
|
react-refresh: 0.17.0
|
||||||
vite: 6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)
|
vite: 6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -5896,7 +5966,7 @@ snapshots:
|
|||||||
|
|
||||||
agent-base@6.0.2:
|
agent-base@6.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -5933,6 +6003,8 @@ snapshots:
|
|||||||
json-schema-traverse: 1.0.0
|
json-schema-traverse: 1.0.0
|
||||||
require-from-string: 2.0.2
|
require-from-string: 2.0.2
|
||||||
|
|
||||||
|
ansi-colors@4.1.3: {}
|
||||||
|
|
||||||
ansi-regex@5.0.1: {}
|
ansi-regex@5.0.1: {}
|
||||||
|
|
||||||
ansi-regex@6.1.0: {}
|
ansi-regex@6.1.0: {}
|
||||||
@@ -5966,7 +6038,7 @@ snapshots:
|
|||||||
builder-util-runtime: 9.3.1
|
builder-util-runtime: 9.3.1
|
||||||
chromium-pickle-js: 0.2.0
|
chromium-pickle-js: 0.2.0
|
||||||
config-file-ts: 0.2.8-rc1
|
config-file-ts: 0.2.8-rc1
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12)
|
dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12)
|
||||||
dotenv: 16.5.0
|
dotenv: 16.5.0
|
||||||
dotenv-expand: 11.0.7
|
dotenv-expand: 11.0.7
|
||||||
@@ -6186,7 +6258,7 @@ snapshots:
|
|||||||
|
|
||||||
builder-util-runtime@9.3.1:
|
builder-util-runtime@9.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
sax: 1.4.1
|
sax: 1.4.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -6199,10 +6271,10 @@ snapshots:
|
|||||||
builder-util-runtime: 9.3.1
|
builder-util-runtime: 9.3.1
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
fs-extra: 10.1.0
|
fs-extra: 10.1.0
|
||||||
http-proxy-agent: 7.0.2
|
http-proxy-agent: 7.0.2
|
||||||
https-proxy-agent: 7.0.6
|
https-proxy-agent: 7.0.6(supports-color@10.0.0)
|
||||||
is-ci: 3.0.1
|
is-ci: 3.0.1
|
||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
sanitize-filename: 1.6.3
|
sanitize-filename: 1.6.3
|
||||||
@@ -6283,6 +6355,8 @@ snapshots:
|
|||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
supports-color: 7.2.0
|
supports-color: 7.2.0
|
||||||
|
|
||||||
|
change-case@5.4.4: {}
|
||||||
|
|
||||||
charenc@0.0.2: {}
|
charenc@0.0.2: {}
|
||||||
|
|
||||||
cheerio-select@2.1.0:
|
cheerio-select@2.1.0:
|
||||||
@@ -6364,6 +6438,8 @@ snapshots:
|
|||||||
|
|
||||||
colord@2.9.3: {}
|
colord@2.9.3: {}
|
||||||
|
|
||||||
|
colorette@1.4.0: {}
|
||||||
|
|
||||||
colorjs.io@0.5.2: {}
|
colorjs.io@0.5.2: {}
|
||||||
|
|
||||||
colors@1.4.0: {}
|
colors@1.4.0: {}
|
||||||
@@ -6418,10 +6494,6 @@ snapshots:
|
|||||||
|
|
||||||
convert-source-map@2.0.0: {}
|
convert-source-map@2.0.0: {}
|
||||||
|
|
||||||
copy-anything@3.0.5:
|
|
||||||
dependencies:
|
|
||||||
is-what: 4.1.16
|
|
||||||
|
|
||||||
core-util-is@1.0.2:
|
core-util-is@1.0.2:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -6521,9 +6593,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.0.0
|
ms: 2.0.0
|
||||||
|
|
||||||
debug@4.4.1:
|
debug@4.4.1(supports-color@10.0.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
|
optionalDependencies:
|
||||||
|
supports-color: 10.0.0
|
||||||
|
|
||||||
decompress-response@6.0.0:
|
decompress-response@6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6713,7 +6787,7 @@ snapshots:
|
|||||||
|
|
||||||
electron-localshortcut@3.2.1:
|
electron-localshortcut@3.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
electron-is-accelerator: 0.1.2
|
electron-is-accelerator: 0.1.2
|
||||||
keyboardevent-from-electron-accelerator: 2.0.0
|
keyboardevent-from-electron-accelerator: 2.0.0
|
||||||
keyboardevents-areequal: 0.2.2
|
keyboardevents-areequal: 0.2.2
|
||||||
@@ -6755,7 +6829,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
electron-vite@3.1.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)):
|
electron-vite@3.1.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.27.1
|
'@babel/core': 7.27.1
|
||||||
'@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.27.1)
|
'@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.27.1)
|
||||||
@@ -6763,14 +6837,14 @@ snapshots:
|
|||||||
esbuild: 0.25.4
|
esbuild: 0.25.4
|
||||||
magic-string: 0.30.17
|
magic-string: 0.30.17
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
vite: 6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)
|
vite: 6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
electron-winstaller@5.4.0:
|
electron-winstaller@5.4.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@electron/asar': 3.4.1
|
'@electron/asar': 3.4.1
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
fs-extra: 7.0.1
|
fs-extra: 7.0.1
|
||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
temp: 0.9.4
|
temp: 0.9.4
|
||||||
@@ -7038,7 +7112,7 @@ snapshots:
|
|||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
escape-string-regexp: 4.0.0
|
escape-string-regexp: 4.0.0
|
||||||
eslint-scope: 8.3.0
|
eslint-scope: 8.3.0
|
||||||
eslint-visitor-keys: 4.2.0
|
eslint-visitor-keys: 4.2.0
|
||||||
@@ -7092,7 +7166,7 @@ snapshots:
|
|||||||
|
|
||||||
extract-zip@2.0.1:
|
extract-zip@2.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
get-stream: 5.2.0
|
get-stream: 5.2.0
|
||||||
yauzl: 2.10.0
|
yauzl: 2.10.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
@@ -7499,14 +7573,14 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@tootallnate/once': 2.0.0
|
'@tootallnate/once': 2.0.0
|
||||||
agent-base: 6.0.2
|
agent-base: 6.0.2
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
http-proxy-agent@7.0.2:
|
http-proxy-agent@7.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 7.1.3
|
agent-base: 7.1.3
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -7518,14 +7592,14 @@ snapshots:
|
|||||||
https-proxy-agent@5.0.1:
|
https-proxy-agent@5.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 6.0.2
|
agent-base: 6.0.2
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
https-proxy-agent@7.0.6:
|
https-proxy-agent@7.0.6(supports-color@10.0.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 7.1.3
|
agent-base: 7.1.3
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -7598,6 +7672,8 @@ snapshots:
|
|||||||
|
|
||||||
indent-string@4.0.0: {}
|
indent-string@4.0.0: {}
|
||||||
|
|
||||||
|
index-to-position@1.1.0: {}
|
||||||
|
|
||||||
infer-owner@1.0.4: {}
|
infer-owner@1.0.4: {}
|
||||||
|
|
||||||
inflight@1.0.6:
|
inflight@1.0.6:
|
||||||
@@ -7758,8 +7834,6 @@ snapshots:
|
|||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
get-intrinsic: 1.3.0
|
get-intrinsic: 1.3.0
|
||||||
|
|
||||||
is-what@4.1.16: {}
|
|
||||||
|
|
||||||
isarray@1.0.0: {}
|
isarray@1.0.0: {}
|
||||||
|
|
||||||
isarray@2.0.5: {}
|
isarray@2.0.5: {}
|
||||||
@@ -7792,6 +7866,8 @@ snapshots:
|
|||||||
filelist: 1.0.4
|
filelist: 1.0.4
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
|
|
||||||
|
js-levenshtein@1.1.6: {}
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
|
|
||||||
js-yaml@4.1.0:
|
js-yaml@4.1.0:
|
||||||
@@ -8192,6 +8268,22 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-fn: 2.1.0
|
mimic-fn: 2.1.0
|
||||||
|
|
||||||
|
openapi-fetch@0.14.0:
|
||||||
|
dependencies:
|
||||||
|
openapi-typescript-helpers: 0.0.15
|
||||||
|
|
||||||
|
openapi-typescript-helpers@0.0.15: {}
|
||||||
|
|
||||||
|
openapi-typescript@7.8.0(typescript@5.8.3):
|
||||||
|
dependencies:
|
||||||
|
'@redocly/openapi-core': 1.34.3(supports-color@10.0.0)
|
||||||
|
ansi-colors: 4.1.3
|
||||||
|
change-case: 5.4.4
|
||||||
|
parse-json: 8.3.0
|
||||||
|
supports-color: 10.0.0
|
||||||
|
typescript: 5.8.3
|
||||||
|
yargs-parser: 21.1.1
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
deep-is: 0.1.4
|
deep-is: 0.1.4
|
||||||
@@ -8265,6 +8357,12 @@ snapshots:
|
|||||||
json-parse-even-better-errors: 2.3.1
|
json-parse-even-better-errors: 2.3.1
|
||||||
lines-and-columns: 1.2.4
|
lines-and-columns: 1.2.4
|
||||||
|
|
||||||
|
parse-json@8.3.0:
|
||||||
|
dependencies:
|
||||||
|
'@babel/code-frame': 7.27.1
|
||||||
|
index-to-position: 1.1.0
|
||||||
|
type-fest: 4.41.0
|
||||||
|
|
||||||
parse5-htmlparser2-tree-adapter@7.1.0:
|
parse5-htmlparser2-tree-adapter@7.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
domhandler: 5.0.3
|
domhandler: 5.0.3
|
||||||
@@ -8321,6 +8419,8 @@ snapshots:
|
|||||||
base64-js: 1.5.1
|
base64-js: 1.5.1
|
||||||
xmlbuilder: 15.1.1
|
xmlbuilder: 15.1.1
|
||||||
|
|
||||||
|
pluralize@8.0.0: {}
|
||||||
|
|
||||||
possible-typed-array-names@1.1.0: {}
|
possible-typed-array-names@1.1.0: {}
|
||||||
|
|
||||||
postcss-js@4.0.1(postcss@8.5.3):
|
postcss-js@4.0.1(postcss@8.5.3):
|
||||||
@@ -8596,7 +8696,7 @@ snapshots:
|
|||||||
|
|
||||||
read-binary-file-arch@1.0.6:
|
read-binary-file-arch@1.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -8636,8 +8736,6 @@ snapshots:
|
|||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
set-function-name: 2.0.2
|
set-function-name: 2.0.2
|
||||||
|
|
||||||
remove-accents@0.5.0: {}
|
|
||||||
|
|
||||||
remove-trailing-separator@1.1.0: {}
|
remove-trailing-separator@1.1.0: {}
|
||||||
|
|
||||||
replace-ext@2.0.0: {}
|
replace-ext@2.0.0: {}
|
||||||
@@ -8966,7 +9064,7 @@ snapshots:
|
|||||||
socks-proxy-agent@7.0.0:
|
socks-proxy-agent@7.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 6.0.2
|
agent-base: 6.0.2
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
socks: 2.8.6
|
socks: 2.8.6
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -9157,7 +9255,7 @@ snapshots:
|
|||||||
cosmiconfig: 9.0.0(typescript@5.8.3)
|
cosmiconfig: 9.0.0(typescript@5.8.3)
|
||||||
css-functions-list: 3.2.3
|
css-functions-list: 3.2.3
|
||||||
css-tree: 3.1.0
|
css-tree: 3.1.0
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
fast-glob: 3.3.3
|
fast-glob: 3.3.3
|
||||||
fastest-levenshtein: 1.0.16
|
fastest-levenshtein: 1.0.16
|
||||||
file-entry-cache: 10.1.1
|
file-entry-cache: 10.1.1
|
||||||
@@ -9195,13 +9293,11 @@ snapshots:
|
|||||||
|
|
||||||
sumchecker@3.0.1:
|
sumchecker@3.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.1
|
debug: 4.4.1(supports-color@10.0.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
superjson@1.13.3:
|
supports-color@10.0.0: {}
|
||||||
dependencies:
|
|
||||||
copy-anything: 3.0.5
|
|
||||||
|
|
||||||
supports-color@7.2.0:
|
supports-color@7.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9421,6 +9517,8 @@ snapshots:
|
|||||||
escalade: 3.2.0
|
escalade: 3.2.0
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
|
|
||||||
|
uri-js-replace@1.0.1: {}
|
||||||
|
|
||||||
uri-js@4.4.1:
|
uri-js@4.4.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
punycode: 2.3.1
|
punycode: 2.3.1
|
||||||
@@ -9529,12 +9627,12 @@ snapshots:
|
|||||||
fast-glob: 3.3.3
|
fast-glob: 3.3.3
|
||||||
magic-string: 0.30.17
|
magic-string: 0.30.17
|
||||||
|
|
||||||
vite-plugin-ejs@1.7.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)):
|
vite-plugin-ejs@1.7.0(vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
ejs: 3.1.10
|
ejs: 3.1.10
|
||||||
vite: 6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)
|
vite: 6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0)
|
||||||
|
|
||||||
vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2):
|
vite@6.3.5(@types/node@22.15.32)(sass-embedded@1.89.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.2)(yaml@2.8.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.4
|
esbuild: 0.25.4
|
||||||
fdir: 6.4.4(picomatch@4.0.2)
|
fdir: 6.4.4(picomatch@4.0.2)
|
||||||
@@ -9548,6 +9646,7 @@ snapshots:
|
|||||||
sass-embedded: 1.89.0
|
sass-embedded: 1.89.0
|
||||||
sugarss: 4.0.1(postcss@8.5.3)
|
sugarss: 4.0.1(postcss@8.5.3)
|
||||||
terser: 5.39.2
|
terser: 5.39.2
|
||||||
|
yaml: 2.8.0
|
||||||
|
|
||||||
void-elements@3.1.0: {}
|
void-elements@3.1.0: {}
|
||||||
|
|
||||||
@@ -9661,6 +9760,11 @@ snapshots:
|
|||||||
|
|
||||||
yallist@4.0.0: {}
|
yallist@4.0.0: {}
|
||||||
|
|
||||||
|
yaml-ast-parser@0.0.43: {}
|
||||||
|
|
||||||
|
yaml@2.8.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
yargs-parser@21.1.1: {}
|
yargs-parser@21.1.1: {}
|
||||||
|
|
||||||
yargs@17.7.2:
|
yargs@17.7.2:
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
plugins: {
|
||||||
'postcss-preset-mantine': {},
|
'postcss-preset-mantine': {
|
||||||
|
mixins: {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -227,7 +227,11 @@
|
|||||||
"songCount": "song count",
|
"songCount": "song count",
|
||||||
"title": "title",
|
"title": "title",
|
||||||
"toYear": "to year",
|
"toYear": "to year",
|
||||||
"trackNumber": "track"
|
"trackNumber": "track",
|
||||||
|
"createdAt": "created at",
|
||||||
|
"updatedAt": "updated at",
|
||||||
|
"type": "type",
|
||||||
|
"email": "email"
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"addServer": {
|
"addServer": {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import axios, { AxiosResponse } from 'axios';
|
import axios, { AxiosResponse } from 'axios';
|
||||||
import { load } from 'cheerio';
|
import { load } from 'cheerio';
|
||||||
|
|
||||||
|
import { orderSearchResults } from './shared';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
InternetProviderLyricResponse,
|
InternetProviderLyricResponse,
|
||||||
InternetProviderLyricSearchResponse,
|
InternetProviderLyricSearchResponse,
|
||||||
LyricSearchQuery,
|
LyricSearchQuery,
|
||||||
LyricSource,
|
LyricSource,
|
||||||
} from '.';
|
} from '/@/shared/types/domain/lyric-domain-types';
|
||||||
import { orderSearchResults } from './shared';
|
|
||||||
|
|
||||||
const SEARCH_URL = 'https://genius.com/api/search/song';
|
const SEARCH_URL = 'https://genius.com/api/search/song';
|
||||||
|
|
||||||
|
|||||||
@@ -17,35 +17,12 @@ import {
|
|||||||
getSearchResults as searchNetease,
|
getSearchResults as searchNetease,
|
||||||
} from './netease';
|
} from './netease';
|
||||||
|
|
||||||
import { Song } from '/@/shared/types/domain-types';
|
import {
|
||||||
|
InternetProviderLyricResponse,
|
||||||
export enum LyricSource {
|
InternetProviderLyricSearchResponse,
|
||||||
GENIUS = 'Genius',
|
LyricSource,
|
||||||
LRCLIB = 'lrclib.net',
|
} from '/@/shared/types/domain/lyric-domain-types';
|
||||||
NETEASE = 'NetEase',
|
import { Song } from '/@/shared/types/domain/song-domain-types';
|
||||||
}
|
|
||||||
|
|
||||||
export type FullLyricsMetadata = Omit<InternetProviderLyricResponse, 'id' | 'lyrics' | 'source'> & {
|
|
||||||
lyrics: LyricsResponse;
|
|
||||||
remote: boolean;
|
|
||||||
source: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type InternetProviderLyricResponse = {
|
|
||||||
artist: string;
|
|
||||||
id: string;
|
|
||||||
lyrics: string;
|
|
||||||
name: string;
|
|
||||||
source: LyricSource;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type InternetProviderLyricSearchResponse = {
|
|
||||||
artist: string;
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
score?: number;
|
|
||||||
source: LyricSource;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type LyricGetQuery = {
|
export type LyricGetQuery = {
|
||||||
remoteSongId: string;
|
remoteSongId: string;
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
// Credits to https://github.com/tranxuanthang/lrcget for API implementation
|
// Credits to https://github.com/tranxuanthang/lrcget for API implementation
|
||||||
import axios, { AxiosResponse } from 'axios';
|
import axios, { AxiosResponse } from 'axios';
|
||||||
|
|
||||||
|
import { orderSearchResults } from './shared';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
InternetProviderLyricResponse,
|
InternetProviderLyricResponse,
|
||||||
InternetProviderLyricSearchResponse,
|
InternetProviderLyricSearchResponse,
|
||||||
LyricSearchQuery,
|
LyricSearchQuery,
|
||||||
LyricSource,
|
LyricSource,
|
||||||
} from '.';
|
} from '/@/shared/types/domain/lyric-domain-types';
|
||||||
import { orderSearchResults } from './shared';
|
|
||||||
|
|
||||||
const FETCH_URL = 'https://lrclib.net/api/get';
|
const FETCH_URL = 'https://lrclib.net/api/get';
|
||||||
const SEEARCH_URL = 'https://lrclib.net/api/search';
|
const SEEARCH_URL = 'https://lrclib.net/api/search';
|
||||||
|
|||||||
@@ -1,43 +1,20 @@
|
|||||||
import axios, { AxiosResponse } from 'axios';
|
import axios, { AxiosResponse } from 'axios';
|
||||||
|
|
||||||
|
import { store } from '../settings';
|
||||||
|
import { orderSearchResults } from './shared';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
InternetProviderLyricResponse,
|
InternetProviderLyricResponse,
|
||||||
InternetProviderLyricSearchResponse,
|
InternetProviderLyricSearchResponse,
|
||||||
LyricSearchQuery,
|
LyricSearchQuery,
|
||||||
LyricSource,
|
LyricSource,
|
||||||
} from '.';
|
} from '/@/shared/types/domain/lyric-domain-types';
|
||||||
import { store } from '../settings';
|
|
||||||
import { orderSearchResults } from './shared';
|
|
||||||
|
|
||||||
const SEARCH_URL = 'https://music.163.com/api/search/get';
|
const SEARCH_URL = 'https://music.163.com/api/search/get';
|
||||||
const LYRICS_URL = 'https://music.163.com/api/song/lyric';
|
const LYRICS_URL = 'https://music.163.com/api/song/lyric';
|
||||||
|
|
||||||
// Adapted from https://github.com/NyaomiDEV/Sunamu/blob/master/src/main/lyricproviders/netease.ts
|
// Adapted from https://github.com/NyaomiDEV/Sunamu/blob/master/src/main/lyricproviders/netease.ts
|
||||||
|
|
||||||
export interface Result {
|
|
||||||
hasMore: boolean;
|
|
||||||
songCount: number;
|
|
||||||
songs: Song[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Song {
|
|
||||||
album: Album;
|
|
||||||
alias: string[];
|
|
||||||
artists: Artist[];
|
|
||||||
copyrightId: number;
|
|
||||||
duration: number;
|
|
||||||
fee: number;
|
|
||||||
ftype: number;
|
|
||||||
id: number;
|
|
||||||
mark: number;
|
|
||||||
mvid: number;
|
|
||||||
name: string;
|
|
||||||
rtype: number;
|
|
||||||
rUrl: null;
|
|
||||||
status: number;
|
|
||||||
transNames?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Album {
|
interface Album {
|
||||||
artist: Artist;
|
artist: Artist;
|
||||||
copyrightId: number;
|
copyrightId: number;
|
||||||
@@ -69,6 +46,30 @@ interface NetEaseResponse {
|
|||||||
result: Result;
|
result: Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Result {
|
||||||
|
hasMore: boolean;
|
||||||
|
songCount: number;
|
||||||
|
songs: Song[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Song {
|
||||||
|
album: Album;
|
||||||
|
alias: string[];
|
||||||
|
artists: Artist[];
|
||||||
|
copyrightId: number;
|
||||||
|
duration: number;
|
||||||
|
fee: number;
|
||||||
|
ftype: number;
|
||||||
|
id: number;
|
||||||
|
mark: number;
|
||||||
|
mvid: number;
|
||||||
|
name: string;
|
||||||
|
rtype: number;
|
||||||
|
rUrl: null;
|
||||||
|
status: number;
|
||||||
|
transNames?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export async function getLyricsBySongId(songId: string): Promise<null | string> {
|
export async function getLyricsBySongId(songId: string): Promise<null | string> {
|
||||||
let result: AxiosResponse<any, any>;
|
let result: AxiosResponse<any, any>;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import Fuse from 'fuse.js';
|
import Fuse from 'fuse.js';
|
||||||
|
|
||||||
import {
|
import { InternetProviderLyricSearchResponse } from '/@/shared/types/domain/lyric-domain-types';
|
||||||
InternetProviderLyricSearchResponse,
|
import { LyricSearchQuery } from '/@/shared/types/domain/lyric-domain-types';
|
||||||
LyricSearchQuery,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
export const orderSearchResults = (args: {
|
export const orderSearchResults = (args: {
|
||||||
params: LyricSearchQuery;
|
params: LyricSearchQuery;
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import manifest from './manifest.json';
|
|||||||
|
|
||||||
import { getMainWindow } from '/@/main/index';
|
import { getMainWindow } from '/@/main/index';
|
||||||
import { isLinux } from '/@/main/utils';
|
import { isLinux } from '/@/main/utils';
|
||||||
import { QueueSong } from '/@/shared/types/domain-types';
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
import { ClientEvent, ServerEvent } from '/@/shared/types/remote-types';
|
import { ClientEvent, ServerEvent } from '/@/shared/types/domain/remote-types';
|
||||||
import { PlayerRepeat, PlayerStatus, SongState } from '/@/shared/types/types';
|
import { PlayerRepeat, PlayerStatus, SongState } from '/@/shared/types/types';
|
||||||
|
|
||||||
let mprisPlayer: any | undefined;
|
let mprisPlayer: any | undefined;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ipcMain } from 'electron';
|
|||||||
import Player from 'mpris-service';
|
import Player from 'mpris-service';
|
||||||
|
|
||||||
import { getMainWindow } from '/@/main/index';
|
import { getMainWindow } from '/@/main/index';
|
||||||
import { QueueSong } from '/@/shared/types/domain-types';
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
import { PlayerRepeat, PlayerStatus } from '/@/shared/types/types';
|
import { PlayerRepeat, PlayerStatus } from '/@/shared/types/types';
|
||||||
|
|
||||||
const mprisPlayer = Player({
|
const mprisPlayer = Player({
|
||||||
@@ -168,7 +168,7 @@ ipcMain.on('update-song', (_event, song: QueueSong | undefined) => {
|
|||||||
'xesam:contentCreated': song.releaseDate,
|
'xesam:contentCreated': song.releaseDate,
|
||||||
'xesam:discNumber': song.discNumber ? song.discNumber : null,
|
'xesam:discNumber': song.discNumber ? song.discNumber : null,
|
||||||
'xesam:genre': song.genres?.length ? song.genres.map((genre: any) => genre.name) : null,
|
'xesam:genre': song.genres?.length ? song.genres.map((genre: any) => genre.name) : null,
|
||||||
'xesam:lastUsed': song.lastPlayedAt,
|
'xesam:lastUsed': song.userLastPlayedDate,
|
||||||
'xesam:title': song.name || null,
|
'xesam:title': song.name || null,
|
||||||
'xesam:trackNumber': song.trackNumber ? song.trackNumber : null,
|
'xesam:trackNumber': song.trackNumber ? song.trackNumber : null,
|
||||||
'xesam:useCount':
|
'xesam:useCount':
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
LyricSource,
|
LyricSource,
|
||||||
} from '../main/features/core/lyrics';
|
} from '../main/features/core/lyrics';
|
||||||
|
|
||||||
import { QueueSong } from '/@/shared/types/domain-types';
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
|
|
||||||
const getRemoteLyricsBySong = (song: QueueSong) => {
|
const getRemoteLyricsBySong = (song: QueueSong) => {
|
||||||
const result = ipcRenderer.invoke('lyric-by-song', song);
|
const result = ipcRenderer.invoke('lyric-by-song', song);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ipcRenderer, IpcRendererEvent } from 'electron';
|
import { ipcRenderer, IpcRendererEvent } from 'electron';
|
||||||
|
|
||||||
import { PlayerData } from '/@/shared/types/domain-types';
|
import { PlayerData } from '/@/shared/types/domain/player-domain-types';
|
||||||
|
|
||||||
const initialize = (data: { extraParameters?: string[]; properties?: Record<string, any> }) => {
|
const initialize = (data: { extraParameters?: string[]; properties?: Record<string, any> }) => {
|
||||||
return ipcRenderer.invoke('player-initialize', data);
|
return ipcRenderer.invoke('player-initialize', data);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ipcRenderer, IpcRendererEvent } from 'electron';
|
import { ipcRenderer, IpcRendererEvent } from 'electron';
|
||||||
|
|
||||||
import { QueueSong } from '/@/shared/types/domain-types';
|
import { QueueSong, QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
import { PlayerStatus } from '/@/shared/types/types';
|
import { PlayerStatus } from '/@/shared/types/types';
|
||||||
|
|
||||||
const requestFavorite = (
|
const requestFavorite = (
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
import {
|
||||||
|
ApiController,
|
||||||
|
ApiControllerError,
|
||||||
|
ApiControllerFn,
|
||||||
|
} from '/@/shared/types/adapter/api-controller-types';
|
||||||
|
import { ServerListItem } from '/@/shared/types/domain/server-domain-types';
|
||||||
|
import { logger } from '/@/shared/utils/logger';
|
||||||
|
|
||||||
|
export interface LoggingOptions {
|
||||||
|
logErrors?: boolean;
|
||||||
|
logPerformance?: boolean;
|
||||||
|
logRequests?: boolean;
|
||||||
|
logResponses?: boolean;
|
||||||
|
maxRequestSize?: number;
|
||||||
|
maxResponseSize?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoggedApiControllerFn<TRequest, TResponse> = (
|
||||||
|
request: TRequest,
|
||||||
|
server: ServerListItem,
|
||||||
|
options?: any,
|
||||||
|
) => Promise<[ApiControllerError, null] | [null, TResponse]>;
|
||||||
|
|
||||||
|
export function createLoggedApiController(
|
||||||
|
controller: ApiController,
|
||||||
|
options: LoggingOptions = {},
|
||||||
|
): ApiController {
|
||||||
|
const loggedController: any = {};
|
||||||
|
|
||||||
|
// Log utility functions
|
||||||
|
loggedController._utility = createLoggedUtility(controller._utility);
|
||||||
|
|
||||||
|
// Log all controller methods
|
||||||
|
for (const [sectionKey, section] of Object.entries(controller)) {
|
||||||
|
if (sectionKey === '_utility') continue;
|
||||||
|
|
||||||
|
loggedController[sectionKey] = {};
|
||||||
|
|
||||||
|
for (const [methodKey, method] of Object.entries(section as Record<string, any>)) {
|
||||||
|
if (typeof method === 'function') {
|
||||||
|
const functionName = `${sectionKey}.${methodKey}`;
|
||||||
|
|
||||||
|
if (methodKey === 'authenticate' || methodKey === 'getType') {
|
||||||
|
// Special handling for non-standard API functions
|
||||||
|
loggedController[sectionKey][methodKey] = (...args: any[]) => {
|
||||||
|
logger.info(`[API] ${functionName} called`, {
|
||||||
|
args: JSON.stringify(args, null, 2),
|
||||||
|
});
|
||||||
|
return method(...args);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
loggedController[sectionKey][methodKey] = createLoggedFunction(
|
||||||
|
method as ApiControllerFn<any, any>,
|
||||||
|
functionName,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loggedController[sectionKey][methodKey] = method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return loggedController as ApiController;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLoggedFunction<TRequest, TResponse>(
|
||||||
|
originalFn: ApiControllerFn<TRequest, TResponse> | undefined,
|
||||||
|
functionName: string,
|
||||||
|
options: LoggingOptions = {},
|
||||||
|
): LoggedApiControllerFn<TRequest, TResponse> | undefined {
|
||||||
|
if (!originalFn) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return async (request: TRequest, requestOptions?: any) => {
|
||||||
|
const startTime = Date.now();
|
||||||
|
const requestId = Math.random().toString(36).substring(2, 15);
|
||||||
|
|
||||||
|
const {
|
||||||
|
logErrors = true,
|
||||||
|
logPerformance = true,
|
||||||
|
logRequests = true,
|
||||||
|
logResponses = true,
|
||||||
|
maxRequestSize = 1000,
|
||||||
|
maxResponseSize = 1000,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
if (logRequests) {
|
||||||
|
const requestStr = JSON.stringify(request, null, 2);
|
||||||
|
const truncatedRequest =
|
||||||
|
requestStr.length > maxRequestSize
|
||||||
|
? requestStr.substring(0, maxRequestSize) + '...'
|
||||||
|
: requestStr;
|
||||||
|
|
||||||
|
logger.info(`[API] ${functionName} called`, {
|
||||||
|
request: truncatedRequest,
|
||||||
|
requestId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await originalFn(request, requestOptions);
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
|
||||||
|
if (result[0]) {
|
||||||
|
// Error response
|
||||||
|
if (logErrors) {
|
||||||
|
const error = result[0] as ApiControllerError;
|
||||||
|
logger.error(`[API] ${functionName} failed`, {
|
||||||
|
duration: logPerformance ? `${duration}ms` : undefined,
|
||||||
|
error: {
|
||||||
|
code: error.code,
|
||||||
|
message: error.message,
|
||||||
|
},
|
||||||
|
requestId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Success response
|
||||||
|
if (logResponses) {
|
||||||
|
const response = result[1];
|
||||||
|
const responseStr = JSON.stringify(response);
|
||||||
|
const truncatedResponse =
|
||||||
|
responseStr.length > maxResponseSize
|
||||||
|
? responseStr.substring(0, maxResponseSize) + '...'
|
||||||
|
: responseStr;
|
||||||
|
|
||||||
|
logger.info(`[API] ${functionName} succeeded`, {
|
||||||
|
duration: logPerformance ? `${duration}ms` : undefined,
|
||||||
|
requestId,
|
||||||
|
response: truncatedResponse,
|
||||||
|
responseSize: responseStr.length,
|
||||||
|
responseType: typeof response,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
if (logErrors) {
|
||||||
|
logger.error(`[API] ${functionName} threw exception`, {
|
||||||
|
duration: logPerformance ? `${duration}ms` : undefined,
|
||||||
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
requestId,
|
||||||
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLoggedUtility<T extends Record<string, any>>(utility: T): T {
|
||||||
|
const loggedUtility: any = {};
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(utility)) {
|
||||||
|
if (typeof value === 'function') {
|
||||||
|
loggedUtility[key] = (...args: any[]) => {
|
||||||
|
logger.debug(`[API] _utility.${key} called`, {
|
||||||
|
args: JSON.stringify(args, null, 2),
|
||||||
|
});
|
||||||
|
return value(...args);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
loggedUtility[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return loggedUtility as T;
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import { createLoggedApiController } from '/@/renderer/api/api-controller-logger';
|
||||||
|
import { useAuthStore } from '/@/renderer/store';
|
||||||
|
import {
|
||||||
|
createApiClient as subsonicApiClient,
|
||||||
|
authenticate as subsonicAuthenticate,
|
||||||
|
controller as subsonicController,
|
||||||
|
middleware as subsonicMiddleware,
|
||||||
|
} from '/@/shared/api/subsonic/subsonic-controller';
|
||||||
|
import { ApiController } from '/@/shared/types/adapter/api-controller-types';
|
||||||
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
|
|
||||||
|
export const serverApiMap = {
|
||||||
|
[ServerType.JELLYFIN]: {
|
||||||
|
apiClient: null,
|
||||||
|
authenticate: null,
|
||||||
|
controller: {},
|
||||||
|
middleware: null,
|
||||||
|
},
|
||||||
|
[ServerType.NAVIDROME]: {
|
||||||
|
apiClient: null,
|
||||||
|
authenticate: null,
|
||||||
|
controller: {},
|
||||||
|
middleware: null,
|
||||||
|
},
|
||||||
|
[ServerType.SUBSONIC]: {
|
||||||
|
apiClient: subsonicApiClient,
|
||||||
|
authenticate: subsonicAuthenticate,
|
||||||
|
controller: subsonicController,
|
||||||
|
middleware: subsonicMiddleware,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const getApiByServer = (serverId: string): ApiController => {
|
||||||
|
const servers = useAuthStore.getState().serverList;
|
||||||
|
const server = servers[serverId];
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
throw new Error('No server or api client selected');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { apiClient, controller, middleware } = serverApiMap[server.type];
|
||||||
|
|
||||||
|
if (!apiClient) {
|
||||||
|
throw new Error('No api client found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = apiClient(server, middleware);
|
||||||
|
|
||||||
|
return createLoggedApiController(controller(client, server));
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAppApi = () => {
|
||||||
|
const servers = useAuthStore.getState().serverList;
|
||||||
|
|
||||||
|
return Object.entries(servers).reduce(
|
||||||
|
(acc, [id]) => {
|
||||||
|
acc[id] = getApiByServer(id);
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<string, ApiController>,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const api = {
|
||||||
|
authenticate: (serverType: ServerType) => {
|
||||||
|
const { authenticate } = serverApiMap[serverType];
|
||||||
|
|
||||||
|
if (!serverType || !authenticate) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return authenticate;
|
||||||
|
},
|
||||||
|
controller: getAppApi(),
|
||||||
|
};
|
||||||
@@ -4,11 +4,9 @@ import { NavidromeController } from '/@/renderer/api/navidrome/navidrome-control
|
|||||||
import { SubsonicController } from '/@/renderer/api/subsonic/subsonic-controller';
|
import { SubsonicController } from '/@/renderer/api/subsonic/subsonic-controller';
|
||||||
import { useAuthStore } from '/@/renderer/store';
|
import { useAuthStore } from '/@/renderer/store';
|
||||||
import { toast } from '/@/shared/components/toast/toast';
|
import { toast } from '/@/shared/components/toast/toast';
|
||||||
import {
|
import { ControllerEndpoint } from '/@/shared/types/domain/api-domain-types';
|
||||||
AuthenticationResponse,
|
import { AuthenticationResponse } from '/@/shared/types/domain/auth-domain-types';
|
||||||
ControllerEndpoint,
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
ServerType,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
type ApiController = {
|
type ApiController = {
|
||||||
jellyfin: ControllerEndpoint;
|
jellyfin: ControllerEndpoint;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { authenticationFailure } from '/@/renderer/api/utils';
|
|||||||
import { useAuthStore } from '/@/renderer/store';
|
import { useAuthStore } from '/@/renderer/store';
|
||||||
import { jfType } from '/@/shared/api/jellyfin/jellyfin-types';
|
import { jfType } from '/@/shared/api/jellyfin/jellyfin-types';
|
||||||
import { getClientType } from '/@/shared/api/utils';
|
import { getClientType } from '/@/shared/api/utils';
|
||||||
import { ServerListItem } from '/@/shared/types/domain-types';
|
import { ServerListItem } from '/@/shared/types/domain/server-domain-types';
|
||||||
|
|
||||||
const c = initContract();
|
const c = initContract();
|
||||||
|
|
||||||
|
|||||||
@@ -6,19 +6,13 @@ import { JFSongListSort, JFSortOrder } from '/@/shared/api/jellyfin.types';
|
|||||||
import { jfNormalize } from '/@/shared/api/jellyfin/jellyfin-normalize';
|
import { jfNormalize } from '/@/shared/api/jellyfin/jellyfin-normalize';
|
||||||
import { jfType } from '/@/shared/api/jellyfin/jellyfin-types';
|
import { jfType } from '/@/shared/api/jellyfin/jellyfin-types';
|
||||||
import { getFeatures, hasFeature, VersionInfo } from '/@/shared/api/utils';
|
import { getFeatures, hasFeature, VersionInfo } from '/@/shared/api/utils';
|
||||||
import {
|
import { albumListSortMap } from '/@/shared/types/domain/album-domain-types';
|
||||||
albumArtistListSortMap,
|
import { ControllerEndpoint } from '/@/shared/types/domain/api-domain-types';
|
||||||
albumListSortMap,
|
import { albumArtistListSortMap } from '/@/shared/types/domain/artist-domain-types';
|
||||||
ControllerEndpoint,
|
import { Played } from '/@/shared/types/domain/player-domain-types';
|
||||||
genreListSortMap,
|
import { ServerFeature } from '/@/shared/types/domain/server-domain-types';
|
||||||
LibraryItem,
|
import { LibraryItem, sortOrderMap } from '/@/shared/types/domain/shared-domain-types';
|
||||||
Played,
|
import { Song, songListSortMap } from '/@/shared/types/domain/song-domain-types';
|
||||||
playlistListSortMap,
|
|
||||||
Song,
|
|
||||||
songListSortMap,
|
|
||||||
sortOrderMap,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { ServerFeature } from '/@/shared/types/features-types';
|
|
||||||
|
|
||||||
const formatCommaDelimitedString = (value: string[]) => {
|
const formatCommaDelimitedString = (value: string[]) => {
|
||||||
return value.join(',');
|
return value.join(',');
|
||||||
@@ -326,7 +320,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
SearchTerm: query.searchTerm,
|
SearchTerm: query.searchTerm,
|
||||||
SortBy: albumListSortMap.jellyfin[query.sortBy] || 'SortName',
|
SortBy: albumListSortMap.jellyfin[query.sortBy] || 'SortName',
|
||||||
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
||||||
StartIndex: query.startIndex,
|
StartIndex: query.offset,
|
||||||
...query._custom?.jellyfin,
|
...query._custom?.jellyfin,
|
||||||
Years: yearsFilter,
|
Years: yearsFilter,
|
||||||
},
|
},
|
||||||
@@ -338,14 +332,14 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.Items.map((item) => jfNormalize.album(item, apiClientProps.server)),
|
items: res.body.Items.map((item) => jfNormalize.album(item, apiClientProps.server)),
|
||||||
startIndex: query.startIndex,
|
offset: query.offset,
|
||||||
totalRecordCount: res.body.TotalRecordCount,
|
totalRecordCount: res.body.TotalRecordCount,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getAlbumListCount: async ({ apiClientProps, query }) =>
|
getAlbumListCount: async ({ apiClientProps, query }) =>
|
||||||
JellyfinController.getAlbumList({
|
JellyfinController.getAlbumList({
|
||||||
apiClientProps,
|
apiClientProps,
|
||||||
query: { ...query, limit: 1, startIndex: 0 },
|
query: { ...query, limit: 1, offset: 0 },
|
||||||
}).then((result) => result!.totalRecordCount!),
|
}).then((result) => result!.totalRecordCount!),
|
||||||
getArtistList: async (args) => {
|
getArtistList: async (args) => {
|
||||||
const { apiClientProps, query } = args;
|
const { apiClientProps, query } = args;
|
||||||
@@ -360,7 +354,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
SearchTerm: query.searchTerm,
|
SearchTerm: query.searchTerm,
|
||||||
SortBy: albumArtistListSortMap.jellyfin[query.sortBy] || 'SortName,Name',
|
SortBy: albumArtistListSortMap.jellyfin[query.sortBy] || 'SortName,Name',
|
||||||
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
||||||
StartIndex: query.startIndex,
|
StartIndex: query.offset,
|
||||||
UserId: apiClientProps.server?.userId || undefined,
|
UserId: apiClientProps.server?.userId || undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -373,14 +367,14 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
items: res.body.Items.map((item) =>
|
items: res.body.Items.map((item) =>
|
||||||
jfNormalize.albumArtist(item, apiClientProps.server),
|
jfNormalize.albumArtist(item, apiClientProps.server),
|
||||||
),
|
),
|
||||||
startIndex: query.startIndex,
|
offset: query.offset,
|
||||||
totalRecordCount: res.body.TotalRecordCount,
|
totalRecordCount: res.body.TotalRecordCount,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getArtistListCount: async ({ apiClientProps, query }) =>
|
getArtistListCount: async ({ apiClientProps, query }) =>
|
||||||
JellyfinController.getArtistList({
|
JellyfinController.getArtistList({
|
||||||
apiClientProps,
|
apiClientProps,
|
||||||
query: { ...query, limit: 1, startIndex: 0 },
|
query: { ...query, limit: 1, offset: 0 },
|
||||||
}).then((result) => result!.totalRecordCount!),
|
}).then((result) => result!.totalRecordCount!),
|
||||||
getDownloadUrl: (args) => {
|
getDownloadUrl: (args) => {
|
||||||
const { apiClientProps, query } = args;
|
const { apiClientProps, query } = args;
|
||||||
@@ -402,7 +396,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
SearchTerm: query?.searchTerm,
|
SearchTerm: query?.searchTerm,
|
||||||
SortBy: genreListSortMap.jellyfin[query.sortBy] || 'SortName',
|
SortBy: genreListSortMap.jellyfin[query.sortBy] || 'SortName',
|
||||||
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
||||||
StartIndex: query.startIndex,
|
StartIndex: query.offset,
|
||||||
UserId: apiClientProps.server?.userId,
|
UserId: apiClientProps.server?.userId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -413,7 +407,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.Items.map((item) => jfNormalize.genre(item, apiClientProps.server)),
|
items: res.body.Items.map((item) => jfNormalize.genre(item, apiClientProps.server)),
|
||||||
startIndex: query.startIndex || 0,
|
offset: query.offset || 0,
|
||||||
totalRecordCount: res.body?.TotalRecordCount || 0,
|
totalRecordCount: res.body?.TotalRecordCount || 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -462,7 +456,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: musicFolders.map(jfNormalize.musicFolder),
|
items: musicFolders.map(jfNormalize.musicFolder),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: musicFolders?.length || 0,
|
totalRecordCount: musicFolders?.length || 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -509,7 +503,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
SearchTerm: query.searchTerm,
|
SearchTerm: query.searchTerm,
|
||||||
SortBy: playlistListSortMap.jellyfin[query.sortBy],
|
SortBy: playlistListSortMap.jellyfin[query.sortBy],
|
||||||
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
||||||
StartIndex: query.startIndex,
|
StartIndex: query.offset,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -519,14 +513,14 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.Items.map((item) => jfNormalize.playlist(item, apiClientProps.server)),
|
items: res.body.Items.map((item) => jfNormalize.playlist(item, apiClientProps.server)),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: res.body.TotalRecordCount,
|
totalRecordCount: res.body.TotalRecordCount,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getPlaylistListCount: async ({ apiClientProps, query }) =>
|
getPlaylistListCount: async ({ apiClientProps, query }) =>
|
||||||
JellyfinController.getPlaylistList({
|
JellyfinController.getPlaylistList({
|
||||||
apiClientProps,
|
apiClientProps,
|
||||||
query: { ...query, limit: 1, startIndex: 0 },
|
query: { ...query, limit: 1, offset: 0 },
|
||||||
}).then((result) => result!.totalRecordCount!),
|
}).then((result) => result!.totalRecordCount!),
|
||||||
getPlaylistSongList: async (args) => {
|
getPlaylistSongList: async (args) => {
|
||||||
const { apiClientProps, query } = args;
|
const { apiClientProps, query } = args;
|
||||||
@@ -556,7 +550,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.Items.map((item) => jfNormalize.song(item, apiClientProps.server, '')),
|
items: res.body.Items.map((item) => jfNormalize.song(item, apiClientProps.server, '')),
|
||||||
startIndex: query.startIndex,
|
offset: query.startIndex,
|
||||||
totalRecordCount: res.body.TotalRecordCount,
|
totalRecordCount: res.body.TotalRecordCount,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -606,7 +600,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.Items.map((item) => jfNormalize.song(item, apiClientProps.server, '')),
|
items: res.body.Items.map((item) => jfNormalize.song(item, apiClientProps.server, '')),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: res.body.Items.length || 0,
|
totalRecordCount: res.body.Items.length || 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -746,7 +740,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
SearchTerm: query.searchTerm,
|
SearchTerm: query.searchTerm,
|
||||||
SortBy: songListSortMap.jellyfin[query.sortBy] || 'Album,SortName',
|
SortBy: songListSortMap.jellyfin[query.sortBy] || 'Album,SortName',
|
||||||
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
||||||
StartIndex: query.startIndex,
|
StartIndex: query.offset,
|
||||||
...query._custom?.jellyfin,
|
...query._custom?.jellyfin,
|
||||||
Years: yearsFilter,
|
Years: yearsFilter,
|
||||||
},
|
},
|
||||||
@@ -781,7 +775,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
SearchTerm: query.searchTerm,
|
SearchTerm: query.searchTerm,
|
||||||
SortBy: songListSortMap.jellyfin[query.sortBy] || 'Album,SortName',
|
SortBy: songListSortMap.jellyfin[query.sortBy] || 'Album,SortName',
|
||||||
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
SortOrder: sortOrderMap.jellyfin[query.sortOrder],
|
||||||
StartIndex: query.startIndex,
|
StartIndex: query.offset,
|
||||||
...query._custom?.jellyfin,
|
...query._custom?.jellyfin,
|
||||||
Years: yearsFilter,
|
Years: yearsFilter,
|
||||||
},
|
},
|
||||||
@@ -810,14 +804,14 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
items: items.map((item) =>
|
items: items.map((item) =>
|
||||||
jfNormalize.song(item, apiClientProps.server, '', query.imageSize),
|
jfNormalize.song(item, apiClientProps.server, '', query.imageSize),
|
||||||
),
|
),
|
||||||
startIndex: query.startIndex,
|
offset: query.offset,
|
||||||
totalRecordCount,
|
totalRecordCount,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getSongListCount: async ({ apiClientProps, query }) =>
|
getSongListCount: async ({ apiClientProps, query }) =>
|
||||||
JellyfinController.getSongList({
|
JellyfinController.getSongList({
|
||||||
apiClientProps,
|
apiClientProps,
|
||||||
query: { ...query, limit: 1, startIndex: 0 },
|
query: { ...query, limit: 1, offset: 0 },
|
||||||
}).then((result) => result!.totalRecordCount!),
|
}).then((result) => result!.totalRecordCount!),
|
||||||
getTags: async (args) => {
|
getTags: async (args) => {
|
||||||
const { apiClientProps, query } = args;
|
const { apiClientProps, query } = args;
|
||||||
@@ -873,7 +867,7 @@ export const JellyfinController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.Items.map((item) => jfNormalize.song(item, apiClientProps.server, '')),
|
items: res.body.Items.map((item) => jfNormalize.song(item, apiClientProps.server, '')),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: res.body.TotalRecordCount,
|
totalRecordCount: res.body.TotalRecordCount,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { useAuthStore } from '/@/renderer/store';
|
|||||||
import { ndType } from '/@/shared/api/navidrome/navidrome-types';
|
import { ndType } from '/@/shared/api/navidrome/navidrome-types';
|
||||||
import { resultWithHeaders } from '/@/shared/api/utils';
|
import { resultWithHeaders } from '/@/shared/api/utils';
|
||||||
import { toast } from '/@/shared/components/toast/toast';
|
import { toast } from '/@/shared/components/toast/toast';
|
||||||
import { ServerListItem } from '/@/shared/types/domain-types';
|
import { ServerListItem } from '/@/shared/types/domain/server-domain-types';
|
||||||
|
|
||||||
const localSettings = isElectron() ? window.api.localSettings : null;
|
const localSettings = isElectron() ? window.api.localSettings : null;
|
||||||
|
|
||||||
|
|||||||
@@ -4,25 +4,24 @@ import { SubsonicController } from '/@/renderer/api/subsonic/subsonic-controller
|
|||||||
import { NDSongListSort } from '/@/shared/api/navidrome.types';
|
import { NDSongListSort } from '/@/shared/api/navidrome.types';
|
||||||
import { ndNormalize } from '/@/shared/api/navidrome/navidrome-normalize';
|
import { ndNormalize } from '/@/shared/api/navidrome/navidrome-normalize';
|
||||||
import { ndType } from '/@/shared/api/navidrome/navidrome-types';
|
import { ndType } from '/@/shared/api/navidrome/navidrome-types';
|
||||||
import { ssNormalize } from '/@/shared/api/subsonic/subsonic-normalize';
|
import { normalize } from '/@/shared/api/subsonic/subsonic-normalize';
|
||||||
import { SubsonicExtensions } from '/@/shared/api/subsonic/subsonic-types';
|
import { SubsonicExtensions } from '/@/shared/api/subsonic/subsonic-types';
|
||||||
import { getFeatures, hasFeature, VersionInfo } from '/@/shared/api/utils';
|
import { getFeatures, hasFeature, VersionInfo } from '/@/shared/api/utils';
|
||||||
|
import { albumListSortMap } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
import { ControllerEndpoint } from '/@/shared/types/domain/api-domain-types';
|
||||||
|
import { albumArtistListSortMap } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
import { AuthenticationResponse } from '/@/shared/types/domain/auth-domain-types';
|
||||||
import {
|
import {
|
||||||
albumArtistListSortMap,
|
PlaylistSongListRequest,
|
||||||
albumListSortMap,
|
|
||||||
AuthenticationResponse,
|
|
||||||
ControllerEndpoint,
|
|
||||||
genreListSortMap,
|
|
||||||
playlistListSortMap,
|
|
||||||
PlaylistSongListArgs,
|
|
||||||
PlaylistSongListResponse,
|
PlaylistSongListResponse,
|
||||||
|
} from '/@/shared/types/domain/playlist-domain-types';
|
||||||
|
import {
|
||||||
|
ServerFeature,
|
||||||
|
ServerFeatures,
|
||||||
ServerListItem,
|
ServerListItem,
|
||||||
Song,
|
} from '/@/shared/types/domain/server-domain-types';
|
||||||
songListSortMap,
|
import { sortOrderMap } from '/@/shared/types/domain/shared-domain-types';
|
||||||
sortOrderMap,
|
import { Song, songListSortMap } from '/@/shared/types/domain/song-domain-types';
|
||||||
userListSortMap,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { ServerFeature, ServerFeatures } from '/@/shared/types/features-types';
|
|
||||||
|
|
||||||
const VERSION_INFO: VersionInfo = [
|
const VERSION_INFO: VersionInfo = [
|
||||||
['0.55.0', { [ServerFeature.BFR]: [1] }],
|
['0.55.0', { [ServerFeature.BFR]: [1] }],
|
||||||
@@ -271,10 +270,10 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
const res = await ndApiClient(apiClientProps).getAlbumList({
|
const res = await ndApiClient(apiClientProps).getAlbumList({
|
||||||
query: {
|
query: {
|
||||||
_end: query.startIndex + (query.limit || 0),
|
_end: query.offset + (query.limit || 0),
|
||||||
_order: sortOrderMap.navidrome[query.sortOrder],
|
_order: sortOrderMap.navidrome[query.sortOrder],
|
||||||
_sort: albumListSortMap.navidrome[query.sortBy],
|
_sort: albumListSortMap.navidrome[query.sortBy],
|
||||||
_start: query.startIndex,
|
_start: query.offset,
|
||||||
artist_id: query.artistIds?.[0],
|
artist_id: query.artistIds?.[0],
|
||||||
compilation: query.compilation,
|
compilation: query.compilation,
|
||||||
genre_id: query.genres?.[0],
|
genre_id: query.genres?.[0],
|
||||||
@@ -291,24 +290,24 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.data.map((album) => ndNormalize.album(album, apiClientProps.server)),
|
items: res.body.data.map((album) => ndNormalize.album(album, apiClientProps.server)),
|
||||||
startIndex: query?.startIndex || 0,
|
offset: query?.offset || 0,
|
||||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getAlbumListCount: async ({ apiClientProps, query }) =>
|
getAlbumListCount: async ({ apiClientProps, query }) =>
|
||||||
NavidromeController.getAlbumList({
|
NavidromeController.getAlbumList({
|
||||||
apiClientProps,
|
apiClientProps,
|
||||||
query: { ...query, limit: 1, startIndex: 0 },
|
query: { ...query, limit: 1, offset: 0 },
|
||||||
}).then((result) => result!.totalRecordCount!),
|
}).then((result) => result!.totalRecordCount!),
|
||||||
getArtistList: async (args) => {
|
getArtistList: async (args) => {
|
||||||
const { apiClientProps, query } = args;
|
const { apiClientProps, query } = args;
|
||||||
|
|
||||||
const res = await ndApiClient(apiClientProps).getAlbumArtistList({
|
const res = await ndApiClient(apiClientProps).getAlbumArtistList({
|
||||||
query: {
|
query: {
|
||||||
_end: query.startIndex + (query.limit || 0),
|
_end: query.offset + (query.limit || 0),
|
||||||
_order: sortOrderMap.navidrome[query.sortOrder],
|
_order: sortOrderMap.navidrome[query.sortOrder],
|
||||||
_sort: albumArtistListSortMap.navidrome[query.sortBy],
|
_sort: albumArtistListSortMap.navidrome[query.sortBy],
|
||||||
_start: query.startIndex,
|
_start: query.offset,
|
||||||
name: query.searchTerm,
|
name: query.searchTerm,
|
||||||
...query._custom?.navidrome,
|
...query._custom?.navidrome,
|
||||||
role: query.role || undefined,
|
role: query.role || undefined,
|
||||||
@@ -333,14 +332,14 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
apiClientProps.server,
|
apiClientProps.server,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
startIndex: query.startIndex,
|
offset: query.offset,
|
||||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getArtistListCount: async ({ apiClientProps, query }) =>
|
getArtistListCount: async ({ apiClientProps, query }) =>
|
||||||
NavidromeController.getArtistList({
|
NavidromeController.getArtistList({
|
||||||
apiClientProps,
|
apiClientProps,
|
||||||
query: { ...query, limit: 1, startIndex: 0 },
|
query: { ...query, limit: 1, offset: 0 },
|
||||||
}).then((result) => result!.totalRecordCount!),
|
}).then((result) => result!.totalRecordCount!),
|
||||||
getDownloadUrl: SubsonicController.getDownloadUrl,
|
getDownloadUrl: SubsonicController.getDownloadUrl,
|
||||||
getGenreList: async (args) => {
|
getGenreList: async (args) => {
|
||||||
@@ -348,10 +347,10 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
const res = await ndApiClient(apiClientProps).getGenreList({
|
const res = await ndApiClient(apiClientProps).getGenreList({
|
||||||
query: {
|
query: {
|
||||||
_end: query.startIndex + (query.limit || 0),
|
_end: query.offset + (query.limit || 0),
|
||||||
_order: sortOrderMap.navidrome[query.sortOrder],
|
_order: sortOrderMap.navidrome[query.sortOrder],
|
||||||
_sort: genreListSortMap.navidrome[query.sortBy],
|
_sort: genreListSortMap.navidrome[query.sortBy],
|
||||||
_start: query.startIndex,
|
_start: query.offset,
|
||||||
name: query.searchTerm,
|
name: query.searchTerm,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -362,7 +361,7 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.data.map((genre) => ndNormalize.genre(genre)),
|
items: res.body.data.map((genre) => ndNormalize.genre(genre)),
|
||||||
startIndex: query.startIndex || 0,
|
offset: query.offset || 0,
|
||||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -398,10 +397,10 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
const res = await ndApiClient(apiClientProps).getPlaylistList({
|
const res = await ndApiClient(apiClientProps).getPlaylistList({
|
||||||
query: {
|
query: {
|
||||||
_end: query.startIndex + (query.limit || 0),
|
_end: query.offset + (query.limit || 0),
|
||||||
_order: sortOrderMap.navidrome[query.sortOrder],
|
_order: sortOrderMap.navidrome[query.sortOrder],
|
||||||
_sort: query.sortBy ? playlistListSortMap.navidrome[query.sortBy] : undefined,
|
_sort: query.sortBy ? playlistListSortMap.navidrome[query.sortBy] : undefined,
|
||||||
_start: query.startIndex,
|
_start: query.offset,
|
||||||
q: query.searchTerm,
|
q: query.searchTerm,
|
||||||
...customQuery,
|
...customQuery,
|
||||||
},
|
},
|
||||||
@@ -413,16 +412,18 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.data.map((item) => ndNormalize.playlist(item, apiClientProps.server)),
|
items: res.body.data.map((item) => ndNormalize.playlist(item, apiClientProps.server)),
|
||||||
startIndex: query?.startIndex || 0,
|
offset: query?.offset || 0,
|
||||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getPlaylistListCount: async ({ apiClientProps, query }) =>
|
getPlaylistListCount: async ({ apiClientProps, query }) =>
|
||||||
NavidromeController.getPlaylistList({
|
NavidromeController.getPlaylistList({
|
||||||
apiClientProps,
|
apiClientProps,
|
||||||
query: { ...query, limit: 1, startIndex: 0 },
|
query: { ...query, limit: 1, offset: 0 },
|
||||||
}).then((result) => result!.totalRecordCount!),
|
}).then((result) => result!.totalRecordCount!),
|
||||||
getPlaylistSongList: async (args: PlaylistSongListArgs): Promise<PlaylistSongListResponse> => {
|
getPlaylistSongList: async (
|
||||||
|
args: PlaylistSongListRequest,
|
||||||
|
): Promise<PlaylistSongListResponse> => {
|
||||||
const { apiClientProps, query } = args;
|
const { apiClientProps, query } = args;
|
||||||
|
|
||||||
const res = await ndApiClient(apiClientProps).getPlaylistSongList({
|
const res = await ndApiClient(apiClientProps).getPlaylistSongList({
|
||||||
@@ -446,7 +447,7 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.data.map((item) => ndNormalize.song(item, apiClientProps.server)),
|
items: res.body.data.map((item) => ndNormalize.song(item, apiClientProps.server)),
|
||||||
startIndex: query?.startIndex || 0,
|
offset: query?.startIndex || 0,
|
||||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -518,7 +519,7 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
if (res.status === 200 && res.body.similarSongs?.song) {
|
if (res.status === 200 && res.body.similarSongs?.song) {
|
||||||
const similar = res.body.similarSongs.song.reduce<Song[]>((acc, song) => {
|
const similar = res.body.similarSongs.song.reduce<Song[]>((acc, song) => {
|
||||||
if (song.id !== query.songId) {
|
if (song.id !== query.songId) {
|
||||||
acc.push(ssNormalize.song(song, apiClientProps.server));
|
acc.push(normalize.song(song, apiClientProps.server));
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
@@ -572,10 +573,10 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
const res = await ndApiClient(apiClientProps).getSongList({
|
const res = await ndApiClient(apiClientProps).getSongList({
|
||||||
query: {
|
query: {
|
||||||
_end: query.startIndex + (query.limit || -1),
|
_end: query.offset + (query.limit || -1),
|
||||||
_order: sortOrderMap.navidrome[query.sortOrder],
|
_order: sortOrderMap.navidrome[query.sortOrder],
|
||||||
_sort: songListSortMap.navidrome[query.sortBy],
|
_sort: songListSortMap.navidrome[query.sortBy],
|
||||||
_start: query.startIndex,
|
_start: query.offset,
|
||||||
album_artist_id: query.albumArtistIds,
|
album_artist_id: query.albumArtistIds,
|
||||||
album_id: query.albumIds,
|
album_id: query.albumIds,
|
||||||
artist_id: query.artistIds,
|
artist_id: query.artistIds,
|
||||||
@@ -595,14 +596,14 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
items: res.body.data.map((song) =>
|
items: res.body.data.map((song) =>
|
||||||
ndNormalize.song(song, apiClientProps.server, query.imageSize),
|
ndNormalize.song(song, apiClientProps.server, query.imageSize),
|
||||||
),
|
),
|
||||||
startIndex: query?.startIndex || 0,
|
offset: query?.offset || 0,
|
||||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getSongListCount: async ({ apiClientProps, query }) =>
|
getSongListCount: async ({ apiClientProps, query }) =>
|
||||||
NavidromeController.getSongList({
|
NavidromeController.getSongList({
|
||||||
apiClientProps,
|
apiClientProps,
|
||||||
query: { ...query, limit: 1, startIndex: 0 },
|
query: { ...query, limit: 1, offset: 0 },
|
||||||
}).then((result) => result!.totalRecordCount!),
|
}).then((result) => result!.totalRecordCount!),
|
||||||
getStructuredLyrics: SubsonicController.getStructuredLyrics,
|
getStructuredLyrics: SubsonicController.getStructuredLyrics,
|
||||||
getTags: async (args) => {
|
getTags: async (args) => {
|
||||||
@@ -651,10 +652,10 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
const res = await ndApiClient(apiClientProps).getUserList({
|
const res = await ndApiClient(apiClientProps).getUserList({
|
||||||
query: {
|
query: {
|
||||||
_end: query.startIndex + (query.limit || 0),
|
_end: query.offset + (query.limit || 0),
|
||||||
_order: sortOrderMap.navidrome[query.sortOrder],
|
_order: sortOrderMap.navidrome[query.sortOrder],
|
||||||
_sort: userListSortMap.navidrome[query.sortBy],
|
_sort: userListSortMap.navidrome[query.sortBy],
|
||||||
_start: query.startIndex,
|
_start: query.offset,
|
||||||
...query._custom?.navidrome,
|
...query._custom?.navidrome,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -665,7 +666,7 @@ export const NavidromeController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: res.body.data.map((user) => ndNormalize.user(user)),
|
items: res.body.data.map((user) => ndNormalize.user(user)),
|
||||||
startIndex: query?.startIndex || 0,
|
offset: query?.offset || 0,
|
||||||
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
totalRecordCount: Number(res.body.headers.get('x-total-count') || 0),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,27 +1,31 @@
|
|||||||
import type {
|
import { QueryFunctionContext } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { AlbumDetailQuery, AlbumListQuery } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
import {
|
||||||
AlbumArtistDetailQuery,
|
AlbumArtistDetailQuery,
|
||||||
AlbumArtistListQuery,
|
AlbumArtistListQuery,
|
||||||
AlbumDetailQuery,
|
|
||||||
AlbumListQuery,
|
|
||||||
ArtistListQuery,
|
ArtistListQuery,
|
||||||
GenreListQuery,
|
} from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
import { GenreListQuery } from '/@/shared/types/domain/genre-domain-types';
|
||||||
|
import {
|
||||||
LyricSearchQuery,
|
LyricSearchQuery,
|
||||||
|
LyricSource,
|
||||||
LyricsQuery,
|
LyricsQuery,
|
||||||
|
} from '/@/shared/types/domain/lyric-domain-types';
|
||||||
|
import {
|
||||||
PlaylistDetailQuery,
|
PlaylistDetailQuery,
|
||||||
PlaylistListQuery,
|
PlaylistListQuery,
|
||||||
PlaylistSongListQuery,
|
PlaylistSongListQuery,
|
||||||
|
} from '/@/shared/types/domain/playlist-domain-types';
|
||||||
|
import { SearchQuery } from '/@/shared/types/domain/search-domain-types';
|
||||||
|
import {
|
||||||
RandomSongListQuery,
|
RandomSongListQuery,
|
||||||
SearchQuery,
|
|
||||||
SimilarSongsQuery,
|
SimilarSongsQuery,
|
||||||
SongDetailQuery,
|
SongDetailQuery,
|
||||||
SongListQuery,
|
SongListQuery,
|
||||||
TopSongListQuery,
|
TopSongListQuery,
|
||||||
UserListQuery,
|
} from '/@/shared/types/domain/song-domain-types';
|
||||||
} from '/@/shared/types/domain-types';
|
import { UserListQuery } from '/@/shared/types/domain/user-domain-types';
|
||||||
|
|
||||||
import { QueryFunctionContext } from '@tanstack/react-query';
|
|
||||||
|
|
||||||
import { LyricSource } from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
export const splitPaginatedQuery = (key: any) => {
|
export const splitPaginatedQuery = (key: any) => {
|
||||||
const { limit, startIndex, ...filter } = key || {};
|
const { limit, startIndex, ...filter } = key || {};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { z } from 'zod';
|
|||||||
import i18n from '/@/i18n/i18n';
|
import i18n from '/@/i18n/i18n';
|
||||||
import { ssType } from '/@/shared/api/subsonic/subsonic-types';
|
import { ssType } from '/@/shared/api/subsonic/subsonic-types';
|
||||||
import { toast } from '/@/shared/components/toast/toast';
|
import { toast } from '/@/shared/components/toast/toast';
|
||||||
import { ServerListItem } from '/@/shared/types/domain-types';
|
import { ServerListItem } from '/@/shared/types/domain/server-domain-types';
|
||||||
|
|
||||||
const c = initContract();
|
const c = initContract();
|
||||||
|
|
||||||
|
|||||||
@@ -8,25 +8,18 @@ import { z } from 'zod';
|
|||||||
|
|
||||||
import { contract, ssApiClient } from '/@/renderer/api/subsonic/subsonic-api';
|
import { contract, ssApiClient } from '/@/renderer/api/subsonic/subsonic-api';
|
||||||
import { randomString } from '/@/renderer/utils';
|
import { randomString } from '/@/renderer/utils';
|
||||||
import { ssNormalize } from '/@/shared/api/subsonic/subsonic-normalize';
|
import { normalize } from '/@/shared/api/subsonic/subsonic-normalize';
|
||||||
import {
|
import {
|
||||||
AlbumListSortType,
|
AlbumListSortType,
|
||||||
ssType,
|
ssType,
|
||||||
SubsonicExtensions,
|
SubsonicExtensions,
|
||||||
} from '/@/shared/api/subsonic/subsonic-types';
|
} from '/@/shared/api/subsonic/subsonic-types';
|
||||||
import {
|
import { AlbumListSort, sortAlbumList } from '/@/shared/types/domain/album-domain-types';
|
||||||
AlbumListSort,
|
import { ControllerEndpoint } from '/@/shared/types/domain/api-domain-types';
|
||||||
ControllerEndpoint,
|
import { sortAlbumArtistList } from '/@/shared/types/domain/artist-domain-types';
|
||||||
GenreListSort,
|
import { ServerFeatures } from '/@/shared/types/domain/server-domain-types';
|
||||||
LibraryItem,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
PlaylistListSort,
|
import { Song, sortSongList } from '/@/shared/types/domain/song-domain-types';
|
||||||
Song,
|
|
||||||
sortAlbumArtistList,
|
|
||||||
sortAlbumList,
|
|
||||||
SortOrder,
|
|
||||||
sortSongList,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { ServerFeatures } from '/@/shared/types/features-types';
|
|
||||||
|
|
||||||
const ALBUM_LIST_SORT_MAPPING: Record<AlbumListSort, AlbumListSortType | undefined> = {
|
const ALBUM_LIST_SORT_MAPPING: Record<AlbumListSort, AlbumListSortType | undefined> = {
|
||||||
[AlbumListSort.ALBUM_ARTIST]: AlbumListSortType.ALPHABETICAL_BY_ARTIST,
|
[AlbumListSort.ALBUM_ARTIST]: AlbumListSortType.ALPHABETICAL_BY_ARTIST,
|
||||||
@@ -205,11 +198,11 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...ssNormalize.albumArtist(artist, apiClientProps.server, 300),
|
...normalize.albumArtist(artist, apiClientProps.server, 300),
|
||||||
albums: artist.album?.map((album) => ssNormalize.album(album, apiClientProps.server)),
|
albums: artist.album?.map((album) => normalize.album(album, apiClientProps.server)),
|
||||||
similarArtists:
|
similarArtists:
|
||||||
artistInfo?.similarArtist?.map((artist) =>
|
artistInfo?.similarArtist?.map((artist) =>
|
||||||
ssNormalize.albumArtist(artist, apiClientProps.server, 300),
|
normalize.albumArtist(artist, apiClientProps.server, 300),
|
||||||
) || null,
|
) || null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -229,7 +222,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
const artists = (res.body.artists?.index || []).flatMap((index) => index.artist);
|
const artists = (res.body.artists?.index || []).flatMap((index) => index.artist);
|
||||||
|
|
||||||
let results = artists.map((artist) =>
|
let results = artists.map((artist) =>
|
||||||
ssNormalize.albumArtist(artist, apiClientProps.server, 300),
|
normalize.albumArtist(artist, apiClientProps.server, 300),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (query.searchTerm) {
|
if (query.searchTerm) {
|
||||||
@@ -265,7 +258,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
throw new Error('Failed to get album detail');
|
throw new Error('Failed to get album detail');
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssNormalize.album(res.body.album, apiClientProps.server);
|
return normalize.album(res.body.album, apiClientProps.server);
|
||||||
},
|
},
|
||||||
getAlbumList: async (args) => {
|
getAlbumList: async (args) => {
|
||||||
const { apiClientProps, query } = args;
|
const { apiClientProps, query } = args;
|
||||||
@@ -274,7 +267,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
const res = await ssApiClient(apiClientProps).search3({
|
const res = await ssApiClient(apiClientProps).search3({
|
||||||
query: {
|
query: {
|
||||||
albumCount: query.limit,
|
albumCount: query.limit,
|
||||||
albumOffset: query.startIndex,
|
albumOffset: query.offset,
|
||||||
artistCount: 0,
|
artistCount: 0,
|
||||||
artistOffset: 0,
|
artistOffset: 0,
|
||||||
query: query.searchTerm || '',
|
query: query.searchTerm || '',
|
||||||
@@ -289,12 +282,12 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
|
|
||||||
const results =
|
const results =
|
||||||
res.body.searchResult3?.album?.map((album) =>
|
res.body.searchResult3?.album?.map((album) =>
|
||||||
ssNormalize.album(album, apiClientProps.server),
|
normalize.album(album, apiClientProps.server),
|
||||||
) || [];
|
) || [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: results,
|
items: results,
|
||||||
startIndex: query.startIndex,
|
offset: query.offset,
|
||||||
totalRecordCount: null,
|
totalRecordCount: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -324,11 +317,11 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
return artist.body.artist.album ?? [];
|
return artist.body.artist.album ?? [];
|
||||||
});
|
});
|
||||||
|
|
||||||
const items = albums.map((album) => ssNormalize.album(album, apiClientProps.server));
|
const items = albums.map((album) => normalize.album(album, apiClientProps.server));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: sortAlbumList(items, query.sortBy, query.sortOrder),
|
items: sortAlbumList(items, query.sortBy, query.sortOrder),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: albums.length,
|
totalRecordCount: albums.length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -346,12 +339,12 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
|
|
||||||
const results =
|
const results =
|
||||||
res.body.starred?.album?.map((album) =>
|
res.body.starred?.album?.map((album) =>
|
||||||
ssNormalize.album(album, apiClientProps.server),
|
normalize.album(album, apiClientProps.server),
|
||||||
) || [];
|
) || [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: sortAlbumList(results, query.sortBy, query.sortOrder),
|
items: sortAlbumList(results, query.sortBy, query.sortOrder),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: res.body.starred?.album?.length || 0,
|
totalRecordCount: res.body.starred?.album?.length || 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -381,7 +374,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === AlbumListSortType.BY_YEAR && !fromYear && !toYear) {
|
if (type === AlbumListSortType.BY_YEAR && !fromYear && !toYear) {
|
||||||
if (query.sortOrder === SortOrder.ASC) {
|
if (query.sortOrder === ListSortOrder.ASC) {
|
||||||
fromYear = 0;
|
fromYear = 0;
|
||||||
toYear = dayjs().year();
|
toYear = dayjs().year();
|
||||||
} else {
|
} else {
|
||||||
@@ -395,7 +388,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
fromYear,
|
fromYear,
|
||||||
genre: query.genres?.length ? query.genres[0] : undefined,
|
genre: query.genres?.length ? query.genres[0] : undefined,
|
||||||
musicFolderId: query.musicFolderId,
|
musicFolderId: query.musicFolderId,
|
||||||
offset: query.startIndex,
|
offset: query.offset,
|
||||||
size: query.limit,
|
size: query.limit,
|
||||||
toYear,
|
toYear,
|
||||||
type,
|
type,
|
||||||
@@ -409,9 +402,9 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
return {
|
return {
|
||||||
items:
|
items:
|
||||||
res.body.albumList2.album?.map((album) =>
|
res.body.albumList2.album?.map((album) =>
|
||||||
ssNormalize.album(album, apiClientProps.server, 300),
|
normalize.album(album, apiClientProps.server, 300),
|
||||||
) || [],
|
) || [],
|
||||||
startIndex: query.startIndex,
|
offset: query.offset,
|
||||||
totalRecordCount: null,
|
totalRecordCount: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -579,7 +572,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let results = artists.map((artist) =>
|
let results = artists.map((artist) =>
|
||||||
ssNormalize.albumArtist(artist, apiClientProps.server, 300),
|
normalize.albumArtist(artist, apiClientProps.server, 300),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (query.searchTerm) {
|
if (query.searchTerm) {
|
||||||
@@ -596,7 +589,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: results,
|
items: results,
|
||||||
startIndex: query.startIndex,
|
offset: query.offset,
|
||||||
totalRecordCount: results?.length || 0,
|
totalRecordCount: results?.length || 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -640,11 +633,11 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const genres = results.map(ssNormalize.genre);
|
const genres = results.map(normalize.genre);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: genres,
|
items: genres,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: genres.length,
|
totalRecordCount: genres.length,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -662,7 +655,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
id: folder.id.toString(),
|
id: folder.id.toString(),
|
||||||
name: folder.name,
|
name: folder.name,
|
||||||
})),
|
})),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: res.body.musicFolders.musicFolder.length,
|
totalRecordCount: res.body.musicFolders.musicFolder.length,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -679,7 +672,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
throw new Error('Failed to get playlist detail');
|
throw new Error('Failed to get playlist detail');
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssNormalize.playlist(res.body.playlist, apiClientProps.server);
|
return normalize.playlist(res.body.playlist, apiClientProps.server);
|
||||||
},
|
},
|
||||||
getPlaylistList: async ({ apiClientProps, query }) => {
|
getPlaylistList: async ({ apiClientProps, query }) => {
|
||||||
const sortOrder = query.sortOrder.toLowerCase() as 'asc' | 'desc';
|
const sortOrder = query.sortOrder.toLowerCase() as 'asc' | 'desc';
|
||||||
@@ -724,8 +717,8 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: results.map((playlist) => ssNormalize.playlist(playlist, apiClientProps.server)),
|
items: results.map((playlist) => normalize.playlist(playlist, apiClientProps.server)),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: results.length,
|
totalRecordCount: results.length,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -760,7 +753,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let results =
|
let results =
|
||||||
res.body.playlist.entry?.map((song) => ssNormalize.song(song, apiClientProps.server)) ||
|
res.body.playlist.entry?.map((song) => normalize.song(song, apiClientProps.server)) ||
|
||||||
[];
|
[];
|
||||||
|
|
||||||
if (query.sortBy && query.sortOrder) {
|
if (query.sortBy && query.sortOrder) {
|
||||||
@@ -769,7 +762,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
items: results,
|
items: results,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: results?.length || 0,
|
totalRecordCount: results?.length || 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -793,8 +786,8 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
const results = res.body.randomSongs?.song || [];
|
const results = res.body.randomSongs?.song || [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: results.map((song) => ssNormalize.song(song, apiClientProps.server)),
|
items: results.map((song) => normalize.song(song, apiClientProps.server)),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: res.body.randomSongs?.song?.length || 0,
|
totalRecordCount: res.body.randomSongs?.song?.length || 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -878,7 +871,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return res.body.similarSongs.song.reduce<Song[]>((acc, song) => {
|
return res.body.similarSongs.song.reduce<Song[]>((acc, song) => {
|
||||||
if (song.id !== query.songId) {
|
if (song.id !== query.songId) {
|
||||||
acc.push(ssNormalize.song(song, apiClientProps.server));
|
acc.push(normalize.song(song, apiClientProps.server));
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
@@ -897,7 +890,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
throw new Error('Failed to get song detail');
|
throw new Error('Failed to get song detail');
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssNormalize.song(res.body.song, apiClientProps.server);
|
return normalize.song(res.body.song, apiClientProps.server);
|
||||||
},
|
},
|
||||||
getSongList: async ({ apiClientProps, query }) => {
|
getSongList: async ({ apiClientProps, query }) => {
|
||||||
const fromAlbumPromises: Promise<ServerInferResponses<typeof contract.getAlbum>>[] = [];
|
const fromAlbumPromises: Promise<ServerInferResponses<typeof contract.getAlbum>>[] = [];
|
||||||
@@ -912,7 +905,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
artistOffset: 0,
|
artistOffset: 0,
|
||||||
query: query.searchTerm || '',
|
query: query.searchTerm || '',
|
||||||
songCount: query.limit,
|
songCount: query.limit,
|
||||||
songOffset: query.startIndex,
|
songOffset: query.offset,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -923,9 +916,9 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
return {
|
return {
|
||||||
items:
|
items:
|
||||||
res.body.searchResult3?.song?.map((song) =>
|
res.body.searchResult3?.song?.map((song) =>
|
||||||
ssNormalize.song(song, apiClientProps.server),
|
normalize.song(song, apiClientProps.server),
|
||||||
) || [],
|
) || [],
|
||||||
startIndex: query.startIndex,
|
offset: query.offset,
|
||||||
totalRecordCount: null,
|
totalRecordCount: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -936,7 +929,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
count: query.limit,
|
count: query.limit,
|
||||||
genre: query.genreIds[0],
|
genre: query.genreIds[0],
|
||||||
musicFolderId: query.musicFolderId,
|
musicFolderId: query.musicFolderId,
|
||||||
offset: query.startIndex,
|
offset: query.offset,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -947,8 +940,8 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
const results = res.body.songsByGenre?.song || [];
|
const results = res.body.songsByGenre?.song || [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: results.map((song) => ssNormalize.song(song, apiClientProps.server)) || [],
|
items: results.map((song) => normalize.song(song, apiClientProps.server)) || [],
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: null,
|
totalRecordCount: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -966,12 +959,12 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
|
|
||||||
const results =
|
const results =
|
||||||
(res.body.starred?.song || []).map((song) =>
|
(res.body.starred?.song || []).map((song) =>
|
||||||
ssNormalize.song(song, apiClientProps.server),
|
normalize.song(song, apiClientProps.server),
|
||||||
) || [];
|
) || [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: sortSongList(results, query.sortBy, query.sortOrder),
|
items: sortSongList(results, query.sortBy, query.sortOrder),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: (res.body.starred?.song || []).length || 0,
|
totalRecordCount: (res.body.starred?.song || []).length || 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1040,8 +1033,8 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: results.map((song) => ssNormalize.song(song, apiClientProps.server)),
|
items: results.map((song) => normalize.song(song, apiClientProps.server)),
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: results.length,
|
totalRecordCount: results.length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1054,7 +1047,7 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
artistOffset: 0,
|
artistOffset: 0,
|
||||||
query: query.searchTerm || '',
|
query: query.searchTerm || '',
|
||||||
songCount: query.limit,
|
songCount: query.limit,
|
||||||
songOffset: query.startIndex,
|
songOffset: query.offset,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1065,9 +1058,9 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
return {
|
return {
|
||||||
items:
|
items:
|
||||||
res.body.searchResult3?.song?.map((song) =>
|
res.body.searchResult3?.song?.map((song) =>
|
||||||
ssNormalize.song(song, apiClientProps.server),
|
normalize.song(song, apiClientProps.server),
|
||||||
) || [],
|
) || [],
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: null,
|
totalRecordCount: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -1302,9 +1295,9 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
return {
|
return {
|
||||||
items:
|
items:
|
||||||
res.body.topSongs?.song?.map((song) =>
|
res.body.topSongs?.song?.map((song) =>
|
||||||
ssNormalize.song(song, apiClientProps.server),
|
normalize.song(song, apiClientProps.server),
|
||||||
) || [],
|
) || [],
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
totalRecordCount: res.body.topSongs?.song?.length || 0,
|
totalRecordCount: res.body.topSongs?.song?.length || 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -1372,13 +1365,13 @@ export const SubsonicController: ControllerEndpoint = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
albumArtists: (res.body.searchResult3?.artist || [])?.map((artist) =>
|
albumArtists: (res.body.searchResult3?.artist || [])?.map((artist) =>
|
||||||
ssNormalize.albumArtist(artist, apiClientProps.server),
|
normalize.albumArtist(artist, apiClientProps.server),
|
||||||
),
|
),
|
||||||
albums: (res.body.searchResult3?.album || []).map((album) =>
|
albums: (res.body.searchResult3?.album || []).map((album) =>
|
||||||
ssNormalize.album(album, apiClientProps.server),
|
normalize.album(album, apiClientProps.server),
|
||||||
),
|
),
|
||||||
songs: (res.body.searchResult3?.song || []).map((song) =>
|
songs: (res.body.searchResult3?.song || []).map((song) =>
|
||||||
ssNormalize.song(song, apiClientProps.server),
|
normalize.song(song, apiClientProps.server),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { Song } from '/@/shared/types/domain-types';
|
|
||||||
import type { CrossfadeStyle } from '/@/shared/types/types';
|
import type { CrossfadeStyle } from '/@/shared/types/types';
|
||||||
import type { ReactPlayerProps } from 'react-player';
|
import type { ReactPlayerProps } from 'react-player';
|
||||||
|
|
||||||
@@ -20,9 +19,11 @@ import {
|
|||||||
gaplessHandler,
|
gaplessHandler,
|
||||||
} from '/@/renderer/components/audio-player/utils/list-handlers';
|
} from '/@/renderer/components/audio-player/utils/list-handlers';
|
||||||
import { useWebAudio } from '/@/renderer/features/player/hooks/use-webaudio';
|
import { useWebAudio } from '/@/renderer/features/player/hooks/use-webaudio';
|
||||||
import { getServerById, TranscodingConfig, usePlaybackSettings, useSpeed } from '/@/renderer/store';
|
import { TranscodingConfig, usePlaybackSettings, useSpeed } from '/@/renderer/store';
|
||||||
import { useSettingsStore, useSettingsStoreActions } from '/@/renderer/store/settings.store';
|
import { useSettingsStore, useSettingsStoreActions } from '/@/renderer/store/settings.store';
|
||||||
import { toast } from '/@/shared/components/toast/toast';
|
import { toast } from '/@/shared/components/toast/toast';
|
||||||
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
|
import { Song } from '/@/shared/types/domain/song-domain-types';
|
||||||
import { PlaybackStyle, PlayerStatus } from '/@/shared/types/types';
|
import { PlaybackStyle, PlayerStatus } from '/@/shared/types/types';
|
||||||
|
|
||||||
export type AudioPlayerProgress = {
|
export type AudioPlayerProgress = {
|
||||||
@@ -57,27 +58,28 @@ const getDuration = (ref: any) => {
|
|||||||
const EMPTY_SOURCE =
|
const EMPTY_SOURCE =
|
||||||
'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU2LjM2LjEwMAAAAAAAAAAAAAAA//OEAAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAAEAAABIADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV6urq6urq6urq6urq6urq6urq6urq6urq6v////////////////////////////////8AAAAATGF2YzU2LjQxAAAAAAAAAAAAAAAAJAAAAAAAAAAAASDs90hvAAAAAAAAAAAAAAAAAAAA//MUZAAAAAGkAAAAAAAAA0gAAAAATEFN//MUZAMAAAGkAAAAAAAAA0gAAAAARTMu//MUZAYAAAGkAAAAAAAAA0gAAAAAOTku//MUZAkAAAGkAAAAAAAAA0gAAAAANVVV';
|
'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU2LjM2LjEwMAAAAAAAAAAAAAAA//OEAAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAAEAAABIADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV6urq6urq6urq6urq6urq6urq6urq6urq6v////////////////////////////////8AAAAATGF2YzU2LjQxAAAAAAAAAAAAAAAAJAAAAAAAAAAAASDs90hvAAAAAAAAAAAAAAAAAAAA//MUZAAAAAGkAAAAAAAAA0gAAAAATEFN//MUZAMAAAGkAAAAAAAAA0gAAAAARTMu//MUZAYAAAGkAAAAAAAAA0gAAAAAOTku//MUZAkAAAGkAAAAAAAAA0gAAAAANVVV';
|
||||||
|
|
||||||
const useSongUrl = (transcode: TranscodingConfig, current: boolean, song?: Song): null | string => {
|
const useSongUrl = (
|
||||||
|
transcode: TranscodingConfig,
|
||||||
|
current: boolean,
|
||||||
|
song?: QueueSong,
|
||||||
|
): null | string => {
|
||||||
const prior = useRef(['', '']);
|
const prior = useRef(['', '']);
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
if (song?.serverId) {
|
if (song?._serverId) {
|
||||||
// If we are the current track, we do not want a transcoding
|
// If we are the current track, we do not want a transcoding
|
||||||
// reconfiguration to force a restart.
|
// reconfiguration to force a restart.
|
||||||
if (current && prior.current[0] === song.uniqueId) {
|
if (current && prior.current[0] === song._uniqueId) {
|
||||||
return prior.current[1];
|
return prior.current[1] as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!transcode.enabled) {
|
if (!transcode.enabled) {
|
||||||
// transcoding disabled; save the result
|
// transcoding disabled; save the result
|
||||||
prior.current = [song.uniqueId, song.streamUrl];
|
prior.current = [song._uniqueId, song.streamUrl];
|
||||||
return song.streamUrl;
|
return song.streamUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = api.controller.getTranscodingUrl({
|
const result = api.controller.getTranscodingUrl({
|
||||||
apiClientProps: {
|
|
||||||
server: getServerById(song.serverId),
|
|
||||||
},
|
|
||||||
query: {
|
query: {
|
||||||
base: song.streamUrl,
|
base: song.streamUrl,
|
||||||
...transcode,
|
...transcode,
|
||||||
@@ -85,14 +87,14 @@ const useSongUrl = (transcode: TranscodingConfig, current: boolean, song?: Song)
|
|||||||
})!;
|
})!;
|
||||||
|
|
||||||
// transcoding enabled; save the updated result
|
// transcoding enabled; save the updated result
|
||||||
prior.current = [song.uniqueId, result];
|
prior.current = [song._uniqueId, result];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no track; clear result
|
// no track; clear result
|
||||||
prior.current = ['', ''];
|
prior.current = ['', ''];
|
||||||
return null;
|
return null;
|
||||||
}, [current, song?.uniqueId, song?.serverId, song?.streamUrl, transcode]);
|
}, [song?._serverId, song?._uniqueId, song?.streamUrl, current, transcode]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface AudioPlayerRef {
|
export interface AudioPlayerRef {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
|||||||
import { Button } from '/@/shared/components/button/button';
|
import { Button } from '/@/shared/components/button/button';
|
||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
import { Icon } from '/@/shared/components/icon/icon';
|
import { Icon } from '/@/shared/components/icon/icon';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { Play } from '/@/shared/types/types';
|
import { Play } from '/@/shared/types/types';
|
||||||
|
|
||||||
export const CardControls = ({
|
export const CardControls = ({
|
||||||
|
|||||||
@@ -3,18 +3,21 @@ import formatDuration from 'format-duration';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { generatePath } from 'react-router';
|
import { generatePath } from 'react-router';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import { Song } from 'src/main/features/core/lyrics/netease';
|
||||||
|
|
||||||
import styles from './card-rows.module.css';
|
import styles from './card-rows.module.css';
|
||||||
|
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
import { formatDateAbsolute, formatDateRelative, formatRating } from '/@/renderer/utils/format';
|
import { formatDateAbsolute, formatDateRelative, formatRating } from '/@/renderer/utils/format';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { Album, AlbumArtist, Artist, Playlist, Song } from '/@/shared/types/domain-types';
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
import { Playlist } from '/@/shared/types/domain/playlist-domain-types';
|
||||||
import { CardRow } from '/@/shared/types/types';
|
import { CardRow } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface CardRowsProps {
|
interface CardRowsProps {
|
||||||
data: any;
|
data: any;
|
||||||
rows: CardRow<Album>[] | CardRow<AlbumArtist>[] | CardRow<Artist>[];
|
rows: CardRow<Album>[] | CardRow<Artist>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CardRows = ({ data, rows }: CardRowsProps) => {
|
export const CardRows = ({ data, rows }: CardRowsProps) => {
|
||||||
|
|||||||
@@ -8,12 +8,14 @@ import { GridCardControls } from '/@/renderer/components/virtual-grid/grid-card/
|
|||||||
import { Image } from '/@/shared/components/image/image';
|
import { Image } from '/@/shared/components/image/image';
|
||||||
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { Album, AlbumArtist, Artist, LibraryItem } from '/@/shared/types/domain-types';
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { CardRoute, CardRow, Play, PlayQueueAddOptions } from '/@/shared/types/types';
|
import { CardRoute, CardRow, Play, PlayQueueAddOptions } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface BaseGridCardProps {
|
interface BaseGridCardProps {
|
||||||
controls: {
|
controls: {
|
||||||
cardRows: CardRow<Album>[] | CardRow<AlbumArtist>[] | CardRow<Artist>[];
|
cardRows: CardRow<Album>[] | CardRow<Artist>[];
|
||||||
handleFavorite: (options: {
|
handleFavorite: (options: {
|
||||||
id: string[];
|
id: string[];
|
||||||
isFavorite: boolean;
|
isFavorite: boolean;
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ import { Image } from '/@/shared/components/image/image';
|
|||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { TextTitle } from '/@/shared/components/text-title/text-title';
|
import { TextTitle } from '/@/shared/components/text-title/text-title';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { Album, LibraryItem } from '/@/shared/types/domain-types';
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { Play } from '/@/shared/types/types';
|
import { Play } from '/@/shared/types/types';
|
||||||
|
|
||||||
const variants: Variants = {
|
const variants: Variants = {
|
||||||
|
|||||||
@@ -24,13 +24,9 @@ import { Group } from '/@/shared/components/group/group';
|
|||||||
import { Icon } from '/@/shared/components/icon/icon';
|
import { Icon } from '/@/shared/components/icon/icon';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { TextTitle } from '/@/shared/components/text-title/text-title';
|
import { TextTitle } from '/@/shared/components/text-title/text-title';
|
||||||
import {
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
Album,
|
import { Artist, RelatedArtist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
AlbumArtist,
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
Artist,
|
|
||||||
LibraryItem,
|
|
||||||
RelatedArtist,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { CardRoute, CardRow } from '/@/shared/types/types';
|
import { CardRoute, CardRow } from '/@/shared/types/types';
|
||||||
|
|
||||||
const getSlidesPerView = (windowWidth: number) => {
|
const getSlidesPerView = (windowWidth: number) => {
|
||||||
|
|||||||
@@ -10,20 +10,17 @@ import { GridCardControls } from '/@/renderer/components/virtual-grid/grid-card/
|
|||||||
import { Image } from '/@/shared/components/image/image';
|
import { Image } from '/@/shared/components/image/image';
|
||||||
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import {
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
Album,
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
AlbumArtist,
|
import { Playlist } from '/@/shared/types/domain/playlist-domain-types';
|
||||||
Artist,
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
import { Song } from '/@/shared/types/domain/song-domain-types';
|
||||||
Playlist,
|
|
||||||
Song,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { CardRoute, CardRow, Play, PlayQueueAddOptions } from '/@/shared/types/types';
|
import { CardRoute, CardRow, Play, PlayQueueAddOptions } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface BaseGridCardProps {
|
interface BaseGridCardProps {
|
||||||
columnIndex: number;
|
columnIndex: number;
|
||||||
controls: {
|
controls: {
|
||||||
cardRows: CardRow<Album | AlbumArtist | Artist | Playlist | Song>[];
|
cardRows: CardRow<Album | Artist | Playlist | Song>[];
|
||||||
handleFavorite: (options: {
|
handleFavorite: (options: {
|
||||||
id: string[];
|
id: string[];
|
||||||
isFavorite: boolean;
|
isFavorite: boolean;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
|||||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||||
import { Button } from '/@/shared/components/button/button';
|
import { Button } from '/@/shared/components/button/button';
|
||||||
import { Icon } from '/@/shared/components/icon/icon';
|
import { Icon } from '/@/shared/components/icon/icon';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { Play, PlayQueueAddOptions } from '/@/shared/types/types';
|
import { Play, PlayQueueAddOptions } from '/@/shared/types/types';
|
||||||
|
|
||||||
export const GridCardControls = ({
|
export const GridCardControls = ({
|
||||||
|
|||||||
@@ -10,20 +10,17 @@ import { GridCardControls } from '/@/renderer/components/virtual-grid/grid-card/
|
|||||||
import { Image } from '/@/shared/components/image/image';
|
import { Image } from '/@/shared/components/image/image';
|
||||||
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import {
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
Album,
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
AlbumArtist,
|
import { Playlist } from '/@/shared/types/domain/playlist-domain-types';
|
||||||
Artist,
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
import { Song } from '/@/shared/types/domain/song-domain-types';
|
||||||
Playlist,
|
|
||||||
Song,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { CardRoute, CardRow, Play, PlayQueueAddOptions } from '/@/shared/types/types';
|
import { CardRoute, CardRow, Play, PlayQueueAddOptions } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface BaseGridCardProps {
|
interface BaseGridCardProps {
|
||||||
columnIndex: number;
|
columnIndex: number;
|
||||||
controls: {
|
controls: {
|
||||||
cardRows: CardRow<Album | AlbumArtist | Artist | Playlist | Song>[];
|
cardRows: CardRow<Album | Artist | Playlist | Song>[];
|
||||||
handleFavorite: (options: {
|
handleFavorite: (options: {
|
||||||
id: string[];
|
id: string[];
|
||||||
isFavorite: boolean;
|
isFavorite: boolean;
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ import { FixedSizeList } from 'react-window';
|
|||||||
import styles from './virtual-grid-wrapper.module.css';
|
import styles from './virtual-grid-wrapper.module.css';
|
||||||
|
|
||||||
import { GridCard } from '/@/renderer/components/virtual-grid/grid-card';
|
import { GridCard } from '/@/renderer/components/virtual-grid/grid-card';
|
||||||
import { Album, AlbumArtist, Artist, LibraryItem } from '/@/shared/types/domain-types';
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
const createItemData = memoize(
|
const createItemData = memoize(
|
||||||
(
|
(
|
||||||
@@ -72,7 +74,7 @@ export const VirtualGridWrapper = ({
|
|||||||
width,
|
width,
|
||||||
...rest
|
...rest
|
||||||
}: Omit<FixedSizeListProps, 'children' | 'height' | 'itemSize' | 'ref' | 'width'> & {
|
}: Omit<FixedSizeListProps, 'children' | 'height' | 'itemSize' | 'ref' | 'width'> & {
|
||||||
cardRows: CardRow<Album | AlbumArtist | Artist>[];
|
cardRows: CardRow<Album | Artist>[];
|
||||||
columnCount: number;
|
columnCount: number;
|
||||||
display: ListDisplayType;
|
display: ListDisplayType;
|
||||||
handleFavorite?: (options: {
|
handleFavorite?: (options: {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import {
|
|||||||
import InfiniteLoader from 'react-window-infinite-loader';
|
import InfiniteLoader from 'react-window-infinite-loader';
|
||||||
|
|
||||||
import { VirtualGridWrapper } from '/@/renderer/components/virtual-grid/virtual-grid-wrapper';
|
import { VirtualGridWrapper } from '/@/renderer/components/virtual-grid/virtual-grid-wrapper';
|
||||||
import { AnyLibraryItem, Genre, LibraryItem } from '/@/shared/types/domain-types';
|
import { Genre } from '/@/shared/types/domain/genre-domain-types';
|
||||||
|
import { AnyLibraryItem, LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { ListDisplayType } from '/@/shared/types/types';
|
import { ListDisplayType } from '/@/shared/types/types';
|
||||||
|
|
||||||
export type VirtualInfiniteGridRef = {
|
export type VirtualInfiniteGridRef = {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { AlbumArtist, Artist } from '/@/shared/types/domain-types';
|
|
||||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@@ -10,6 +9,7 @@ import { AppRoute } from '/@/renderer/router/routes';
|
|||||||
import { Separator } from '/@/shared/components/separator/separator';
|
import { Separator } from '/@/shared/components/separator/separator';
|
||||||
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
|
||||||
export const AlbumArtistCell = ({ data, value }: ICellRendererParams) => {
|
export const AlbumArtistCell = ({ data, value }: ICellRendererParams) => {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
@@ -23,7 +23,7 @@ export const AlbumArtistCell = ({ data, value }: ICellRendererParams) => {
|
|||||||
return (
|
return (
|
||||||
<CellContainer position="left">
|
<CellContainer position="left">
|
||||||
<Text isMuted overflow="hidden" size="md">
|
<Text isMuted overflow="hidden" size="md">
|
||||||
{value?.map((item: AlbumArtist | Artist, index: number) => (
|
{value?.map((item: Artist, index: number) => (
|
||||||
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
||||||
{index > 0 && <Separator />}
|
{index > 0 && <Separator />}
|
||||||
{item.id ? (
|
{item.id ? (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { AlbumArtist, Artist } from '/@/shared/types/domain-types';
|
|
||||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@@ -10,6 +9,7 @@ import { AppRoute } from '/@/renderer/router/routes';
|
|||||||
import { Separator } from '/@/shared/components/separator/separator';
|
import { Separator } from '/@/shared/components/separator/separator';
|
||||||
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
|
||||||
export const ArtistCell = ({ data, value }: ICellRendererParams) => {
|
export const ArtistCell = ({ data, value }: ICellRendererParams) => {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
@@ -23,7 +23,7 @@ export const ArtistCell = ({ data, value }: ICellRendererParams) => {
|
|||||||
return (
|
return (
|
||||||
<CellContainer position="left">
|
<CellContainer position="left">
|
||||||
<Text isMuted overflow="hidden" size="md">
|
<Text isMuted overflow="hidden" size="md">
|
||||||
{value?.map((item: AlbumArtist | Artist, index: number) => (
|
{value?.map((item: Artist, index: number) => (
|
||||||
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
||||||
{index > 0 && <Separator />}
|
{index > 0 && <Separator />}
|
||||||
{item.id ? (
|
{item.id ? (
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import styles from './combined-title-cell-controls.module.css';
|
|||||||
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
||||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { Play } from '/@/shared/types/types';
|
import { Play } from '/@/shared/types/types';
|
||||||
|
|
||||||
export const ListCoverControls = ({
|
export const ListCoverControls = ({
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { SEPARATOR_STRING } from '/@/shared/api/utils';
|
|||||||
import { Image } from '/@/shared/components/image/image';
|
import { Image } from '/@/shared/components/image/image';
|
||||||
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
import { Skeleton } from '/@/shared/components/skeleton/skeleton';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { AlbumArtist, Artist } from '/@/shared/types/domain-types';
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
|
||||||
export const CombinedTitleCell = ({
|
export const CombinedTitleCell = ({
|
||||||
context,
|
context,
|
||||||
@@ -74,7 +74,7 @@ export const CombinedTitleCell = ({
|
|||||||
</Text>
|
</Text>
|
||||||
<Text isMuted overflow="hidden" size="md">
|
<Text isMuted overflow="hidden" size="md">
|
||||||
{artists?.length ? (
|
{artists?.length ? (
|
||||||
artists.map((artist: AlbumArtist | Artist, index: number) => (
|
artists.map((artist: Artist, index: number) => (
|
||||||
<React.Fragment key={`queue-${rowIndex}-artist-${artist.id}`}>
|
<React.Fragment key={`queue-${rowIndex}-artist-${artist.id}`}>
|
||||||
{index > 0 ? SEPARATOR_STRING : null}
|
{index > 0 ? SEPARATOR_STRING : null}
|
||||||
{artist.id ? (
|
{artist.id ? (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { AlbumArtist, Artist } from '/@/shared/types/domain-types';
|
|
||||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@@ -8,13 +7,14 @@ import { CellContainer } from '/@/renderer/components/virtual-table/cells/generi
|
|||||||
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
|
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
|
||||||
import { Separator } from '/@/shared/components/separator/separator';
|
import { Separator } from '/@/shared/components/separator/separator';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
|
||||||
export const GenreCell = ({ data, value }: ICellRendererParams) => {
|
export const GenreCell = ({ data, value }: ICellRendererParams) => {
|
||||||
const genrePath = useGenreRoute();
|
const genrePath = useGenreRoute();
|
||||||
return (
|
return (
|
||||||
<CellContainer position="left">
|
<CellContainer position="left">
|
||||||
<Text isMuted overflow="hidden" size="md">
|
<Text isMuted overflow="hidden" size="md">
|
||||||
{value?.map((item: AlbumArtist | Artist, index: number) => (
|
{value?.map((item: Artist, index: number) => (
|
||||||
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
||||||
{index > 0 && <Separator />}
|
{index > 0 && <Separator />}
|
||||||
<Text
|
<Text
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { MutableRefObject, useEffect, useMemo, useRef } from 'react';
|
|||||||
|
|
||||||
import { useAppFocus } from '/@/renderer/hooks';
|
import { useAppFocus } from '/@/renderer/hooks';
|
||||||
import { useCurrentSong, usePlayerStore } from '/@/renderer/store';
|
import { useCurrentSong, usePlayerStore } from '/@/renderer/store';
|
||||||
import { Song } from '/@/shared/types/domain-types';
|
import { Song } from '/@/shared/types/domain/song-domain-types';
|
||||||
import { PlayerStatus } from '/@/shared/types/types';
|
import { PlayerStatus } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface UseCurrentSongRowStylesProps {
|
interface UseCurrentSongRowStylesProps {
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ import { AppRoute } from '/@/renderer/router/routes';
|
|||||||
import { PersistedTableColumn, useListStoreActions } from '/@/renderer/store';
|
import { PersistedTableColumn, useListStoreActions } from '/@/renderer/store';
|
||||||
import { ListKey, useListStoreByKey } from '/@/renderer/store/list.store';
|
import { ListKey, useListStoreByKey } from '/@/renderer/store/list.store';
|
||||||
import {
|
import {
|
||||||
|
BasePaginatedQuery,
|
||||||
BasePaginatedResponse,
|
BasePaginatedResponse,
|
||||||
BaseQuery,
|
} from '/@/shared/types/adapter/api-controller-types';
|
||||||
LibraryItem,
|
import { ServerListItem } from '/@/shared/types/domain/server-domain-types';
|
||||||
ServerListItem,
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { ListDisplayType, TablePagination } from '/@/shared/types/types';
|
import { ListDisplayType, TablePagination } from '/@/shared/types/types';
|
||||||
|
|
||||||
export type AgGridFetchFn<TResponse, TFilter> = (
|
export type AgGridFetchFn<TResponse, TFilter> = (
|
||||||
@@ -52,7 +52,7 @@ interface UseAgGridProps<TFilter> {
|
|||||||
|
|
||||||
const BLOCK_SIZE = 500;
|
const BLOCK_SIZE = 500;
|
||||||
|
|
||||||
export const useVirtualTable = <TFilter extends BaseQuery<any>>({
|
export const useVirtualTable = <TFilter extends BasePaginatedQuery<any>>({
|
||||||
columnType,
|
columnType,
|
||||||
contextMenu,
|
contextMenu,
|
||||||
customFilters,
|
customFilters,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { Icon } from '/@/shared/components/icon/icon';
|
|||||||
import { ScrollArea } from '/@/shared/components/scroll-area/scroll-area';
|
import { ScrollArea } from '/@/shared/components/scroll-area/scroll-area';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { ServerListItem, ServerType } from '/@/shared/types/domain-types';
|
import { ServerListItem, ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
|
|
||||||
const localSettings = isElectron() ? window.api.localSettings : null;
|
const localSettings = isElectron() ? window.api.localSettings : null;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { queryOptions, UseQueryOptions } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { api } from '/@/renderer/api/api-controller';
|
||||||
|
import { AlbumListRequest } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
|
||||||
|
export const getAlbumListQueryKey = (serverId: string, request?: AlbumListRequest) => {
|
||||||
|
if (!request) {
|
||||||
|
return [serverId, 'albums'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [serverId, 'albums', request];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getInfiniteAlbumListQueryKey = (serverId: string, request?: AlbumListRequest) => {
|
||||||
|
if (!request) {
|
||||||
|
return [serverId, 'albums', 'infinite'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [serverId, 'albums', 'infinite', request];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAlbumList = async (serverId: string, request: AlbumListRequest) => {
|
||||||
|
const [error, response] = await api.controller[serverId]!.album.getList!({
|
||||||
|
query: request.query,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw new Error(error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAlbumListQuery = (
|
||||||
|
serverId: string,
|
||||||
|
request: AlbumListRequest,
|
||||||
|
options?: UseQueryOptions,
|
||||||
|
) => {
|
||||||
|
return queryOptions({
|
||||||
|
enabled: !!serverId,
|
||||||
|
queryFn: () => getAlbumList(serverId, request),
|
||||||
|
queryKey: getAlbumListQueryKey(serverId, request),
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -49,13 +49,9 @@ import { Group } from '/@/shared/components/group/group';
|
|||||||
import { Popover } from '/@/shared/components/popover/popover';
|
import { Popover } from '/@/shared/components/popover/popover';
|
||||||
import { Spoiler } from '/@/shared/components/spoiler/spoiler';
|
import { Spoiler } from '/@/shared/components/spoiler/spoiler';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import {
|
import { AlbumListQuery, AlbumListSort } from '/@/shared/types/domain/album-domain-types';
|
||||||
AlbumListQuery,
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
AlbumListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
|
||||||
QueueSong,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { Play } from '/@/shared/types/types';
|
import { Play } from '/@/shared/types/types';
|
||||||
|
|
||||||
const isFullWidthRow = (node: RowNode) => {
|
const isFullWidthRow = (node: RowNode) => {
|
||||||
@@ -154,8 +150,8 @@ export const AlbumDetailContent = ({ background, tableRef }: AlbumDetailContentP
|
|||||||
|
|
||||||
const artistQuery = useAlbumList({
|
const artistQuery = useAlbumList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60,
|
|
||||||
enabled: detailQuery?.data?.albumArtists[0]?.id !== undefined,
|
enabled: detailQuery?.data?.albumArtists[0]?.id !== undefined,
|
||||||
|
gcTime: 1000 * 60,
|
||||||
keepPreviousData: true,
|
keepPreviousData: true,
|
||||||
staleTime: 1000 * 60,
|
staleTime: 1000 * 60,
|
||||||
},
|
},
|
||||||
@@ -169,9 +165,9 @@ export const AlbumDetailContent = ({ background, tableRef }: AlbumDetailContentP
|
|||||||
? [detailQuery?.data?.albumArtists[0].id]
|
? [detailQuery?.data?.albumArtists[0].id]
|
||||||
: undefined,
|
: undefined,
|
||||||
limit: 15,
|
limit: 15,
|
||||||
|
offset: 0,
|
||||||
sortBy: AlbumListSort.YEAR,
|
sortBy: AlbumListSort.YEAR,
|
||||||
sortOrder: SortOrder.DESC,
|
sortOrder: ListSortOrder.DESC,
|
||||||
startIndex: 0,
|
|
||||||
},
|
},
|
||||||
serverId: server?.id,
|
serverId: server?.id,
|
||||||
});
|
});
|
||||||
@@ -179,15 +175,15 @@ export const AlbumDetailContent = ({ background, tableRef }: AlbumDetailContentP
|
|||||||
const relatedAlbumGenresRequest: AlbumListQuery = {
|
const relatedAlbumGenresRequest: AlbumListQuery = {
|
||||||
genres: detailQuery.data?.genres.length ? [detailQuery.data.genres[0].id] : undefined,
|
genres: detailQuery.data?.genres.length ? [detailQuery.data.genres[0].id] : undefined,
|
||||||
limit: 15,
|
limit: 15,
|
||||||
|
offset: 0,
|
||||||
sortBy: AlbumListSort.RANDOM,
|
sortBy: AlbumListSort.RANDOM,
|
||||||
sortOrder: SortOrder.ASC,
|
sortOrder: ListSortOrder.ASC,
|
||||||
startIndex: 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const relatedAlbumGenresQuery = useAlbumList({
|
const relatedAlbumGenresQuery = useAlbumList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60,
|
|
||||||
enabled: !!detailQuery?.data?.genres?.[0],
|
enabled: !!detailQuery?.data?.genres?.[0],
|
||||||
|
gcTime: 1000 * 60,
|
||||||
queryKey: queryKeys.albums.related(
|
queryKey: queryKeys.albums.related(
|
||||||
server?.id || '',
|
server?.id || '',
|
||||||
albumId,
|
albumId,
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ import { Group } from '/@/shared/components/group/group';
|
|||||||
import { Rating } from '/@/shared/components/rating/rating';
|
import { Rating } from '/@/shared/components/rating/rating';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { AlbumDetailResponse, LibraryItem, ServerType } from '/@/shared/types/domain-types';
|
import { AlbumDetailResponse } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
interface AlbumDetailHeaderProps {
|
interface AlbumDetailHeaderProps {
|
||||||
background: {
|
background: {
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import {
|
|||||||
AlbumListQuery,
|
AlbumListQuery,
|
||||||
AlbumListResponse,
|
AlbumListResponse,
|
||||||
AlbumListSort,
|
AlbumListSort,
|
||||||
LibraryItem,
|
} from '/@/shared/types/domain/album-domain-types';
|
||||||
} from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { CardRow, ListDisplayType } from '/@/shared/types/types';
|
import { CardRow, ListDisplayType } from '/@/shared/types/types';
|
||||||
|
|
||||||
export const AlbumListGridView = ({ gridRef, itemCount }: any) => {
|
export const AlbumListGridView = ({ gridRef, itemCount }: any) => {
|
||||||
@@ -137,15 +137,11 @@ export const AlbumListGridView = ({ gridRef, itemCount }: any) => {
|
|||||||
const itemData: Album[] = [];
|
const itemData: Album[] = [];
|
||||||
|
|
||||||
for (const [, data] of queriesFromCache) {
|
for (const [, data] of queriesFromCache) {
|
||||||
const { items, startIndex } = data || {};
|
const { items, offset } = data || {};
|
||||||
|
|
||||||
if (items && items.length !== 1 && startIndex !== undefined) {
|
if (items && items.length !== 1 && offset !== undefined) {
|
||||||
let itemIndex = 0;
|
let itemIndex = 0;
|
||||||
for (
|
for (let rowIndex = offset; rowIndex < offset + items.length; rowIndex += 1) {
|
||||||
let rowIndex = startIndex;
|
|
||||||
rowIndex < startIndex + items.length;
|
|
||||||
rowIndex += 1
|
|
||||||
) {
|
|
||||||
itemData[rowIndex] = items[itemIndex];
|
itemData[rowIndex] = items[itemIndex];
|
||||||
itemIndex += 1;
|
itemIndex += 1;
|
||||||
}
|
}
|
||||||
@@ -165,7 +161,7 @@ export const AlbumListGridView = ({ gridRef, itemCount }: any) => {
|
|||||||
limit: take,
|
limit: take,
|
||||||
...filter,
|
...filter,
|
||||||
...customFilters,
|
...customFilters,
|
||||||
startIndex: skip,
|
offset: skip,
|
||||||
};
|
};
|
||||||
|
|
||||||
const queryKey = queryKeys.albums.list(server?.id || '', query, id);
|
const queryKey = queryKeys.albums.list(server?.id || '', query, id);
|
||||||
|
|||||||
@@ -34,158 +34,154 @@ import { DropdownMenu } from '/@/shared/components/dropdown-menu/dropdown-menu';
|
|||||||
import { Flex } from '/@/shared/components/flex/flex';
|
import { Flex } from '/@/shared/components/flex/flex';
|
||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
import { Icon } from '/@/shared/components/icon/icon';
|
import { Icon } from '/@/shared/components/icon/icon';
|
||||||
import {
|
import { AlbumListQuery, AlbumListSort } from '/@/shared/types/domain/album-domain-types';
|
||||||
AlbumListQuery,
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
AlbumListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
|
||||||
ServerType,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { ListDisplayType, Play, TableColumn } from '/@/shared/types/types';
|
import { ListDisplayType, Play, TableColumn } from '/@/shared/types/types';
|
||||||
|
|
||||||
const FILTERS = {
|
const FILTERS = {
|
||||||
jellyfin: [
|
jellyfin: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.albumArtist', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.albumArtist', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.ALBUM_ARTIST,
|
value: AlbumListSort.ALBUM_ARTIST,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.communityRating', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.communityRating', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.COMMUNITY_RATING,
|
value: AlbumListSort.COMMUNITY_RATING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.criticRating', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.criticRating', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.CRITIC_RATING,
|
value: AlbumListSort.CRITIC_RATING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.NAME,
|
value: AlbumListSort.NAME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.playCount', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.playCount', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.PLAY_COUNT,
|
value: AlbumListSort.PLAY_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RANDOM,
|
value: AlbumListSort.RANDOM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RECENTLY_ADDED,
|
value: AlbumListSort.RECENTLY_ADDED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.releaseDate', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.releaseDate', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RELEASE_DATE,
|
value: AlbumListSort.RELEASE_DATE,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
navidrome: [
|
navidrome: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.albumArtist', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.albumArtist', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.ALBUM_ARTIST,
|
value: AlbumListSort.ALBUM_ARTIST,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.artist', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.artist', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.ARTIST,
|
value: AlbumListSort.ARTIST,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.duration', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.duration', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.DURATION,
|
value: AlbumListSort.DURATION,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.mostPlayed', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.mostPlayed', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.PLAY_COUNT,
|
value: AlbumListSort.PLAY_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.NAME,
|
value: AlbumListSort.NAME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RANDOM,
|
value: AlbumListSort.RANDOM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RATING,
|
value: AlbumListSort.RATING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RECENTLY_ADDED,
|
value: AlbumListSort.RECENTLY_ADDED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.recentlyPlayed', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.recentlyPlayed', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RECENTLY_PLAYED,
|
value: AlbumListSort.RECENTLY_PLAYED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.songCount', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.songCount', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.SONG_COUNT,
|
value: AlbumListSort.SONG_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.favorited', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.favorited', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.FAVORITED,
|
value: AlbumListSort.FAVORITED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.releaseYear', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.releaseYear', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.YEAR,
|
value: AlbumListSort.YEAR,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
subsonic: [
|
subsonic: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.albumArtist', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.albumArtist', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.ALBUM_ARTIST,
|
value: AlbumListSort.ALBUM_ARTIST,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.mostPlayed', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.mostPlayed', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.PLAY_COUNT,
|
value: AlbumListSort.PLAY_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.NAME,
|
value: AlbumListSort.NAME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RANDOM,
|
value: AlbumListSort.RANDOM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RECENTLY_ADDED,
|
value: AlbumListSort.RECENTLY_ADDED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.recentlyPlayed', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.recentlyPlayed', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.RECENTLY_PLAYED,
|
value: AlbumListSort.RECENTLY_PLAYED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.favorited', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.favorited', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.FAVORITED,
|
value: AlbumListSort.FAVORITED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.releaseYear', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.releaseYear', { postProcess: 'titleCase' }),
|
||||||
value: AlbumListSort.YEAR,
|
value: AlbumListSort.YEAR,
|
||||||
},
|
},
|
||||||
@@ -299,7 +295,7 @@ export const AlbumListHeaderFilters = ({
|
|||||||
customFilters,
|
customFilters,
|
||||||
data: {
|
data: {
|
||||||
sortBy: e.currentTarget.value as AlbumListSort,
|
sortBy: e.currentTarget.value as AlbumListSort,
|
||||||
sortOrder: sortOrder || SortOrder.ASC,
|
sortOrder: sortOrder || ListSortOrder.ASC,
|
||||||
},
|
},
|
||||||
itemType: LibraryItem.ALBUM,
|
itemType: LibraryItem.ALBUM,
|
||||||
key: pageKey,
|
key: pageKey,
|
||||||
@@ -337,7 +333,8 @@ export const AlbumListHeaderFilters = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleToggleSortOrder = useCallback(() => {
|
const handleToggleSortOrder = useCallback(() => {
|
||||||
const newSortOrder = filter.sortOrder === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
|
const newSortOrder =
|
||||||
|
filter.sortOrder === ListSortOrder.ASC ? ListSortOrder.DESC : ListSortOrder.ASC;
|
||||||
const updatedFilters = setFilter({
|
const updatedFilters = setFilter({
|
||||||
customFilters,
|
customFilters,
|
||||||
data: { sortOrder: newSortOrder },
|
data: { sortOrder: newSortOrder },
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ import { titleCase } from '/@/renderer/utils';
|
|||||||
import { Flex } from '/@/shared/components/flex/flex';
|
import { Flex } from '/@/shared/components/flex/flex';
|
||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { AlbumListQuery, LibraryItem } from '/@/shared/types/domain-types';
|
import { AlbumListQuery } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
interface AlbumListHeaderProps {
|
interface AlbumListHeaderProps {
|
||||||
genreId?: string;
|
genreId?: string;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-
|
|||||||
import { useListContext } from '/@/renderer/context/list-context';
|
import { useListContext } from '/@/renderer/context/list-context';
|
||||||
import { ALBUM_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
|
import { ALBUM_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
|
||||||
import { useCurrentServer } from '/@/renderer/store';
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
export const AlbumListTableView = ({ itemCount, tableRef }: any) => {
|
export const AlbumListTableView = ({ itemCount, tableRef }: any) => {
|
||||||
const server = useCurrentServer();
|
const server = useCurrentServer();
|
||||||
|
|||||||
@@ -14,13 +14,10 @@ import { SpinnerIcon } from '/@/shared/components/spinner/spinner';
|
|||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { YesNoSelect } from '/@/shared/components/yes-no-select/yes-no-select';
|
import { YesNoSelect } from '/@/shared/components/yes-no-select/yes-no-select';
|
||||||
import {
|
import { AlbumListQuery } from '/@/shared/types/domain/album-domain-types';
|
||||||
AlbumArtistListSort,
|
import { AlbumArtistListSort } from '/@/shared/types/domain/artist-domain-types';
|
||||||
AlbumListQuery,
|
import { GenreListSort } from '/@/shared/types/domain/genre-domain-types';
|
||||||
GenreListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
interface JellyfinAlbumFiltersProps {
|
interface JellyfinAlbumFiltersProps {
|
||||||
customFilters?: Partial<AlbumListFilter>;
|
customFilters?: Partial<AlbumListFilter>;
|
||||||
@@ -44,14 +41,14 @@ export const JellyfinAlbumFilters = ({
|
|||||||
// TODO - eventually replace with /items/filters endpoint to fetch genres and tags specific to the selected library
|
// TODO - eventually replace with /items/filters endpoint to fetch genres and tags specific to the selected library
|
||||||
const genreListQuery = useGenreList({
|
const genreListQuery = useGenreList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 2,
|
gcTime: 1000 * 60 * 2,
|
||||||
staleTime: 1000 * 60 * 1,
|
staleTime: 1000 * 60 * 1,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
musicFolderId: filter?.musicFolderId,
|
musicFolderId: filter?.musicFolderId,
|
||||||
sortBy: GenreListSort.NAME,
|
sortBy: GenreListSort.NAME,
|
||||||
sortOrder: SortOrder.ASC,
|
sortOrder: ListSortOrder.ASC,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
serverId,
|
serverId,
|
||||||
});
|
});
|
||||||
@@ -66,7 +63,7 @@ export const JellyfinAlbumFilters = ({
|
|||||||
|
|
||||||
const tagsQuery = useTagList({
|
const tagsQuery = useTagList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 2,
|
gcTime: 1000 * 60 * 2,
|
||||||
staleTime: 1000 * 60 * 1,
|
staleTime: 1000 * 60 * 1,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
@@ -173,12 +170,12 @@ export const JellyfinAlbumFilters = ({
|
|||||||
|
|
||||||
const albumArtistListQuery = useAlbumArtistList({
|
const albumArtistListQuery = useAlbumArtistList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 2,
|
gcTime: 1000 * 60 * 2,
|
||||||
staleTime: 1000 * 60 * 1,
|
staleTime: 1000 * 60 * 1,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
sortBy: AlbumArtistListSort.NAME,
|
sortBy: AlbumArtistListSort.NAME,
|
||||||
sortOrder: SortOrder.ASC,
|
sortOrder: ListSortOrder.ASC,
|
||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
},
|
},
|
||||||
serverId,
|
serverId,
|
||||||
|
|||||||
@@ -16,13 +16,10 @@ import { Stack } from '/@/shared/components/stack/stack';
|
|||||||
import { Switch } from '/@/shared/components/switch/switch';
|
import { Switch } from '/@/shared/components/switch/switch';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { YesNoSelect } from '/@/shared/components/yes-no-select/yes-no-select';
|
import { YesNoSelect } from '/@/shared/components/yes-no-select/yes-no-select';
|
||||||
import {
|
import { AlbumListQuery } from '/@/shared/types/domain/album-domain-types';
|
||||||
AlbumArtistListSort,
|
import { AlbumArtistListSort } from '/@/shared/types/domain/artist-domain-types';
|
||||||
AlbumListQuery,
|
import { GenreListSort } from '/@/shared/types/domain/genre-domain-types';
|
||||||
GenreListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
interface NavidromeAlbumFiltersProps {
|
interface NavidromeAlbumFiltersProps {
|
||||||
customFilters?: Partial<AlbumListFilter>;
|
customFilters?: Partial<AlbumListFilter>;
|
||||||
@@ -45,13 +42,13 @@ export const NavidromeAlbumFilters = ({
|
|||||||
|
|
||||||
const genreListQuery = useGenreList({
|
const genreListQuery = useGenreList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 2,
|
gcTime: 1000 * 60 * 2,
|
||||||
staleTime: 1000 * 60 * 1,
|
staleTime: 1000 * 60 * 1,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
sortBy: GenreListSort.NAME,
|
sortBy: GenreListSort.NAME,
|
||||||
sortOrder: SortOrder.ASC,
|
sortOrder: ListSortOrder.ASC,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
serverId,
|
serverId,
|
||||||
});
|
});
|
||||||
@@ -79,7 +76,7 @@ export const NavidromeAlbumFilters = ({
|
|||||||
|
|
||||||
const tagsQuery = useTagList({
|
const tagsQuery = useTagList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 2,
|
gcTime: 1000 * 60 * 2,
|
||||||
staleTime: 1000 * 60 * 1,
|
staleTime: 1000 * 60 * 1,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
@@ -188,13 +185,13 @@ export const NavidromeAlbumFilters = ({
|
|||||||
|
|
||||||
const albumArtistListQuery = useAlbumArtistList({
|
const albumArtistListQuery = useAlbumArtistList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 2,
|
gcTime: 1000 * 60 * 2,
|
||||||
staleTime: 1000 * 60 * 1,
|
staleTime: 1000 * 60 * 1,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
// searchTerm: debouncedSearchTerm,
|
// searchTerm: debouncedSearchTerm,
|
||||||
sortBy: AlbumArtistListSort.NAME,
|
sortBy: AlbumArtistListSort.NAME,
|
||||||
sortOrder: SortOrder.ASC,
|
sortOrder: ListSortOrder.ASC,
|
||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
},
|
},
|
||||||
serverId,
|
serverId,
|
||||||
|
|||||||
@@ -14,13 +14,10 @@ import { SpinnerIcon } from '/@/shared/components/spinner/spinner';
|
|||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { Switch } from '/@/shared/components/switch/switch';
|
import { Switch } from '/@/shared/components/switch/switch';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import {
|
import { AlbumListQuery } from '/@/shared/types/domain/album-domain-types';
|
||||||
AlbumArtistListSort,
|
import { AlbumArtistListSort } from '/@/shared/types/domain/artist-domain-types';
|
||||||
AlbumListQuery,
|
import { GenreListSort } from '/@/shared/types/domain/genre-domain-types';
|
||||||
GenreListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
interface SubsonicAlbumFiltersProps {
|
interface SubsonicAlbumFiltersProps {
|
||||||
disableArtistFilter?: boolean;
|
disableArtistFilter?: boolean;
|
||||||
@@ -42,12 +39,12 @@ export const SubsonicAlbumFilters = ({
|
|||||||
|
|
||||||
const albumArtistListQuery = useAlbumArtistList({
|
const albumArtistListQuery = useAlbumArtistList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 2,
|
gcTime: 1000 * 60 * 2,
|
||||||
staleTime: 1000 * 60 * 1,
|
staleTime: 1000 * 60 * 1,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
sortBy: AlbumArtistListSort.NAME,
|
sortBy: AlbumArtistListSort.NAME,
|
||||||
sortOrder: SortOrder.ASC,
|
sortOrder: ListSortOrder.ASC,
|
||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
},
|
},
|
||||||
serverId,
|
serverId,
|
||||||
@@ -75,13 +72,13 @@ export const SubsonicAlbumFilters = ({
|
|||||||
|
|
||||||
const genreListQuery = useGenreList({
|
const genreListQuery = useGenreList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 2,
|
gcTime: 1000 * 60 * 2,
|
||||||
staleTime: 1000 * 60 * 1,
|
staleTime: 1000 * 60 * 1,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
sortBy: GenreListSort.NAME,
|
sortBy: GenreListSort.NAME,
|
||||||
sortOrder: SortOrder.ASC,
|
sortOrder: ListSortOrder.ASC,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
serverId,
|
serverId,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import type { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import type { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import type { AlbumDetailQuery } from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { controller } from '/@/renderer/api/controller';
|
import { controller } from '/@/renderer/api/controller';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
|
import { AlbumDetailQuery } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
|
||||||
export const useAlbumDetail = (args: QueryHookArgs<AlbumDetailQuery>) => {
|
export const useAlbumDetail = (args: RQueryHookArgs<AlbumDetailQuery>) => {
|
||||||
const { options, query, serverId } = args;
|
const { options, query, serverId } = args;
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryFn: ({ signal }) => {
|
queryFn: ({ signal }) => {
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import type { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import type { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import type { AlbumListQuery } from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
|
import { AlbumListQuery } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
|
||||||
export const useAlbumListCount = (args: QueryHookArgs<AlbumListQuery>) => {
|
export const useAlbumListCount = (args: RQueryHookArgs<AlbumListQuery>) => {
|
||||||
const { options, query, serverId } = args;
|
const { options, query, serverId } = args;
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!serverId,
|
enabled: !!serverId,
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import type { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import type { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import type { AlbumListQuery, AlbumListResponse } from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
|
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { controller } from '/@/renderer/api/controller';
|
import { controller } from '/@/renderer/api/controller';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
|
import { AlbumListQuery, AlbumListResponse } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
|
||||||
export const useAlbumList = (args: QueryHookArgs<AlbumListQuery>) => {
|
export const useAlbumList = (args: RQueryHookArgs<AlbumListQuery>) => {
|
||||||
const { options, query, serverId } = args;
|
const { options, query, serverId } = args;
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!serverId,
|
enabled: !!serverId,
|
||||||
@@ -33,9 +33,9 @@ export const useAlbumList = (args: QueryHookArgs<AlbumListQuery>) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useAlbumListInfinite = (args: QueryHookArgs<AlbumListQuery>) => {
|
export const useAlbumListInfinite = (args: RQueryHookArgs<AlbumListQuery>) => {
|
||||||
const { options, query, serverId } = args;
|
const { options, query, serverId } = args;
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useInfiniteQuery({
|
return useInfiniteQuery({
|
||||||
enabled: !!serverId,
|
enabled: !!serverId,
|
||||||
@@ -57,7 +57,7 @@ export const useAlbumListInfinite = (args: QueryHookArgs<AlbumListQuery>) => {
|
|||||||
query: {
|
query: {
|
||||||
...query,
|
...query,
|
||||||
limit: query.limit || 50,
|
limit: query.limit || 50,
|
||||||
startIndex: pageParam * (query.limit || 50),
|
offset: pageParam * (query.limit || 50),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { AnimatedPage, LibraryHeaderBar } from '/@/renderer/features/shared';
|
|||||||
import { useFastAverageColor } from '/@/renderer/hooks';
|
import { useFastAverageColor } from '/@/renderer/hooks';
|
||||||
import { useCurrentServer, useGeneralSettings } from '/@/renderer/store';
|
import { useCurrentServer, useGeneralSettings } from '/@/renderer/store';
|
||||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
const AlbumDetailRoute = () => {
|
const AlbumDetailRoute = () => {
|
||||||
const tableRef = useRef<AgGridReactType | null>(null);
|
const tableRef = useRef<AgGridReactType | null>(null);
|
||||||
|
|||||||
@@ -16,12 +16,9 @@ import { usePlayQueueAdd } from '/@/renderer/features/player';
|
|||||||
import { AnimatedPage } from '/@/renderer/features/shared';
|
import { AnimatedPage } from '/@/renderer/features/shared';
|
||||||
import { queryClient } from '/@/renderer/lib/react-query';
|
import { queryClient } from '/@/renderer/lib/react-query';
|
||||||
import { useCurrentServer, useListFilterByKey } from '/@/renderer/store';
|
import { useCurrentServer, useListFilterByKey } from '/@/renderer/store';
|
||||||
import {
|
import { AlbumListQuery } from '/@/shared/types/domain/album-domain-types';
|
||||||
AlbumListQuery,
|
import { GenreListSort } from '/@/shared/types/domain/genre-domain-types';
|
||||||
GenreListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { Play } from '/@/shared/types/types';
|
import { Play } from '/@/shared/types/types';
|
||||||
|
|
||||||
const AlbumListRoute = () => {
|
const AlbumListRoute = () => {
|
||||||
@@ -55,13 +52,13 @@ const AlbumListRoute = () => {
|
|||||||
|
|
||||||
const genreList = useGenreList({
|
const genreList = useGenreList({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 60,
|
gcTime: 1000 * 60 * 60,
|
||||||
enabled: !!genreId,
|
enabled: !!genreId,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
sortBy: GenreListSort.NAME,
|
sortBy: GenreListSort.NAME,
|
||||||
sortOrder: SortOrder.ASC,
|
sortOrder: ListSortOrder.ASC,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
serverId: server?.id,
|
serverId: server?.id,
|
||||||
});
|
});
|
||||||
@@ -77,7 +74,7 @@ const AlbumListRoute = () => {
|
|||||||
|
|
||||||
const itemCountCheck = useAlbumListCount({
|
const itemCountCheck = useAlbumListCount({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60,
|
gcTime: 1000 * 60,
|
||||||
staleTime: 1000 * 60,
|
staleTime: 1000 * 60,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ import { Icon } from '/@/shared/components/icon/icon';
|
|||||||
import { Spoiler } from '/@/shared/components/spoiler/spoiler';
|
import { Spoiler } from '/@/shared/components/spoiler/spoiler';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { LibraryItem, SongDetailResponse } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
import { SongDetailResponse } from '/@/shared/types/domain/song-domain-types';
|
||||||
|
|
||||||
const DummyAlbumDetailRoute = () => {
|
const DummyAlbumDetailRoute = () => {
|
||||||
const cq = useContainerQuery();
|
const cq = useContainerQuery();
|
||||||
|
|||||||
@@ -35,15 +35,10 @@ import { Group } from '/@/shared/components/group/group';
|
|||||||
import { Spoiler } from '/@/shared/components/spoiler/spoiler';
|
import { Spoiler } from '/@/shared/components/spoiler/spoiler';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { TextTitle } from '/@/shared/components/text-title/text-title';
|
import { TextTitle } from '/@/shared/components/text-title/text-title';
|
||||||
import {
|
import { Album, AlbumListSort } from '/@/shared/types/domain/album-domain-types';
|
||||||
Album,
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
AlbumArtist,
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
AlbumListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
|
||||||
QueueSong,
|
|
||||||
ServerType,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { CardRow, Play, TableColumn } from '/@/shared/types/types';
|
import { CardRow, Play, TableColumn } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface AlbumArtistDetailContentProps {
|
interface AlbumArtistDetailContentProps {
|
||||||
@@ -106,8 +101,8 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
|
|||||||
compilation: false,
|
compilation: false,
|
||||||
limit: 15,
|
limit: 15,
|
||||||
sortBy: AlbumListSort.RELEASE_DATE,
|
sortBy: AlbumListSort.RELEASE_DATE,
|
||||||
sortOrder: SortOrder.DESC,
|
sortOrder: ListSortOrder.DESC,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
serverId: server?.id,
|
serverId: server?.id,
|
||||||
});
|
});
|
||||||
@@ -121,8 +116,8 @@ export const AlbumArtistDetailContent = ({ background }: AlbumArtistDetailConten
|
|||||||
compilation: true,
|
compilation: true,
|
||||||
limit: 15,
|
limit: 15,
|
||||||
sortBy: AlbumListSort.RELEASE_DATE,
|
sortBy: AlbumListSort.RELEASE_DATE,
|
||||||
sortOrder: SortOrder.DESC,
|
sortOrder: ListSortOrder.DESC,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
serverId: server?.id,
|
serverId: server?.id,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ import { Group } from '/@/shared/components/group/group';
|
|||||||
import { Rating } from '/@/shared/components/rating/rating';
|
import { Rating } from '/@/shared/components/rating/rating';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { LibraryItem, ServerType } from '/@/shared/types/domain-types';
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
interface AlbumArtistDetailHeaderProps {
|
interface AlbumArtistDetailHeaderProps {
|
||||||
background?: string;
|
background?: string;
|
||||||
|
|||||||
+3
-1
@@ -12,7 +12,9 @@ import { SONG_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/conte
|
|||||||
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
||||||
import { useCurrentServer } from '/@/renderer/store';
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||||
import { LibraryItem, QueueSong, SongListQuery } from '/@/shared/types/domain-types';
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
import { SongListQuery } from '/@/shared/types/domain/song-domain-types';
|
||||||
|
|
||||||
interface AlbumArtistSongListContentProps {
|
interface AlbumArtistSongListContentProps {
|
||||||
data: QueueSong[];
|
data: QueueSong[];
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ import { LibraryHeaderBar } from '/@/renderer/features/shared';
|
|||||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||||
import { Badge } from '/@/shared/components/badge/badge';
|
import { Badge } from '/@/shared/components/badge/badge';
|
||||||
import { SpinnerIcon } from '/@/shared/components/spinner/spinner';
|
import { SpinnerIcon } from '/@/shared/components/spinner/spinner';
|
||||||
import { QueueSong } from '/@/shared/types/domain-types';
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
import { Play } from '/@/shared/types/types';
|
import { Play } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface AlbumArtistDetailTopSongsListHeaderProps {
|
interface AlbumArtistDetailTopSongsListHeaderProps {
|
||||||
|
|||||||
@@ -17,12 +17,11 @@ import { useHandleFavorite } from '/@/renderer/features/shared/hooks/use-handle-
|
|||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
import { useCurrentServer, useListStoreActions, useListStoreByKey } from '/@/renderer/store';
|
import { useCurrentServer, useListStoreActions, useListStoreByKey } from '/@/renderer/store';
|
||||||
import {
|
import {
|
||||||
AlbumArtist,
|
|
||||||
AlbumArtistListQuery,
|
AlbumArtistListQuery,
|
||||||
AlbumArtistListResponse,
|
AlbumArtistListResponse,
|
||||||
AlbumArtistListSort,
|
AlbumArtistListSort,
|
||||||
LibraryItem,
|
} from '/@/shared/types/domain/artist-domain-types';
|
||||||
} from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { CardRow, ListDisplayType } from '/@/shared/types/types';
|
import { CardRow, ListDisplayType } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface AlbumArtistListGridViewProps {
|
interface AlbumArtistListGridViewProps {
|
||||||
|
|||||||
@@ -34,91 +34,90 @@ import { Icon } from '/@/shared/components/icon/icon';
|
|||||||
import {
|
import {
|
||||||
AlbumArtistListQuery,
|
AlbumArtistListQuery,
|
||||||
AlbumArtistListSort,
|
AlbumArtistListSort,
|
||||||
LibraryItem,
|
} from '/@/shared/types/domain/artist-domain-types';
|
||||||
ServerType,
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
SortOrder,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { ListDisplayType } from '/@/shared/types/types';
|
import { ListDisplayType } from '/@/shared/types/types';
|
||||||
|
|
||||||
const FILTERS = {
|
const FILTERS = {
|
||||||
jellyfin: [
|
jellyfin: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.album', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.album', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.ALBUM,
|
value: AlbumArtistListSort.ALBUM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.duration', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.duration', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.DURATION,
|
value: AlbumArtistListSort.DURATION,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.NAME,
|
value: AlbumArtistListSort.NAME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.RANDOM,
|
value: AlbumArtistListSort.RANDOM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.RECENTLY_ADDED,
|
value: AlbumArtistListSort.RECENTLY_ADDED,
|
||||||
},
|
},
|
||||||
// { defaultOrder: SortOrder.DESC, name: 'Release Date', value: AlbumArtistListSort.RELEASE_DATE },
|
// { defaultOrder: ListSortOrder.DESC, name: 'Release Date', value: AlbumArtistListSort.RELEASE_DATE },
|
||||||
],
|
],
|
||||||
navidrome: [
|
navidrome: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.albumCount', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.albumCount', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.ALBUM_COUNT,
|
value: AlbumArtistListSort.ALBUM_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.isFavorited', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.isFavorited', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.FAVORITED,
|
value: AlbumArtistListSort.FAVORITED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.mostPlayed', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.mostPlayed', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.PLAY_COUNT,
|
value: AlbumArtistListSort.PLAY_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.NAME,
|
value: AlbumArtistListSort.NAME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.RATING,
|
value: AlbumArtistListSort.RATING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.songCount', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.songCount', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.SONG_COUNT,
|
value: AlbumArtistListSort.SONG_COUNT,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
subsonic: [
|
subsonic: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.albumCount', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.albumCount', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.ALBUM_COUNT,
|
value: AlbumArtistListSort.ALBUM_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.isFavorited', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.isFavorited', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.FAVORITED,
|
value: AlbumArtistListSort.FAVORITED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.NAME,
|
value: AlbumArtistListSort.NAME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
||||||
value: AlbumArtistListSort.RATING,
|
value: AlbumArtistListSort.RATING,
|
||||||
},
|
},
|
||||||
@@ -270,7 +269,7 @@ export const AlbumArtistListHeaderFilters = ({
|
|||||||
const updatedFilters = setFilter({
|
const updatedFilters = setFilter({
|
||||||
data: {
|
data: {
|
||||||
sortBy: e.currentTarget.value as AlbumArtistListSort,
|
sortBy: e.currentTarget.value as AlbumArtistListSort,
|
||||||
sortOrder: sortOrder || SortOrder.ASC,
|
sortOrder: sortOrder || ListSortOrder.ASC,
|
||||||
},
|
},
|
||||||
itemType: LibraryItem.ALBUM_ARTIST,
|
itemType: LibraryItem.ALBUM_ARTIST,
|
||||||
key: pageKey,
|
key: pageKey,
|
||||||
@@ -306,7 +305,8 @@ export const AlbumArtistListHeaderFilters = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleToggleSortOrder = useCallback(() => {
|
const handleToggleSortOrder = useCallback(() => {
|
||||||
const newSortOrder = filter.sortOrder === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
|
const newSortOrder =
|
||||||
|
filter.sortOrder === ListSortOrder.ASC ? ListSortOrder.DESC : ListSortOrder.ASC;
|
||||||
const updatedFilters = setFilter({
|
const updatedFilters = setFilter({
|
||||||
data: { sortOrder: newSortOrder },
|
data: { sortOrder: newSortOrder },
|
||||||
itemType: LibraryItem.ALBUM_ARTIST,
|
itemType: LibraryItem.ALBUM_ARTIST,
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import { AlbumArtistListFilter, useCurrentServer } from '/@/renderer/store';
|
|||||||
import { Flex } from '/@/shared/components/flex/flex';
|
import { Flex } from '/@/shared/components/flex/flex';
|
||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { AlbumArtistListQuery, LibraryItem } from '/@/shared/types/domain-types';
|
import { AlbumArtistListQuery } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
interface AlbumArtistListHeaderProps {
|
interface AlbumArtistListHeaderProps {
|
||||||
gridRef: MutableRefObject<null | VirtualInfiniteGridRef>;
|
gridRef: MutableRefObject<null | VirtualInfiniteGridRef>;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-
|
|||||||
import { useListContext } from '/@/renderer/context/list-context';
|
import { useListContext } from '/@/renderer/context/list-context';
|
||||||
import { ARTIST_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
|
import { ARTIST_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
|
||||||
import { useCurrentServer } from '/@/renderer/store';
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
interface AlbumArtistListTableViewProps {
|
interface AlbumArtistListTableViewProps {
|
||||||
itemCount?: number;
|
itemCount?: number;
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ import { AppRoute } from '/@/renderer/router/routes';
|
|||||||
import { useCurrentServer, useListStoreActions } from '/@/renderer/store';
|
import { useCurrentServer, useListStoreActions } from '/@/renderer/store';
|
||||||
import { useListStoreByKey } from '/@/renderer/store/list.store';
|
import { useListStoreByKey } from '/@/renderer/store/list.store';
|
||||||
import {
|
import {
|
||||||
AlbumArtist,
|
|
||||||
ArtistListQuery,
|
ArtistListQuery,
|
||||||
ArtistListResponse,
|
ArtistListResponse,
|
||||||
ArtistListSort,
|
ArtistListSort,
|
||||||
LibraryItem,
|
} from '/@/shared/types/domain/artist-domain-types';
|
||||||
} from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { CardRow, ListDisplayType } from '/@/shared/types/types';
|
import { CardRow, ListDisplayType } from '/@/shared/types/types';
|
||||||
|
|
||||||
interface ArtistListGridViewProps {
|
interface ArtistListGridViewProps {
|
||||||
@@ -56,15 +55,11 @@ export const ArtistListGridView = ({ gridRef, itemCount }: ArtistListGridViewPro
|
|||||||
const itemData: AlbumArtist[] = [];
|
const itemData: AlbumArtist[] = [];
|
||||||
|
|
||||||
for (const [, data] of queriesFromCache) {
|
for (const [, data] of queriesFromCache) {
|
||||||
const { items, startIndex } = data || {};
|
const { items, offset } = data || {};
|
||||||
|
|
||||||
if (items && items.length !== 1 && startIndex !== undefined) {
|
if (items && items.length !== 1 && offset !== undefined) {
|
||||||
let itemIndex = 0;
|
let itemIndex = 0;
|
||||||
for (
|
for (let rowIndex = offset; rowIndex < offset + items.length; rowIndex += 1) {
|
||||||
let rowIndex = startIndex;
|
|
||||||
rowIndex < startIndex + items.length;
|
|
||||||
rowIndex += 1
|
|
||||||
) {
|
|
||||||
itemData[rowIndex] = items[itemIndex];
|
itemData[rowIndex] = items[itemIndex];
|
||||||
itemIndex += 1;
|
itemIndex += 1;
|
||||||
}
|
}
|
||||||
@@ -79,7 +74,7 @@ export const ArtistListGridView = ({ gridRef, itemCount }: ArtistListGridViewPro
|
|||||||
const query: ArtistListQuery = {
|
const query: ArtistListQuery = {
|
||||||
...filter,
|
...filter,
|
||||||
limit,
|
limit,
|
||||||
startIndex,
|
offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
const queryKey = queryKeys.artists.list(server?.id || '', query);
|
const queryKey = queryKeys.artists.list(server?.id || '', query);
|
||||||
|
|||||||
@@ -33,93 +33,89 @@ import { Flex } from '/@/shared/components/flex/flex';
|
|||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
import { Icon } from '/@/shared/components/icon/icon';
|
import { Icon } from '/@/shared/components/icon/icon';
|
||||||
import { Select } from '/@/shared/components/select/select';
|
import { Select } from '/@/shared/components/select/select';
|
||||||
import {
|
import { ArtistListQuery, ArtistListSort } from '/@/shared/types/domain/artist-domain-types';
|
||||||
ArtistListQuery,
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
ArtistListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
|
||||||
ServerType,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { ListDisplayType } from '/@/shared/types/types';
|
import { ListDisplayType } from '/@/shared/types/types';
|
||||||
|
|
||||||
const FILTERS = {
|
const FILTERS = {
|
||||||
jellyfin: [
|
jellyfin: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.album', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.album', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.ALBUM,
|
value: ArtistListSort.ALBUM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.duration', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.duration', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.DURATION,
|
value: ArtistListSort.DURATION,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.NAME,
|
value: ArtistListSort.NAME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.random', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.RANDOM,
|
value: ArtistListSort.RANDOM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.recentlyAdded', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.RECENTLY_ADDED,
|
value: ArtistListSort.RECENTLY_ADDED,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
navidrome: [
|
navidrome: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.albumCount', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.albumCount', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.ALBUM_COUNT,
|
value: ArtistListSort.ALBUM_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.isFavorited', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.isFavorited', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.FAVORITED,
|
value: ArtistListSort.FAVORITED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.mostPlayed', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.mostPlayed', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.PLAY_COUNT,
|
value: ArtistListSort.PLAY_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.NAME,
|
value: ArtistListSort.NAME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.RATING,
|
value: ArtistListSort.RATING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.songCount', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.songCount', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.SONG_COUNT,
|
value: ArtistListSort.SONG_COUNT,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
subsonic: [
|
subsonic: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.albumCount', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.albumCount', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.ALBUM_COUNT,
|
value: ArtistListSort.ALBUM_COUNT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.isFavorited', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.isFavorited', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.FAVORITED,
|
value: ArtistListSort.FAVORITED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.NAME,
|
value: ArtistListSort.NAME,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.DESC,
|
defaultOrder: ListSortOrder.DESC,
|
||||||
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.rating', { postProcess: 'titleCase' }),
|
||||||
value: ArtistListSort.RATING,
|
value: ArtistListSort.RATING,
|
||||||
},
|
},
|
||||||
@@ -144,7 +140,7 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF
|
|||||||
const cq = useContainerQuery();
|
const cq = useContainerQuery();
|
||||||
const roles = useRoles({
|
const roles = useRoles({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60 * 60 * 2,
|
gcTime: 1000 * 60 * 60 * 2,
|
||||||
staleTime: 1000 * 60 * 60 * 2,
|
staleTime: 1000 * 60 * 60 * 2,
|
||||||
},
|
},
|
||||||
query: {},
|
query: {},
|
||||||
@@ -192,7 +188,7 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF
|
|||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
limit,
|
limit,
|
||||||
startIndex,
|
offset,
|
||||||
...filters,
|
...filters,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -228,7 +224,7 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF
|
|||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
limit,
|
limit,
|
||||||
startIndex,
|
offset,
|
||||||
...filters,
|
...filters,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -276,7 +272,7 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF
|
|||||||
const updatedFilters = setFilter({
|
const updatedFilters = setFilter({
|
||||||
data: {
|
data: {
|
||||||
sortBy: e.currentTarget.value as ArtistListSort,
|
sortBy: e.currentTarget.value as ArtistListSort,
|
||||||
sortOrder: sortOrder || SortOrder.ASC,
|
sortOrder: sortOrder || ListSortOrder.ASC,
|
||||||
},
|
},
|
||||||
itemType: LibraryItem.ARTIST,
|
itemType: LibraryItem.ARTIST,
|
||||||
key: pageKey,
|
key: pageKey,
|
||||||
@@ -312,7 +308,8 @@ export const ArtistListHeaderFilters = ({ gridRef, tableRef }: ArtistListHeaderF
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleToggleSortOrder = useCallback(() => {
|
const handleToggleSortOrder = useCallback(() => {
|
||||||
const newSortOrder = filter.sortOrder === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
|
const newSortOrder =
|
||||||
|
filter.sortOrder === ListSortOrder.ASC ? ListSortOrder.DESC : ListSortOrder.ASC;
|
||||||
const updatedFilters = setFilter({
|
const updatedFilters = setFilter({
|
||||||
data: { sortOrder: newSortOrder },
|
data: { sortOrder: newSortOrder },
|
||||||
itemType: LibraryItem.ARTIST,
|
itemType: LibraryItem.ARTIST,
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import { ArtistListFilter, useCurrentServer } from '/@/renderer/store';
|
|||||||
import { Flex } from '/@/shared/components/flex/flex';
|
import { Flex } from '/@/shared/components/flex/flex';
|
||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { ArtistListQuery, LibraryItem } from '/@/shared/types/domain-types';
|
import { ArtistListQuery } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
interface ArtistListHeaderProps {
|
interface ArtistListHeaderProps {
|
||||||
gridRef: MutableRefObject<null | VirtualInfiniteGridRef>;
|
gridRef: MutableRefObject<null | VirtualInfiniteGridRef>;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-
|
|||||||
import { useListContext } from '/@/renderer/context/list-context';
|
import { useListContext } from '/@/renderer/context/list-context';
|
||||||
import { ARTIST_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
|
import { ARTIST_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
|
||||||
import { useCurrentServer } from '/@/renderer/store';
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
interface ArtistListTableViewProps {
|
interface ArtistListTableViewProps {
|
||||||
itemCount?: number;
|
itemCount?: number;
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import type { AlbumArtistDetailQuery } from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
|
import { AlbumArtistDetailQuery } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
|
||||||
export const useAlbumArtistDetail = (args: QueryHookArgs<AlbumArtistDetailQuery>) => {
|
export const useAlbumArtistDetail = (args: RQueryHookArgs<AlbumArtistDetailQuery>) => {
|
||||||
const { options, query, serverId } = args || {};
|
const { options, query, serverId } = args || {};
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!server?.id && !!query.id,
|
enabled: !!server?.id && !!query.id,
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { useQuery } from '@tanstack/react-query';
|
|||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
import { AlbumArtistListQuery } from '/@/shared/types/domain-types';
|
import { AlbumArtistListQuery } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
|
||||||
export const useAlbumArtistListCount = (args: QueryHookArgs<AlbumArtistListQuery>) => {
|
export const useAlbumArtistListCount = (args: RQueryHookArgs<AlbumArtistListQuery>) => {
|
||||||
const { options, query, serverId } = args;
|
const { options, query, serverId } = args;
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!serverId,
|
enabled: !!serverId,
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import type { AlbumArtistListQuery } from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
|
import { AlbumArtistListQuery } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
|
||||||
export const useAlbumArtistList = (args: QueryHookArgs<AlbumArtistListQuery>) => {
|
export const useAlbumArtistList = (args: RQueryHookArgs<AlbumArtistListQuery>) => {
|
||||||
const { options, query, serverId } = args || {};
|
const { options, query, serverId } = args || {};
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!server?.id,
|
enabled: !!server?.id,
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import type { AlbumArtistDetailQuery } from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
|
import { AlbumArtistDetailQuery } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
|
||||||
export const useAlbumArtistInfo = (args: QueryHookArgs<AlbumArtistDetailQuery>) => {
|
export const useAlbumArtistInfo = (args: RQueryHookArgs<AlbumArtistDetailQuery>) => {
|
||||||
const { options, query, serverId } = args || {};
|
const { options, query, serverId } = args || {};
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!server?.id && !!query.id,
|
enabled: !!server?.id && !!query.id,
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { useQuery } from '@tanstack/react-query';
|
|||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
import { ArtistListQuery } from '/@/shared/types/domain-types';
|
import { ArtistListQuery } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
|
||||||
export const useArtistListCount = (args: QueryHookArgs<ArtistListQuery>) => {
|
export const useArtistListCount = (args: RQueryHookArgs<ArtistListQuery>) => {
|
||||||
const { options, query, serverId } = args;
|
const { options, query, serverId } = args;
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!serverId,
|
enabled: !!serverId,
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import { useQuery } from '@tanstack/react-query';
|
|||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
|
|
||||||
export const useRoles = (args: QueryHookArgs<object>) => {
|
export const useRoles = (args: RQueryHookArgs<object>) => {
|
||||||
const { options, serverId } = args;
|
const { options, serverId } = args;
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!serverId,
|
enabled: !!serverId,
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import type { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import type { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import type { TopSongListQuery } from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
|
import { TopSongListQuery } from '/@/shared/types/domain/song-domain-types';
|
||||||
|
|
||||||
export const useTopSongsList = (args: QueryHookArgs<TopSongListQuery>) => {
|
export const useTopSongsList = (args: RQueryHookArgs<TopSongListQuery>) => {
|
||||||
const { options, query, serverId } = args || {};
|
const { options, query, serverId } = args || {};
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!server?.id,
|
enabled: !!server?.id,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { AnimatedPage, LibraryHeaderBar } from '/@/renderer/features/shared';
|
|||||||
import { useFastAverageColor } from '/@/renderer/hooks';
|
import { useFastAverageColor } from '/@/renderer/hooks';
|
||||||
import { useCurrentServer } from '/@/renderer/store';
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
const AlbumArtistDetailRoute = () => {
|
const AlbumArtistDetailRoute = () => {
|
||||||
const scrollAreaRef = useRef<HTMLDivElement>(null);
|
const scrollAreaRef = useRef<HTMLDivElement>(null);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { useAlbumArtistDetail } from '/@/renderer/features/artists/queries/album
|
|||||||
import { useTopSongsList } from '/@/renderer/features/artists/queries/top-songs-list-query';
|
import { useTopSongsList } from '/@/renderer/features/artists/queries/top-songs-list-query';
|
||||||
import { AnimatedPage } from '/@/renderer/features/shared';
|
import { AnimatedPage } from '/@/renderer/features/shared';
|
||||||
import { useCurrentServer } from '/@/renderer/store/auth.store';
|
import { useCurrentServer } from '/@/renderer/store/auth.store';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
const AlbumArtistDetailTopSongsListRoute = () => {
|
const AlbumArtistDetailTopSongsListRoute = () => {
|
||||||
const tableRef = useRef<AgGridReactType | null>(null);
|
const tableRef = useRef<AgGridReactType | null>(null);
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import { useAlbumArtistListCount } from '/@/renderer/features/artists/queries/al
|
|||||||
import { AnimatedPage } from '/@/renderer/features/shared';
|
import { AnimatedPage } from '/@/renderer/features/shared';
|
||||||
import { useCurrentServer } from '/@/renderer/store/auth.store';
|
import { useCurrentServer } from '/@/renderer/store/auth.store';
|
||||||
import { useListFilterByKey } from '/@/renderer/store/list.store';
|
import { useListFilterByKey } from '/@/renderer/store/list.store';
|
||||||
import { AlbumArtistListQuery, LibraryItem } from '/@/shared/types/domain-types';
|
import { AlbumArtistListQuery } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
const AlbumArtistListRoute = () => {
|
const AlbumArtistListRoute = () => {
|
||||||
const gridRef = useRef<null | VirtualInfiniteGridRef>(null);
|
const gridRef = useRef<null | VirtualInfiniteGridRef>(null);
|
||||||
@@ -22,7 +23,7 @@ const AlbumArtistListRoute = () => {
|
|||||||
|
|
||||||
const itemCountCheck = useAlbumArtistListCount({
|
const itemCountCheck = useAlbumArtistListCount({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60,
|
gcTime: 1000 * 60,
|
||||||
staleTime: 1000 * 60,
|
staleTime: 1000 * 60,
|
||||||
},
|
},
|
||||||
query: albumArtistListFilter,
|
query: albumArtistListFilter,
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import { useArtistListCount } from '/@/renderer/features/artists/queries/artist-
|
|||||||
import { AnimatedPage } from '/@/renderer/features/shared';
|
import { AnimatedPage } from '/@/renderer/features/shared';
|
||||||
import { useCurrentServer } from '/@/renderer/store/auth.store';
|
import { useCurrentServer } from '/@/renderer/store/auth.store';
|
||||||
import { useListFilterByKey } from '/@/renderer/store/list.store';
|
import { useListFilterByKey } from '/@/renderer/store/list.store';
|
||||||
import { ArtistListQuery, LibraryItem } from '/@/shared/types/domain-types';
|
import { ArtistListQuery } from '/@/shared/types/domain/artist-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
const ArtistListRoute = () => {
|
const ArtistListRoute = () => {
|
||||||
const gridRef = useRef<null | VirtualInfiniteGridRef>(null);
|
const gridRef = useRef<null | VirtualInfiniteGridRef>(null);
|
||||||
@@ -22,7 +23,7 @@ const ArtistListRoute = () => {
|
|||||||
|
|
||||||
const itemCountCheck = useArtistListCount({
|
const itemCountCheck = useArtistListCount({
|
||||||
options: {
|
options: {
|
||||||
cacheTime: 1000 * 60,
|
gcTime: 1000 * 60,
|
||||||
staleTime: 1000 * 60,
|
staleTime: 1000 * 60,
|
||||||
},
|
},
|
||||||
query: artistListFilter,
|
query: artistListFilter,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import { useRemoveFromPlaylist } from '/@/renderer/features/playlists/mutations/
|
|||||||
import { useCreateFavorite, useDeleteFavorite, useSetRating } from '/@/renderer/features/shared';
|
import { useCreateFavorite, useDeleteFavorite, useSetRating } from '/@/renderer/features/shared';
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
import {
|
import {
|
||||||
getServerById,
|
useServerById,
|
||||||
useAuthStore,
|
useAuthStore,
|
||||||
useCurrentServer,
|
useCurrentServer,
|
||||||
usePlayerStore,
|
usePlayerStore,
|
||||||
@@ -57,13 +57,12 @@ import { Rating } from '/@/shared/components/rating/rating';
|
|||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import { toast } from '/@/shared/components/toast/toast';
|
import { toast } from '/@/shared/components/toast/toast';
|
||||||
|
import { ServerFeature, ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
import {
|
import {
|
||||||
AnyLibraryItem,
|
AnyLibraryItem,
|
||||||
AnyLibraryItems,
|
AnyLibraryItems,
|
||||||
LibraryItem,
|
LibraryItem,
|
||||||
ServerType,
|
} from '/@/shared/types/domain/shared-domain-types';
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { ServerFeature } from '/@/shared/types/features-types';
|
|
||||||
import { Play, PlaybackType } from '/@/shared/types/types';
|
import { Play, PlaybackType } from '/@/shared/types/types';
|
||||||
|
|
||||||
type ContextMenuContextProps = {
|
type ContextMenuContextProps = {
|
||||||
@@ -713,7 +712,7 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||||||
const item = ctx.data[0];
|
const item = ctx.data[0];
|
||||||
const songs = await controller.getSimilarSongs({
|
const songs = await controller.getSimilarSongs({
|
||||||
apiClientProps: {
|
apiClientProps: {
|
||||||
server: getServerById(item.serverId),
|
server: useServerById(item.serverId),
|
||||||
signal: undefined,
|
signal: undefined,
|
||||||
},
|
},
|
||||||
query: { albumArtistIds: item.albumArtistIds, songId: item.id },
|
query: { albumArtistIds: item.albumArtistIds, songId: item.id },
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { GridOptions, RowNode } from '@ag-grid-community/core';
|
import { GridOptions, RowNode } from '@ag-grid-community/core';
|
||||||
|
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { createUseExternalEvents } from '/@/shared/utils/create-use-external-events';
|
import { createUseExternalEvents } from '/@/shared/utils/create-use-external-events';
|
||||||
|
|
||||||
export type ContextMenuEvents = {
|
export type ContextMenuEvents = {
|
||||||
|
|||||||
@@ -2,14 +2,11 @@ import { CellContextMenuEvent, GridApi } from '@ag-grid-community/core';
|
|||||||
import sortBy from 'lodash/sortBy';
|
import sortBy from 'lodash/sortBy';
|
||||||
|
|
||||||
import { openContextMenu, SetContextMenuItems } from '/@/renderer/features/context-menu/events';
|
import { openContextMenu, SetContextMenuItems } from '/@/renderer/features/context-menu/events';
|
||||||
import {
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
Album,
|
import { Artist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
AlbumArtist,
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
Artist,
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
import { Song } from '/@/shared/types/domain/song-domain-types';
|
||||||
QueueSong,
|
|
||||||
Song,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
export const useHandleTableContextMenu = (
|
export const useHandleTableContextMenu = (
|
||||||
itemType: LibraryItem,
|
itemType: LibraryItem,
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ import { useCallback, useEffect, useState } from 'react';
|
|||||||
import { controller } from '/@/renderer/api/controller';
|
import { controller } from '/@/renderer/api/controller';
|
||||||
import {
|
import {
|
||||||
DiscordDisplayType,
|
DiscordDisplayType,
|
||||||
getServerById,
|
|
||||||
useAppStore,
|
useAppStore,
|
||||||
useDiscordSettings,
|
useDiscordSettings,
|
||||||
|
useServerById,
|
||||||
useGeneralSettings,
|
useGeneralSettings,
|
||||||
usePlayerStore,
|
usePlayerStore,
|
||||||
} from '/@/renderer/store';
|
} from '/@/renderer/store';
|
||||||
import { QueueSong, ServerType } from '/@/shared/types/domain-types';
|
import { QueueSong } from '/@/shared/types/domain/player-domain-types';
|
||||||
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
import { PlayerStatus } from '/@/shared/types/types';
|
import { PlayerStatus } from '/@/shared/types/types';
|
||||||
|
|
||||||
const discordRpc = isElectron() ? window.api.discordRpc : null;
|
const discordRpc = isElectron() ? window.api.discordRpc : null;
|
||||||
@@ -92,7 +93,7 @@ export const useDiscordRpc = () => {
|
|||||||
if (song.serverType === ServerType.JELLYFIN && song.imageUrl) {
|
if (song.serverType === ServerType.JELLYFIN && song.imageUrl) {
|
||||||
activity.largeImageKey = song.imageUrl;
|
activity.largeImageKey = song.imageUrl;
|
||||||
} else if (song.serverType === ServerType.NAVIDROME) {
|
} else if (song.serverType === ServerType.NAVIDROME) {
|
||||||
const server = getServerById(song.serverId);
|
const server = useServerById(song.serverId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const info = await controller.getAlbumInfo({
|
const info = await controller.getAlbumInfo({
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ import { useListContext } from '/@/renderer/context/list-context';
|
|||||||
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
||||||
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
|
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
|
||||||
import { useCurrentServer, useListStoreActions, useListStoreByKey } from '/@/renderer/store';
|
import { useCurrentServer, useListStoreActions, useListStoreByKey } from '/@/renderer/store';
|
||||||
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
import {
|
import {
|
||||||
Album,
|
|
||||||
Genre,
|
Genre,
|
||||||
GenreListQuery,
|
GenreListQuery,
|
||||||
GenreListResponse,
|
GenreListResponse,
|
||||||
LibraryItem,
|
} from '/@/shared/types/domain/genre-domain-types';
|
||||||
} from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
import { CardRow, ListDisplayType } from '/@/shared/types/types';
|
import { CardRow, ListDisplayType } from '/@/shared/types/types';
|
||||||
|
|
||||||
export const GenreListGridView = ({ gridRef, itemCount }: any) => {
|
export const GenreListGridView = ({ gridRef, itemCount }: any) => {
|
||||||
@@ -74,15 +74,11 @@ export const GenreListGridView = ({ gridRef, itemCount }: any) => {
|
|||||||
const itemData: Genre[] = [];
|
const itemData: Genre[] = [];
|
||||||
|
|
||||||
for (const [, data] of queriesFromCache) {
|
for (const [, data] of queriesFromCache) {
|
||||||
const { items, startIndex } = data || {};
|
const { items, offset } = data || {};
|
||||||
|
|
||||||
if (items && items.length !== 1 && startIndex !== undefined) {
|
if (items && items.length !== 1 && offset !== undefined) {
|
||||||
let itemIndex = 0;
|
let itemIndex = 0;
|
||||||
for (
|
for (let rowIndex = offset; rowIndex < offset + items.length; rowIndex += 1) {
|
||||||
let rowIndex = startIndex;
|
|
||||||
rowIndex < startIndex + items.length;
|
|
||||||
rowIndex += 1
|
|
||||||
) {
|
|
||||||
itemData[rowIndex] = items[itemIndex];
|
itemData[rowIndex] = items[itemIndex];
|
||||||
itemIndex += 1;
|
itemIndex += 1;
|
||||||
}
|
}
|
||||||
@@ -101,7 +97,7 @@ export const GenreListGridView = ({ gridRef, itemCount }: any) => {
|
|||||||
const query: GenreListQuery = {
|
const query: GenreListQuery = {
|
||||||
...filter,
|
...filter,
|
||||||
limit: take,
|
limit: take,
|
||||||
startIndex: skip,
|
offset: skip,
|
||||||
};
|
};
|
||||||
|
|
||||||
const queryKey = queryKeys.albums.list(server?.id || '', query);
|
const queryKey = queryKeys.albums.list(server?.id || '', query);
|
||||||
|
|||||||
@@ -33,33 +33,29 @@ import { DropdownMenu } from '/@/shared/components/dropdown-menu/dropdown-menu';
|
|||||||
import { Flex } from '/@/shared/components/flex/flex';
|
import { Flex } from '/@/shared/components/flex/flex';
|
||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
import { Icon } from '/@/shared/components/icon/icon';
|
import { Icon } from '/@/shared/components/icon/icon';
|
||||||
import {
|
import { GenreListQuery, GenreListSort } from '/@/shared/types/domain/genre-domain-types';
|
||||||
GenreListQuery,
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
GenreListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
|
||||||
ServerType,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { ListDisplayType } from '/@/shared/types/types';
|
import { ListDisplayType } from '/@/shared/types/types';
|
||||||
|
|
||||||
const FILTERS = {
|
const FILTERS = {
|
||||||
jellyfin: [
|
jellyfin: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: GenreListSort.NAME,
|
value: GenreListSort.NAME,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
navidrome: [
|
navidrome: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: GenreListSort.NAME,
|
value: GenreListSort.NAME,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
subsonic: [
|
subsonic: [
|
||||||
{
|
{
|
||||||
defaultOrder: SortOrder.ASC,
|
defaultOrder: ListSortOrder.ASC,
|
||||||
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
name: i18n.t('filter.name', { postProcess: 'titleCase' }),
|
||||||
value: GenreListSort.NAME,
|
value: GenreListSort.NAME,
|
||||||
},
|
},
|
||||||
@@ -137,7 +133,7 @@ export const GenreListHeaderFilters = ({
|
|||||||
customFilters,
|
customFilters,
|
||||||
data: {
|
data: {
|
||||||
sortBy: e.currentTarget.value as GenreListSort,
|
sortBy: e.currentTarget.value as GenreListSort,
|
||||||
sortOrder: sortOrder || SortOrder.ASC,
|
sortOrder: sortOrder || ListSortOrder.ASC,
|
||||||
},
|
},
|
||||||
itemType: LibraryItem.GENRE,
|
itemType: LibraryItem.GENRE,
|
||||||
key: pageKey,
|
key: pageKey,
|
||||||
@@ -175,7 +171,8 @@ export const GenreListHeaderFilters = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleToggleSortOrder = useCallback(() => {
|
const handleToggleSortOrder = useCallback(() => {
|
||||||
const newSortOrder = filter.sortOrder === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC;
|
const newSortOrder =
|
||||||
|
filter.sortOrder === ListSortOrder.ASC ? ListSortOrder.DESC : ListSortOrder.ASC;
|
||||||
const updatedFilters = setFilter({
|
const updatedFilters = setFilter({
|
||||||
customFilters,
|
customFilters,
|
||||||
data: { sortOrder: newSortOrder },
|
data: { sortOrder: newSortOrder },
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import { GenreListFilter, useCurrentServer } from '/@/renderer/store';
|
|||||||
import { Flex } from '/@/shared/components/flex/flex';
|
import { Flex } from '/@/shared/components/flex/flex';
|
||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { GenreListQuery, LibraryItem } from '/@/shared/types/domain-types';
|
import { GenreListQuery } from '/@/shared/types/domain/genre-domain-types';
|
||||||
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
interface GenreListHeaderProps {
|
interface GenreListHeaderProps {
|
||||||
gridRef: MutableRefObject<null | VirtualInfiniteGridRef>;
|
gridRef: MutableRefObject<null | VirtualInfiniteGridRef>;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { useListContext } from '/@/renderer/context/list-context';
|
|||||||
import { GENRE_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
|
import { GENRE_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
|
||||||
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
|
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
|
||||||
import { useCurrentServer } from '/@/renderer/store';
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
interface GenreListTableViewProps {
|
interface GenreListTableViewProps {
|
||||||
itemCount?: number;
|
itemCount?: number;
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import type { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import type { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import type { GenreListQuery } from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
|
import { GenreListQuery } from '/@/shared/types/domain/genre-domain-types';
|
||||||
|
|
||||||
export const useGenreList = (args: QueryHookArgs<GenreListQuery>) => {
|
export const useGenreList = (args: RQueryHookArgs<GenreListQuery>) => {
|
||||||
const { options, query, serverId } = args || {};
|
const { options, query, serverId } = args || {};
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
enabled: !!server,
|
enabled: !!server,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { useGenreList } from '/@/renderer/features/genres/queries/genre-list-que
|
|||||||
import { AnimatedPage } from '/@/renderer/features/shared';
|
import { AnimatedPage } from '/@/renderer/features/shared';
|
||||||
import { useCurrentServer } from '/@/renderer/store';
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
import { useListStoreByKey } from '/@/renderer/store/list.store';
|
import { useListStoreByKey } from '/@/renderer/store/list.store';
|
||||||
import { GenreListQuery } from '/@/shared/types/domain-types';
|
import { GenreListQuery } from '/@/shared/types/domain/genre-domain-types';
|
||||||
|
|
||||||
const GenreListRoute = () => {
|
const GenreListRoute = () => {
|
||||||
const gridRef = useRef<null | VirtualInfiniteGridRef>(null);
|
const gridRef = useRef<null | VirtualInfiniteGridRef>(null);
|
||||||
@@ -23,7 +23,7 @@ const GenreListRoute = () => {
|
|||||||
query: {
|
query: {
|
||||||
...filter,
|
...filter,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
serverId: server?.id,
|
serverId: server?.id,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,19 +2,20 @@ import { useQuery } from '@tanstack/react-query';
|
|||||||
|
|
||||||
import { api } from '/@/renderer/api';
|
import { api } from '/@/renderer/api';
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { QueryHookArgs } from '/@/renderer/lib/react-query';
|
import { RQueryHookArgs } from '/@/renderer/lib/react-query';
|
||||||
import { getServerById } from '/@/renderer/store';
|
import { useServerById } from '/@/renderer/store';
|
||||||
import { AlbumListQuery, AlbumListSort, SortOrder } from '/@/shared/types/domain-types';
|
import { AlbumListQuery, AlbumListSort } from '/@/shared/types/domain/album-domain-types';
|
||||||
|
import { ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
|
|
||||||
export const useRecentlyPlayed = (args: QueryHookArgs<Partial<AlbumListQuery>>) => {
|
export const useRecentlyPlayed = (args: RQueryHookArgs<Partial<AlbumListQuery>>) => {
|
||||||
const { options, query, serverId } = args;
|
const { options, query, serverId } = args;
|
||||||
const server = getServerById(serverId);
|
const server = useServerById(serverId);
|
||||||
|
|
||||||
const requestQuery: AlbumListQuery = {
|
const requestQuery: AlbumListQuery = {
|
||||||
limit: 5,
|
limit: 5,
|
||||||
sortBy: AlbumListSort.RECENTLY_PLAYED,
|
sortBy: AlbumListSort.RECENTLY_PLAYED,
|
||||||
sortOrder: SortOrder.ASC,
|
sortOrder: ListSortOrder.ASC,
|
||||||
startIndex: 0,
|
offset: 0,
|
||||||
...query,
|
...query,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,32 +4,24 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import { FeatureCarousel } from '/@/renderer/components/feature-carousel/feature-carousel';
|
import { FeatureCarousel } from '/@/renderer/components/feature-carousel/feature-carousel';
|
||||||
import { MemoizedSwiperGridCarousel } from '/@/renderer/components/grid-carousel/grid-carousel';
|
|
||||||
import { NativeScrollArea } from '/@/renderer/components/native-scroll-area/native-scroll-area';
|
import { NativeScrollArea } from '/@/renderer/components/native-scroll-area/native-scroll-area';
|
||||||
import { useAlbumList } from '/@/renderer/features/albums';
|
import { useAlbumList } from '/@/renderer/features/albums';
|
||||||
import { useRecentlyPlayed } from '/@/renderer/features/home/queries/recently-played-query';
|
import { useRecentlyPlayed } from '/@/renderer/features/home/queries/recently-played-query';
|
||||||
import { AnimatedPage, LibraryHeaderBar } from '/@/renderer/features/shared';
|
import { AnimatedPage, LibraryHeaderBar } from '/@/renderer/features/shared';
|
||||||
|
import { AlbumInfiniteCarousel } from '/@/renderer/features/shared/components/infinite-album-carousel/infinite-album-carousel';
|
||||||
import { useSongList } from '/@/renderer/features/songs';
|
import { useSongList } from '/@/renderer/features/songs';
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
|
||||||
import {
|
import {
|
||||||
HomeItem,
|
HomeItem,
|
||||||
useCurrentServer,
|
useCurrentServer,
|
||||||
useGeneralSettings,
|
useGeneralSettings,
|
||||||
useWindowSettings,
|
useWindowSettings,
|
||||||
} from '/@/renderer/store';
|
} from '/@/renderer/store';
|
||||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
|
||||||
import { Group } from '/@/shared/components/group/group';
|
|
||||||
import { Icon } from '/@/shared/components/icon/icon';
|
|
||||||
import { Spinner } from '/@/shared/components/spinner/spinner';
|
import { Spinner } from '/@/shared/components/spinner/spinner';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { TextTitle } from '/@/shared/components/text-title/text-title';
|
import { AlbumListSort, AlbumListSortOptions } from '/@/shared/types/domain/album-domain-types';
|
||||||
import {
|
import { ServerType } from '/@/shared/types/domain/server-domain-types';
|
||||||
AlbumListSort,
|
import { LibraryItem, ListSortOrder } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
import { SongListSort } from '/@/shared/types/domain/song-domain-types';
|
||||||
ServerType,
|
|
||||||
SongListSort,
|
|
||||||
SortOrder,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
import { Platform } from '/@/shared/types/types';
|
import { Platform } from '/@/shared/types/types';
|
||||||
|
|
||||||
const HomeRoute = () => {
|
const HomeRoute = () => {
|
||||||
@@ -41,198 +33,198 @@ const HomeRoute = () => {
|
|||||||
const { windowBarStyle } = useWindowSettings();
|
const { windowBarStyle } = useWindowSettings();
|
||||||
const { homeFeature, homeItems } = useGeneralSettings();
|
const { homeFeature, homeItems } = useGeneralSettings();
|
||||||
|
|
||||||
const feature = useAlbumList({
|
// const feature = useAlbumList({
|
||||||
options: {
|
// options: {
|
||||||
cacheTime: 1000 * 60,
|
// enabled: homeFeature,
|
||||||
enabled: homeFeature,
|
// gcTime: 1000 * 60,
|
||||||
staleTime: 1000 * 60,
|
// staleTime: 1000 * 60,
|
||||||
},
|
// },
|
||||||
query: {
|
// query: {
|
||||||
limit: 20,
|
// limit: 20,
|
||||||
sortBy: AlbumListSort.RANDOM,
|
// offset: 0,
|
||||||
sortOrder: SortOrder.DESC,
|
// sortBy: AlbumListSort.RANDOM,
|
||||||
startIndex: 0,
|
// sortOrder: ListSortOrder.DESC,
|
||||||
},
|
// },
|
||||||
serverId: server?.id,
|
// serverId: server?.id,
|
||||||
});
|
// });
|
||||||
|
|
||||||
const featureItemsWithImage = useMemo(() => {
|
// const featureItemsWithImage = useMemo(() => {
|
||||||
return feature.data?.items?.filter((item) => item.imageUrl) ?? [];
|
// return feature.data?.items?.filter((item) => item.imageUrl) ?? [];
|
||||||
}, [feature.data?.items]);
|
// }, [feature.data?.items]);
|
||||||
|
|
||||||
const random = useAlbumList({
|
// const random = useAlbumList({
|
||||||
options: {
|
// options: {
|
||||||
staleTime: 1000 * 60 * 5,
|
// staleTime: 1000 * 60 * 5,
|
||||||
},
|
// },
|
||||||
query: {
|
// query: {
|
||||||
limit: itemsPerPage,
|
// limit: itemsPerPage,
|
||||||
sortBy: AlbumListSort.RANDOM,
|
// offset: 0,
|
||||||
sortOrder: SortOrder.ASC,
|
// sortBy: AlbumListSort.RANDOM,
|
||||||
startIndex: 0,
|
// sortOrder: ListSortOrder.ASC,
|
||||||
},
|
// },
|
||||||
serverId: server?.id,
|
// serverId: server?.id,
|
||||||
});
|
// });
|
||||||
|
|
||||||
const recentlyPlayed = useRecentlyPlayed({
|
// const recentlyPlayed = useRecentlyPlayed({
|
||||||
options: {
|
// options: {
|
||||||
staleTime: 0,
|
// staleTime: 0,
|
||||||
},
|
// },
|
||||||
query: {
|
// query: {
|
||||||
limit: itemsPerPage,
|
// limit: itemsPerPage,
|
||||||
sortBy: AlbumListSort.RECENTLY_PLAYED,
|
// offset: 0,
|
||||||
sortOrder: SortOrder.DESC,
|
// sortBy: AlbumListSort.RECENTLY_PLAYED,
|
||||||
startIndex: 0,
|
// sortOrder: ListSortOrder.DESC,
|
||||||
},
|
// },
|
||||||
serverId: server?.id,
|
// serverId: server?.id,
|
||||||
});
|
// });
|
||||||
|
|
||||||
const recentlyAdded = useAlbumList({
|
// const recentlyAdded = useAlbumList({
|
||||||
options: {
|
// options: {
|
||||||
staleTime: 1000 * 60 * 5,
|
// staleTime: 1000 * 60 * 5,
|
||||||
},
|
// },
|
||||||
query: {
|
// query: {
|
||||||
limit: itemsPerPage,
|
// limit: itemsPerPage,
|
||||||
sortBy: AlbumListSort.RECENTLY_ADDED,
|
// offset: 0,
|
||||||
sortOrder: SortOrder.DESC,
|
// sortBy: AlbumListSort.RECENTLY_ADDED,
|
||||||
startIndex: 0,
|
// sortOrder: ListSortOrder.DESC,
|
||||||
},
|
// },
|
||||||
serverId: server?.id,
|
// serverId: server?.id,
|
||||||
});
|
// });
|
||||||
|
|
||||||
const mostPlayedAlbums = useAlbumList({
|
// const mostPlayedAlbums = useAlbumList({
|
||||||
options: {
|
// options: {
|
||||||
enabled: server?.type === ServerType.SUBSONIC || server?.type === ServerType.NAVIDROME,
|
// enabled: server?.type === ServerType.SUBSONIC || server?.type === ServerType.NAVIDROME,
|
||||||
staleTime: 1000 * 60 * 5,
|
// staleTime: 1000 * 60 * 5,
|
||||||
},
|
// },
|
||||||
query: {
|
// query: {
|
||||||
limit: itemsPerPage,
|
// limit: itemsPerPage,
|
||||||
sortBy: AlbumListSort.PLAY_COUNT,
|
// offset: 0,
|
||||||
sortOrder: SortOrder.DESC,
|
// sortBy: AlbumListSort.PLAY_COUNT,
|
||||||
startIndex: 0,
|
// sortOrder: ListSortOrder.DESC,
|
||||||
},
|
// },
|
||||||
serverId: server?.id,
|
// serverId: server?.id,
|
||||||
});
|
// });
|
||||||
|
|
||||||
const mostPlayedSongs = useSongList(
|
// const mostPlayedSongs = useSongList(
|
||||||
{
|
// {
|
||||||
options: {
|
// options: {
|
||||||
enabled: server?.type === ServerType.JELLYFIN,
|
// enabled: server?.type === ServerType.JELLYFIN,
|
||||||
staleTime: 1000 * 60 * 5,
|
// staleTime: 1000 * 60 * 5,
|
||||||
},
|
// },
|
||||||
query: {
|
// query: {
|
||||||
limit: itemsPerPage,
|
// limit: itemsPerPage,
|
||||||
sortBy: SongListSort.PLAY_COUNT,
|
// offset: 0,
|
||||||
sortOrder: SortOrder.DESC,
|
// sortBy: SongListSort.PLAY_COUNT,
|
||||||
startIndex: 0,
|
// sortOrder: ListSortOrder.DESC,
|
||||||
},
|
// },
|
||||||
serverId: server?.id,
|
// serverId: server?.id,
|
||||||
},
|
// },
|
||||||
300,
|
// 300,
|
||||||
);
|
// );
|
||||||
|
|
||||||
const isLoading =
|
// const isLoading =
|
||||||
random.isLoading ||
|
// random.isLoading ||
|
||||||
recentlyPlayed.isLoading ||
|
// recentlyPlayed.isLoading ||
|
||||||
recentlyAdded.isLoading ||
|
// recentlyAdded.isLoading ||
|
||||||
(server?.type === ServerType.JELLYFIN && mostPlayedSongs.isLoading) ||
|
// (server?.type === ServerType.JELLYFIN && mostPlayedSongs.isLoading) ||
|
||||||
((server?.type === ServerType.SUBSONIC || server?.type === ServerType.NAVIDROME) &&
|
// ((server?.type === ServerType.SUBSONIC || server?.type === ServerType.NAVIDROME) &&
|
||||||
mostPlayedAlbums.isLoading);
|
// mostPlayedAlbums.isLoading);
|
||||||
|
|
||||||
if (isLoading) {
|
// if (isLoading) {
|
||||||
return <Spinner container />;
|
// return <Spinner container />;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const carousels = {
|
// const carousels = {
|
||||||
[HomeItem.MOST_PLAYED]: {
|
// [HomeItem.MOST_PLAYED]: {
|
||||||
data:
|
// data:
|
||||||
server?.type === ServerType.JELLYFIN
|
// server?.type === ServerType.JELLYFIN
|
||||||
? mostPlayedSongs?.data?.items
|
// ? mostPlayedSongs?.data?.items
|
||||||
: mostPlayedAlbums?.data?.items,
|
// : mostPlayedAlbums?.data?.items,
|
||||||
itemType: server?.type === ServerType.JELLYFIN ? LibraryItem.SONG : LibraryItem.ALBUM,
|
// itemType: server?.type === ServerType.JELLYFIN ? LibraryItem.SONG : LibraryItem.ALBUM,
|
||||||
pagination: {
|
// pagination: {
|
||||||
itemsPerPage,
|
// itemsPerPage,
|
||||||
},
|
// },
|
||||||
sortBy:
|
// sortBy:
|
||||||
server?.type === ServerType.JELLYFIN
|
// server?.type === ServerType.JELLYFIN
|
||||||
? SongListSort.PLAY_COUNT
|
// ? SongListSort.PLAY_COUNT
|
||||||
: AlbumListSort.PLAY_COUNT,
|
// : AlbumListSort.PLAY_COUNT,
|
||||||
sortOrder: SortOrder.DESC,
|
// sortOrder: ListSortOrder.DESC,
|
||||||
title: t('page.home.mostPlayed', { postProcess: 'sentenceCase' }),
|
// title: t('page.home.mostPlayed', { postProcess: 'sentenceCase' }),
|
||||||
},
|
// },
|
||||||
[HomeItem.RANDOM]: {
|
// [HomeItem.RANDOM]: {
|
||||||
data: random?.data?.items,
|
// data: random?.data?.items,
|
||||||
itemType: LibraryItem.ALBUM,
|
// itemType: LibraryItem.ALBUM,
|
||||||
sortBy: AlbumListSort.RANDOM,
|
// sortBy: AlbumListSort.RANDOM,
|
||||||
sortOrder: SortOrder.ASC,
|
// sortOrder: ListSortOrder.ASC,
|
||||||
title: t('page.home.explore', { postProcess: 'sentenceCase' }),
|
// title: t('page.home.explore', { postProcess: 'sentenceCase' }),
|
||||||
},
|
// },
|
||||||
[HomeItem.RECENTLY_ADDED]: {
|
// [HomeItem.RECENTLY_ADDED]: {
|
||||||
data: recentlyAdded?.data?.items,
|
// data: recentlyAdded?.data?.items,
|
||||||
itemType: LibraryItem.ALBUM,
|
// itemType: LibraryItem.ALBUM,
|
||||||
pagination: {
|
// pagination: {
|
||||||
itemsPerPage,
|
// itemsPerPage,
|
||||||
},
|
// },
|
||||||
sortBy: AlbumListSort.RECENTLY_ADDED,
|
// sortBy: AlbumListSort.RECENTLY_ADDED,
|
||||||
sortOrder: SortOrder.DESC,
|
// sortOrder: ListSortOrder.DESC,
|
||||||
title: t('page.home.newlyAdded', { postProcess: 'sentenceCase' }),
|
// title: t('page.home.newlyAdded', { postProcess: 'sentenceCase' }),
|
||||||
},
|
// },
|
||||||
[HomeItem.RECENTLY_PLAYED]: {
|
// [HomeItem.RECENTLY_PLAYED]: {
|
||||||
data: recentlyPlayed?.data?.items,
|
// data: recentlyPlayed?.data?.items,
|
||||||
itemType: LibraryItem.ALBUM,
|
// itemType: LibraryItem.ALBUM,
|
||||||
pagination: {
|
// pagination: {
|
||||||
itemsPerPage,
|
// itemsPerPage,
|
||||||
},
|
// },
|
||||||
sortBy: AlbumListSort.RECENTLY_PLAYED,
|
// sortBy: AlbumListSort.RECENTLY_PLAYED,
|
||||||
sortOrder: SortOrder.DESC,
|
// sortOrder: ListSortOrder.DESC,
|
||||||
title: t('page.home.recentlyPlayed', { postProcess: 'sentenceCase' }),
|
// title: t('page.home.recentlyPlayed', { postProcess: 'sentenceCase' }),
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
|
|
||||||
const sortedCarousel = homeItems
|
// const sortedCarousel = homeItems
|
||||||
.filter((item) => {
|
// .filter((item) => {
|
||||||
if (item.disabled) {
|
// if (item.disabled) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
if (server?.type === ServerType.JELLYFIN && item.id === HomeItem.RECENTLY_PLAYED) {
|
// if (server?.type === ServerType.JELLYFIN && item.id === HomeItem.RECENTLY_PLAYED) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
})
|
// })
|
||||||
.map((item) => ({
|
// .map((item) => ({
|
||||||
...carousels[item.id],
|
// ...carousels[item.id],
|
||||||
uniqueId: item.id,
|
// uniqueId: item.id,
|
||||||
}));
|
// }));
|
||||||
|
|
||||||
const invalidateCarouselQuery = (carousel: {
|
// const invalidateCarouselQuery = (carousel: {
|
||||||
itemType: LibraryItem;
|
// itemType: LibraryItem;
|
||||||
sortBy: AlbumListSort | SongListSort;
|
// sortBy: AlbumListSort | SongListSort;
|
||||||
sortOrder: SortOrder;
|
// sortOrder: ListSortOrder;
|
||||||
}) => {
|
// }) => {
|
||||||
if (carousel.itemType === LibraryItem.ALBUM) {
|
// if (carousel.itemType === LibraryItem.ALBUM) {
|
||||||
queryClient.invalidateQueries({
|
// queryClient.invalidateQueries({
|
||||||
exact: false,
|
// exact: false,
|
||||||
queryKey: queryKeys.albums.list(server?.id, {
|
// queryKey: queryKeys.albums.list(server?.id, {
|
||||||
limit: itemsPerPage,
|
// limit: itemsPerPage,
|
||||||
sortBy: carousel.sortBy,
|
// sortBy: carousel.sortBy,
|
||||||
sortOrder: carousel.sortOrder,
|
// sortOrder: carousel.sortOrder,
|
||||||
startIndex: 0,
|
// startIndex: 0,
|
||||||
}),
|
// }),
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (carousel.itemType === LibraryItem.SONG) {
|
// if (carousel.itemType === LibraryItem.SONG) {
|
||||||
queryClient.invalidateQueries({
|
// queryClient.invalidateQueries({
|
||||||
exact: false,
|
// exact: false,
|
||||||
queryKey: queryKeys.songs.list(server?.id, {
|
// queryKey: queryKeys.songs.list(server?.id, {
|
||||||
limit: itemsPerPage,
|
// limit: itemsPerPage,
|
||||||
sortBy: carousel.sortBy,
|
// sortBy: carousel.sortBy,
|
||||||
sortOrder: carousel.sortOrder,
|
// sortOrder: carousel.sortOrder,
|
||||||
startIndex: 0,
|
// startIndex: 0,
|
||||||
}),
|
// }),
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AnimatedPage>
|
<AnimatedPage>
|
||||||
@@ -255,8 +247,16 @@ const HomeRoute = () => {
|
|||||||
pt={windowBarStyle === Platform.WEB ? '5rem' : '3rem'}
|
pt={windowBarStyle === Platform.WEB ? '5rem' : '3rem'}
|
||||||
px="2rem"
|
px="2rem"
|
||||||
>
|
>
|
||||||
{homeFeature && <FeatureCarousel data={featureItemsWithImage} />}
|
{/* {homeFeature && <FeatureCarousel data={featureItemsWithImage} />} */}
|
||||||
{sortedCarousel.map((carousel) => (
|
|
||||||
|
<AlbumInfiniteCarousel
|
||||||
|
serverId={server?.id ?? ''}
|
||||||
|
sortBy={AlbumListSortOptions.NAME}
|
||||||
|
sortOrder={ListSortOrder.ASC}
|
||||||
|
title={t('page.home.explore', { postProcess: 'sentenceCase' })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* {sortedCarousel.map((carousel) => (
|
||||||
<MemoizedSwiperGridCarousel
|
<MemoizedSwiperGridCarousel
|
||||||
cardRows={[
|
cardRows={[
|
||||||
{
|
{
|
||||||
@@ -320,7 +320,7 @@ const HomeRoute = () => {
|
|||||||
}}
|
}}
|
||||||
uniqueId={carousel.uniqueId}
|
uniqueId={carousel.uniqueId}
|
||||||
/>
|
/>
|
||||||
))}
|
))} */}
|
||||||
</Stack>
|
</Stack>
|
||||||
</NativeScrollArea>
|
</NativeScrollArea>
|
||||||
</AnimatedPage>
|
</AnimatedPage>
|
||||||
|
|||||||
@@ -16,18 +16,14 @@ import { Separator } from '/@/shared/components/separator/separator';
|
|||||||
import { Spoiler } from '/@/shared/components/spoiler/spoiler';
|
import { Spoiler } from '/@/shared/components/spoiler/spoiler';
|
||||||
import { Table } from '/@/shared/components/table/table';
|
import { Table } from '/@/shared/components/table/table';
|
||||||
import { Text } from '/@/shared/components/text/text';
|
import { Text } from '/@/shared/components/text/text';
|
||||||
import {
|
import { Album } from '/@/shared/types/domain/album-domain-types';
|
||||||
Album,
|
import { RelatedArtist } from '/@/shared/types/domain/artist-domain-types';
|
||||||
AlbumArtist,
|
import { Playlist } from '/@/shared/types/domain/playlist-domain-types';
|
||||||
AnyLibraryItem,
|
import { AnyLibraryItem, LibraryItem } from '/@/shared/types/domain/shared-domain-types';
|
||||||
LibraryItem,
|
import { Song } from '/@/shared/types/domain/song-domain-types';
|
||||||
Playlist,
|
|
||||||
RelatedArtist,
|
|
||||||
Song,
|
|
||||||
} from '/@/shared/types/domain-types';
|
|
||||||
|
|
||||||
export type ItemDetailsModalProps = {
|
export type ItemDetailsModalProps = {
|
||||||
item: Album | AlbumArtist | Playlist | Song;
|
item: Album | Playlist | Song;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ItemDetailRow<T> = {
|
type ItemDetailRow<T> = {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
InternetProviderLyricSearchResponse,
|
InternetProviderLyricSearchResponse,
|
||||||
LyricSource,
|
LyricSource,
|
||||||
LyricsOverride,
|
LyricsOverride,
|
||||||
} from '/@/shared/types/domain-types';
|
} from '/@/shared/types/domain/lyric-domain-types';
|
||||||
|
|
||||||
interface SearchResultProps {
|
interface SearchResultProps {
|
||||||
data: InternetProviderLyricSearchResponse;
|
data: InternetProviderLyricSearchResponse;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { Group } from '/@/shared/components/group/group';
|
|||||||
import { NumberInput } from '/@/shared/components/number-input/number-input';
|
import { NumberInput } from '/@/shared/components/number-input/number-input';
|
||||||
import { Select } from '/@/shared/components/select/select';
|
import { Select } from '/@/shared/components/select/select';
|
||||||
import { Tooltip } from '/@/shared/components/tooltip/tooltip';
|
import { Tooltip } from '/@/shared/components/tooltip/tooltip';
|
||||||
import { LyricsOverride } from '/@/shared/types/domain-types';
|
import { LyricsOverride } from '/@/shared/types/domain/lyric-domain-types';
|
||||||
|
|
||||||
interface LyricsActionsProps {
|
interface LyricsActionsProps {
|
||||||
index: number;
|
index: number;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user