split between userConfig and userAccount
This commit is contained in:
parent
ad7af09159
commit
d96ac486e4
|
|
@ -28,7 +28,33 @@
|
|||
"prettier": "3.4.2",
|
||||
"typescript": "^5.7.3",
|
||||
"typescript-eslint": "^8.21.0",
|
||||
"vite": "^6.0.11"
|
||||
"vite": "^6.0.11",
|
||||
"vite-plugin-checker": "^0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.26.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
|
||||
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.25.9",
|
||||
"js-tokens": "^4.0.0",
|
||||
"picocolors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
|
||||
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
|
|
@ -1516,6 +1542,32 @@
|
|||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-escapes": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||
"integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"type-fest": "^0.21.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
|
|
@ -1531,6 +1583,20 @@
|
|||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
|
|
@ -1544,6 +1610,19 @@
|
|||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
|
|
@ -1593,6 +1672,44 @@
|
|||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
|
|
@ -1611,6 +1728,16 @@
|
|||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
|
|
@ -2090,6 +2217,21 @@
|
|||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "11.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
|
||||
"integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
|
|
@ -2130,6 +2272,13 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
|
|
@ -2180,6 +2329,19 @@
|
|||
"node": ">=0.8.19"
|
||||
}
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
|
|
@ -2218,6 +2380,13 @@
|
|||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
|
|
@ -2251,6 +2420,19 @@
|
|||
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
|
|
@ -2366,6 +2548,29 @@
|
|||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-path": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
||||
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||
|
|
@ -2611,6 +2816,19 @@
|
|||
"react-dom": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
|
|
@ -2753,6 +2971,19 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-json-comments": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
|
|
@ -2778,6 +3009,13 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-invariant": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
|
||||
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
|
|
@ -2822,6 +3060,19 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "0.21.3",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
|
||||
"integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
|
||||
"dev": true,
|
||||
"license": "(MIT OR CC0-1.0)",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
|
||||
|
|
@ -2859,6 +3110,16 @@
|
|||
"typescript": ">=4.8.4 <5.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
|
|
@ -2941,6 +3202,167 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-checker": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.8.0.tgz",
|
||||
"integrity": "sha512-UA5uzOGm97UvZRTdZHiQVYFnd86AVn8EVaD4L3PoVzxH+IZSfaAw14WGFwX9QS23UW3lV/5bVKZn6l0w+q9P0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.12.13",
|
||||
"ansi-escapes": "^4.3.0",
|
||||
"chalk": "^4.1.1",
|
||||
"chokidar": "^3.5.1",
|
||||
"commander": "^8.0.0",
|
||||
"fast-glob": "^3.2.7",
|
||||
"fs-extra": "^11.1.0",
|
||||
"npm-run-path": "^4.0.1",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"tiny-invariant": "^1.1.0",
|
||||
"vscode-languageclient": "^7.0.0",
|
||||
"vscode-languageserver": "^7.0.0",
|
||||
"vscode-languageserver-textdocument": "^1.0.1",
|
||||
"vscode-uri": "^3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@biomejs/biome": ">=1.7",
|
||||
"eslint": ">=7",
|
||||
"meow": "^9.0.0",
|
||||
"optionator": "^0.9.1",
|
||||
"stylelint": ">=13",
|
||||
"typescript": "*",
|
||||
"vite": ">=2.0.0",
|
||||
"vls": "*",
|
||||
"vti": "*",
|
||||
"vue-tsc": "~2.1.6"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@biomejs/biome": {
|
||||
"optional": true
|
||||
},
|
||||
"eslint": {
|
||||
"optional": true
|
||||
},
|
||||
"meow": {
|
||||
"optional": true
|
||||
},
|
||||
"optionator": {
|
||||
"optional": true
|
||||
},
|
||||
"stylelint": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
},
|
||||
"vls": {
|
||||
"optional": true
|
||||
},
|
||||
"vti": {
|
||||
"optional": true
|
||||
},
|
||||
"vue-tsc": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-jsonrpc": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz",
|
||||
"integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.0.0 || >=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageclient": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz",
|
||||
"integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minimatch": "^3.0.4",
|
||||
"semver": "^7.3.4",
|
||||
"vscode-languageserver-protocol": "3.16.0"
|
||||
},
|
||||
"engines": {
|
||||
"vscode": "^1.52.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageclient/node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageclient/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageserver": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz",
|
||||
"integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"vscode-languageserver-protocol": "3.16.0"
|
||||
},
|
||||
"bin": {
|
||||
"installServerIntoExtension": "bin/installServerIntoExtension"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageserver-protocol": {
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz",
|
||||
"integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"vscode-jsonrpc": "6.0.0",
|
||||
"vscode-languageserver-types": "3.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageserver-textdocument": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz",
|
||||
"integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vscode-languageserver-types": {
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz",
|
||||
"integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vscode-uri": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
|
||||
"integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
"prettier": "3.4.2",
|
||||
"typescript": "^5.7.3",
|
||||
"typescript-eslint": "^8.21.0",
|
||||
"vite": "^6.0.11"
|
||||
"vite": "^6.0.11",
|
||||
"vite-plugin-checker": "^0.8.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,6 @@
|
|||
import { SortByType, SortOrderType, ViewLayoutType } from '../../pages/Home';
|
||||
import APIClient from '../../functions/APIClient';
|
||||
|
||||
export type UserMeType = {
|
||||
id: number;
|
||||
name: string;
|
||||
is_superuser: boolean;
|
||||
is_staff: boolean;
|
||||
groups: [];
|
||||
user_permissions: [];
|
||||
last_login: string;
|
||||
config: UserConfigType;
|
||||
};
|
||||
|
||||
export type ColourVariants = 'dark.css' | 'light.css' | 'matrix.css' | 'midnight.css';
|
||||
|
||||
export type UserConfigType = {
|
||||
|
|
@ -33,7 +22,7 @@ export type UserConfigType = {
|
|||
const updateUserConfig = async (config: Partial<UserConfigType>): Promise<UserConfigType> => {
|
||||
return APIClient('/api/user/me/', {
|
||||
method: 'POST',
|
||||
body: { config: config },
|
||||
body: config,
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
import APIClient from '../../functions/APIClient';
|
||||
import { UserAccountType } from '../../pages/Base';
|
||||
|
||||
const loadUserAccount = async (): Promise<UserAccountType> => {
|
||||
return APIClient('/api/user/account/');
|
||||
};
|
||||
|
||||
export default loadUserAccount;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { UserMeType } from '../actions/updateUserConfig';
|
||||
import { UserConfigType } from '../actions/updateUserConfig';
|
||||
import APIClient from '../../functions/APIClient';
|
||||
|
||||
const loadUserMeConfig = async (): Promise<UserMeType> => {
|
||||
const loadUserMeConfig = async (): Promise<UserConfigType> => {
|
||||
return APIClient('/api/user/me/');
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ type ChannelListProps = {
|
|||
|
||||
const ChannelList = ({ channelList, refreshChannelList }: ChannelListProps) => {
|
||||
const { userConfig } = useUserConfigStore();
|
||||
const viewLayout = userConfig.config.view_style_channel;
|
||||
const viewLayout = userConfig.view_style_channel;
|
||||
|
||||
if (!channelList || channelList.length === 0) {
|
||||
return <p>No channels found.</p>;
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ type DownloadListItemProps = {
|
|||
|
||||
const DownloadListItem = ({ download, setRefresh }: DownloadListItemProps) => {
|
||||
const { userConfig } = useUserConfigStore();
|
||||
const view = userConfig.config.view_style_downloads;
|
||||
const showIgnored = userConfig.config.show_ignored_only;
|
||||
const view = userConfig.view_style_downloads;
|
||||
const showIgnored = userConfig.show_ignored_only;
|
||||
|
||||
const [hideDownload, setHideDownload] = useState(false);
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => {
|
|||
setRefresh(false);
|
||||
}
|
||||
})();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [videoId, refresh]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import iconListView from '/img/icon-listview.svg';
|
|||
import { SortByType, SortOrderType } from '../pages/Home';
|
||||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||
import { ViewStyles } from '../configuration/constants/ViewStyle';
|
||||
import updateUserConfig, { UserConfigType } from '../api/actions/updateUserConfig';
|
||||
|
||||
type FilterbarProps = {
|
||||
hideToggleText: string;
|
||||
|
|
@ -15,9 +16,14 @@ type FilterbarProps = {
|
|||
};
|
||||
|
||||
const Filterbar = ({ hideToggleText, viewStyleName, showSort = true }: FilterbarProps) => {
|
||||
const { userConfig, setPartialConfig } = useUserConfigStore();
|
||||
const { userConfig, setUserConfig } = useUserConfigStore();
|
||||
const [showHidden, setShowHidden] = useState(false);
|
||||
const isGridView = userConfig.config.view_style_home === ViewStyles.grid;
|
||||
const isGridView = userConfig.view_style_home === ViewStyles.grid;
|
||||
|
||||
const handleUserConfigUpdate = async (config: Partial<UserConfigType>) => {
|
||||
const updatedUserConfig = await updateUserConfig(config);
|
||||
setUserConfig(updatedUserConfig);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="view-controls three">
|
||||
|
|
@ -27,13 +33,13 @@ const Filterbar = ({ hideToggleText, viewStyleName, showSort = true }: Filterbar
|
|||
<input
|
||||
id="hide_watched"
|
||||
type="checkbox"
|
||||
checked={userConfig.config.hide_watched}
|
||||
checked={userConfig.hide_watched}
|
||||
onChange={() => {
|
||||
setPartialConfig({ hide_watched: !userConfig.config.hide_watched });
|
||||
handleUserConfigUpdate({ hide_watched: !userConfig.hide_watched });
|
||||
}}
|
||||
/>
|
||||
|
||||
{userConfig.config.hide_watched ? (
|
||||
{userConfig.hide_watched ? (
|
||||
<label htmlFor="" className="onbtn">
|
||||
On
|
||||
</label>
|
||||
|
|
@ -52,9 +58,9 @@ const Filterbar = ({ hideToggleText, viewStyleName, showSort = true }: Filterbar
|
|||
<select
|
||||
name="sort_by"
|
||||
id="sort"
|
||||
value={userConfig.config.sort_by}
|
||||
value={userConfig.sort_by}
|
||||
onChange={event => {
|
||||
setPartialConfig({ sort_by: event.target.value as SortByType });
|
||||
handleUserConfigUpdate({ sort_by: event.target.value as SortByType });
|
||||
}}
|
||||
>
|
||||
<option value="published">date published</option>
|
||||
|
|
@ -67,9 +73,9 @@ const Filterbar = ({ hideToggleText, viewStyleName, showSort = true }: Filterbar
|
|||
<select
|
||||
name="sort_order"
|
||||
id="sort-order"
|
||||
value={userConfig.config.sort_order}
|
||||
value={userConfig.sort_order}
|
||||
onChange={event => {
|
||||
setPartialConfig({ sort_order: event.target.value as SortOrderType });
|
||||
handleUserConfigUpdate({ sort_order: event.target.value as SortOrderType });
|
||||
}}
|
||||
>
|
||||
<option value="asc">asc</option>
|
||||
|
|
@ -90,22 +96,22 @@ const Filterbar = ({ hideToggleText, viewStyleName, showSort = true }: Filterbar
|
|||
/>
|
||||
)}
|
||||
|
||||
{userConfig.config.grid_items !== undefined && isGridView && (
|
||||
{userConfig.grid_items !== undefined && isGridView && (
|
||||
<div className="grid-count">
|
||||
{userConfig.config.grid_items < 7 && (
|
||||
{userConfig.grid_items < 7 && (
|
||||
<img
|
||||
src={iconAdd}
|
||||
onClick={() => {
|
||||
setPartialConfig({ grid_items: userConfig.config.grid_items + 1 });
|
||||
handleUserConfigUpdate({ grid_items: userConfig.grid_items + 1 });
|
||||
}}
|
||||
alt="grid plus row"
|
||||
/>
|
||||
)}
|
||||
{userConfig.config.grid_items > 3 && (
|
||||
{userConfig.grid_items > 3 && (
|
||||
<img
|
||||
src={iconSubstract}
|
||||
onClick={() => {
|
||||
setPartialConfig({ grid_items: userConfig.config.grid_items - 1 });
|
||||
handleUserConfigUpdate({ grid_items: userConfig.grid_items - 1 });
|
||||
}}
|
||||
alt="grid minus row"
|
||||
/>
|
||||
|
|
@ -115,14 +121,14 @@ const Filterbar = ({ hideToggleText, viewStyleName, showSort = true }: Filterbar
|
|||
<img
|
||||
src={iconGridView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ [viewStyleName]: 'grid' });
|
||||
handleUserConfigUpdate({ [viewStyleName]: 'grid' });
|
||||
}}
|
||||
alt="grid view"
|
||||
/>
|
||||
<img
|
||||
src={iconListView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ [viewStyleName]: 'list' });
|
||||
handleUserConfigUpdate({ [viewStyleName]: 'list' });
|
||||
}}
|
||||
alt="list view"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -93,8 +93,10 @@ const GoogleCast = ({ video, setRefresh, onWatchStateChanged }: GoogleCastProps)
|
|||
const [isConnected, setIsConnected] = useState(false);
|
||||
|
||||
const setup = useCallback(() => {
|
||||
const cast = globalThis.cast;
|
||||
const chrome = globalThis.chrome;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const cast = (globalThis as any).cast;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const chrome = (globalThis as any).chrome;
|
||||
|
||||
cast.framework.CastContext.getInstance().setOptions({
|
||||
receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, // Use built in receiver app on cast device, see https://developers.google.com/cast/docs/styled_receiver if you want to be able to add a theme, splash screen or watermark. Has a $5 one time fee.
|
||||
|
|
@ -132,8 +134,10 @@ const GoogleCast = ({ video, setRefresh, onWatchStateChanged }: GoogleCastProps)
|
|||
}, [setRefresh, video]);
|
||||
|
||||
const startPlayback = useCallback(() => {
|
||||
const chrome = globalThis.chrome;
|
||||
const cast = globalThis.cast;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const chrome = (globalThis as any).chrome;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const cast = (globalThis as any).cast;
|
||||
const castSession = cast.framework.CastContext.getInstance().getCurrentSession();
|
||||
|
||||
const mediaUrl = video?.media_url;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ type PlaylistListProps = {
|
|||
|
||||
const PlaylistList = ({ playlistList, setRefresh }: PlaylistListProps) => {
|
||||
const { userConfig } = useUserConfigStore();
|
||||
const viewLayout = userConfig.config.view_style_playlist;
|
||||
const viewLayout = userConfig.view_style_playlist;
|
||||
|
||||
if (!playlistList || playlistList.length === 0) {
|
||||
return <p>No playlists found.</p>;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ const Subtitles = ({ subtitles }: SubtitlesProp) => {
|
|||
const handleTimeUpdate =
|
||||
(
|
||||
youtubeId: string,
|
||||
duration: number,
|
||||
watched: boolean,
|
||||
sponsorBlock?: SponsorBlockType,
|
||||
setSponsorSegmentSkipped?: Dispatch<SetStateAction<SponsorSegmentsSkippedType>>,
|
||||
|
|
@ -337,7 +336,6 @@ const VideoPlayer = ({
|
|||
}}
|
||||
onTimeUpdate={handleTimeUpdate(
|
||||
videoId,
|
||||
duration,
|
||||
watched,
|
||||
sponsorBlock,
|
||||
setSkippedSegments,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const ColourConstant = {
|
|||
|
||||
const useColours = () => {
|
||||
const { userConfig } = useUserConfigStore();
|
||||
const stylesheet = userConfig?.config.stylesheet;
|
||||
const stylesheet = userConfig?.stylesheet;
|
||||
|
||||
switch (stylesheet) {
|
||||
case ColourConstant.Dark:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||
import { useUserAccountStore } from '../stores/UserAccountStore';
|
||||
|
||||
const useIsAdmin = () => {
|
||||
const { userConfig } = useUserConfigStore();
|
||||
const isAdmin = userConfig?.is_staff || userConfig?.is_superuser;
|
||||
const { userAccount } = useUserAccountStore();
|
||||
const isAdmin = userAccount?.is_staff || userAccount?.is_superuser;
|
||||
|
||||
return isAdmin;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import ChannelVideo from './pages/ChannelVideo';
|
|||
import ChannelPlaylist from './pages/ChannelPlaylist';
|
||||
import ChannelAbout from './pages/ChannelAbout';
|
||||
import Download from './pages/Download';
|
||||
import loadUserAccount from './api/loader/loadUserAccount';
|
||||
|
||||
const router = createBrowserRouter(
|
||||
[
|
||||
|
|
@ -41,8 +42,9 @@ const router = createBrowserRouter(
|
|||
const authData = await auth.json();
|
||||
|
||||
const userConfig = await loadUserMeConfig();
|
||||
const userAccount = await loadUserAccount();
|
||||
|
||||
return { userConfig, auth: authData };
|
||||
return { userConfig, userAccount, auth: authData };
|
||||
},
|
||||
element: <Base />,
|
||||
errorElement: <ErrorPage />,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { Outlet, useLoaderData, useLocation, useSearchParams } from 'react-router-dom';
|
||||
import Footer from '../components/Footer';
|
||||
import useColours from '../configuration/colours/useColours';
|
||||
import { UserMeType } from '../api/actions/updateUserConfig';
|
||||
import { UserConfigType } from '../api/actions/updateUserConfig';
|
||||
import { useEffect, useState } from 'react';
|
||||
import Navigation from '../components/Navigation';
|
||||
import { useAuthStore } from '../stores/AuthDataStore';
|
||||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||
import { useUserAccountStore } from '../stores/UserAccountStore';
|
||||
|
||||
export type TaUpdateType = {
|
||||
version?: string;
|
||||
|
|
@ -19,8 +20,19 @@ export type AuthenticationType = {
|
|||
ta_update: TaUpdateType;
|
||||
};
|
||||
|
||||
export type UserAccountType = {
|
||||
id: number;
|
||||
name: string;
|
||||
is_superuser: boolean;
|
||||
is_staff: boolean;
|
||||
groups: [];
|
||||
user_permissions: [];
|
||||
last_login: string;
|
||||
};
|
||||
|
||||
type BaseLoaderData = {
|
||||
userConfig: UserMeType;
|
||||
userConfig: UserConfigType;
|
||||
userAccount: UserAccountType;
|
||||
auth: AuthenticationType;
|
||||
};
|
||||
|
||||
|
|
@ -32,7 +44,8 @@ export type OutletContextType = {
|
|||
const Base = () => {
|
||||
const { setAuth } = useAuthStore();
|
||||
const { setUserConfig } = useUserConfigStore();
|
||||
const { userConfig, auth } = useLoaderData() as BaseLoaderData;
|
||||
const { setUserAccount } = useUserAccountStore();
|
||||
const { userConfig, userAccount, auth } = useLoaderData() as BaseLoaderData;
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
|
|
@ -46,6 +59,7 @@ const Base = () => {
|
|||
useEffect(() => {
|
||||
setAuth(auth);
|
||||
setUserConfig(userConfig);
|
||||
setUserAccount(userAccount);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ const ChannelAbout = () => {
|
|||
<div className="info-box">
|
||||
<div className="info-box-item">
|
||||
<h2>Channel Customization</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<ul>
|
||||
<li>Overwrite the download format over the format set globally.</li>
|
||||
|
|
@ -334,7 +334,7 @@ const ChannelAbout = () => {
|
|||
</div>
|
||||
<div className="info-box-item">
|
||||
<h2>Page Size Overrides</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<p>
|
||||
Disable standard videos, shorts, or streams for this channel by setting their
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ import { PlaylistsResponseType } from './Playlists';
|
|||
import iconGridView from '/img/icon-gridview.svg';
|
||||
import iconListView from '/img/icon-listview.svg';
|
||||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||
import updateUserConfig, { UserConfigType } from '../api/actions/updateUserConfig';
|
||||
|
||||
const ChannelPlaylist = () => {
|
||||
const { channelId } = useParams();
|
||||
const { userConfig, setPartialConfig } = useUserConfigStore();
|
||||
const { userConfig, setUserConfig } = useUserConfigStore();
|
||||
const { currentPage, setCurrentPage } = useOutletContext() as OutletContextType;
|
||||
|
||||
const [refreshPlaylists, setRefreshPlaylists] = useState(false);
|
||||
|
|
@ -23,8 +24,13 @@ const ChannelPlaylist = () => {
|
|||
const playlistList = playlistsResponse?.data;
|
||||
const pagination = playlistsResponse?.paginate;
|
||||
|
||||
const view = userConfig.config.view_style_playlist;
|
||||
const showSubedOnly = userConfig.config.show_subed_only;
|
||||
const view = userConfig.view_style_playlist;
|
||||
const showSubedOnly = userConfig.show_subed_only;
|
||||
|
||||
const handleUserConfigUpdate = async (config: Partial<UserConfigType>) => {
|
||||
const updatedUserConfig = await updateUserConfig(config);
|
||||
setUserConfig(updatedUserConfig);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
|
|
@ -52,7 +58,7 @@ const ChannelPlaylist = () => {
|
|||
<input
|
||||
checked={showSubedOnly}
|
||||
onChange={() => {
|
||||
setPartialConfig({ show_subed_only: !showSubedOnly });
|
||||
handleUserConfigUpdate({ show_subed_only: !showSubedOnly });
|
||||
setRefreshPlaylists(true);
|
||||
}}
|
||||
type="checkbox"
|
||||
|
|
@ -73,14 +79,14 @@ const ChannelPlaylist = () => {
|
|||
<img
|
||||
src={iconGridView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ view_style_playlist: 'grid' });
|
||||
handleUserConfigUpdate({ view_style_playlist: 'grid' });
|
||||
}}
|
||||
alt="grid view"
|
||||
/>
|
||||
<img
|
||||
src={iconListView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ view_style_playlist: 'list' });
|
||||
handleUserConfigUpdate({ view_style_playlist: 'list' });
|
||||
}}
|
||||
alt="list view"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
|
|||
const hasVideos = videoResponse?.data?.length !== 0;
|
||||
const showEmbeddedVideo = videoId !== null;
|
||||
|
||||
const view = userConfig.config.view_style_home;
|
||||
const view = userConfig.view_style_home;
|
||||
const isGridView = view === ViewStyles.grid;
|
||||
const gridView = isGridView ? `boxed-${userConfig.config.grid_items}` : '';
|
||||
const gridViewGrid = isGridView ? `grid-${userConfig.config.grid_items}` : '';
|
||||
const gridView = isGridView ? `boxed-${userConfig.grid_items}` : '';
|
||||
const gridViewGrid = isGridView ? `grid-${userConfig.grid_items}` : '';
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
|
|
@ -60,9 +60,9 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
|
|||
const videos = await loadVideoListByFilter({
|
||||
channel: channelId,
|
||||
page: currentPage,
|
||||
watch: userConfig.config.hide_watched ? 'unwatched' : undefined,
|
||||
sort: userConfig.config.sort_by,
|
||||
order: userConfig.config.sort_order,
|
||||
watch: userConfig.hide_watched ? 'unwatched' : undefined,
|
||||
sort: userConfig.sort_by,
|
||||
order: userConfig.sort_order,
|
||||
type: videoType,
|
||||
});
|
||||
const channelAggs = await loadChannelAggs(channelId);
|
||||
|
|
@ -74,9 +74,9 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
|
|||
})();
|
||||
}, [
|
||||
refresh,
|
||||
userConfig.config.sort_by,
|
||||
userConfig.config.sort_order,
|
||||
userConfig.config.hide_watched,
|
||||
userConfig.sort_by,
|
||||
userConfig.sort_order,
|
||||
userConfig.hide_watched,
|
||||
currentPage,
|
||||
channelId,
|
||||
pagination?.current_page,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import Button from '../components/Button';
|
|||
import updateBulkChannelSubscriptions from '../api/actions/updateBulkChannelSubscriptions';
|
||||
import useIsAdmin from '../functions/useIsAdmin';
|
||||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||
import updateUserConfig, { UserConfigType } from '../api/actions/updateUserConfig';
|
||||
|
||||
type ChannelOverwritesType = {
|
||||
download_format?: string;
|
||||
|
|
@ -48,7 +49,7 @@ type ChannelsListResponse = {
|
|||
};
|
||||
|
||||
const Channels = () => {
|
||||
const { userConfig, setPartialConfig } = useUserConfigStore();
|
||||
const { userConfig, setUserConfig } = useUserConfigStore();
|
||||
const { currentPage, setCurrentPage } = useOutletContext() as OutletContextType;
|
||||
const isAdmin = useIsAdmin();
|
||||
|
||||
|
|
@ -63,18 +64,20 @@ const Channels = () => {
|
|||
// const channelCount = pagination?.total_hits;
|
||||
const hasChannels = channels?.length !== 0;
|
||||
|
||||
const handleUserConfigUpdate = async (config: Partial<UserConfigType>) => {
|
||||
const updatedUserConfig = await updateUserConfig(config);
|
||||
setUserConfig(updatedUserConfig);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const channelListResponse = await loadChannelList(
|
||||
currentPage,
|
||||
userConfig.config.show_subed_only,
|
||||
);
|
||||
const channelListResponse = await loadChannelList(currentPage, userConfig.show_subed_only);
|
||||
|
||||
setChannelListResponse(channelListResponse);
|
||||
setShowNotification(false);
|
||||
setRefresh(false);
|
||||
})();
|
||||
}, [refresh, userConfig.config.show_subed_only, currentPage, pagination?.current_page]);
|
||||
}, [refresh, userConfig.show_subed_only, currentPage, pagination?.current_page]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -145,18 +148,18 @@ const Channels = () => {
|
|||
<input
|
||||
id="show_subed_only"
|
||||
onChange={async () => {
|
||||
setPartialConfig({ show_subed_only: !userConfig.config.show_subed_only });
|
||||
handleUserConfigUpdate({ show_subed_only: !userConfig.show_subed_only });
|
||||
setRefresh(true);
|
||||
}}
|
||||
type="checkbox"
|
||||
checked={userConfig.config.show_subed_only}
|
||||
checked={userConfig.show_subed_only}
|
||||
/>
|
||||
{!userConfig.config.show_subed_only && (
|
||||
{!userConfig.show_subed_only && (
|
||||
<label htmlFor="" className="ofbtn">
|
||||
Off
|
||||
</label>
|
||||
)}
|
||||
{userConfig.config.show_subed_only && (
|
||||
{userConfig.show_subed_only && (
|
||||
<label htmlFor="" className="onbtn">
|
||||
On
|
||||
</label>
|
||||
|
|
@ -167,7 +170,7 @@ const Channels = () => {
|
|||
<img
|
||||
src={iconGridView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ view_style_channel: 'grid' });
|
||||
handleUserConfigUpdate({ view_style_channel: 'grid' });
|
||||
}}
|
||||
data-origin="channel"
|
||||
data-value="grid"
|
||||
|
|
@ -176,7 +179,7 @@ const Channels = () => {
|
|||
<img
|
||||
src={iconListView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ view_style_channel: 'list' });
|
||||
handleUserConfigUpdate({ view_style_channel: 'list' });
|
||||
}}
|
||||
data-origin="channel"
|
||||
data-value="list"
|
||||
|
|
@ -186,7 +189,7 @@ const Channels = () => {
|
|||
</div>
|
||||
{/* {hasChannels && <h2>Total channels: {channelCount}</h2>} */}
|
||||
|
||||
<div className={`channel-list ${userConfig.config.view_style_channel}`}>
|
||||
<div className={`channel-list ${userConfig.view_style_channel}`}>
|
||||
{!hasChannels && <h2>No channels found...</h2>}
|
||||
|
||||
{hasChannels && <ChannelList channelList={channels} refreshChannelList={setRefresh} />}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import Button from '../components/Button';
|
|||
import DownloadListItem from '../components/DownloadListItem';
|
||||
import loadDownloadAggs, { DownloadAggsType } from '../api/loader/loadDownloadAggs';
|
||||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||
import updateUserConfig, { UserConfigType } from '../api/actions/updateUserConfig';
|
||||
|
||||
type Download = {
|
||||
auto_start: boolean;
|
||||
|
|
@ -46,7 +47,7 @@ export type DownloadResponseType = {
|
|||
|
||||
const Download = () => {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const { userConfig, setPartialConfig } = useUserConfigStore();
|
||||
const { userConfig, setUserConfig } = useUserConfigStore();
|
||||
const { currentPage, setCurrentPage } = useOutletContext() as OutletContextType;
|
||||
|
||||
const channelFilterFromUrl = searchParams.get('channel');
|
||||
|
|
@ -75,13 +76,18 @@ const Download = () => {
|
|||
? downloadResponse?.data[0].channel_name
|
||||
: '';
|
||||
|
||||
const view = userConfig.config.view_style_downloads;
|
||||
const gridItems = userConfig.config.grid_items;
|
||||
const showIgnored = userConfig.config.show_ignored_only;
|
||||
const view = userConfig.view_style_downloads;
|
||||
const gridItems = userConfig.grid_items;
|
||||
const showIgnored = userConfig.show_ignored_only;
|
||||
const isGridView = view === ViewStyles.grid;
|
||||
const gridView = isGridView ? `boxed-${gridItems}` : '';
|
||||
const gridViewGrid = isGridView ? `grid-${gridItems}` : '';
|
||||
|
||||
const handleUserConfigUpdate = async (config: Partial<UserConfigType>) => {
|
||||
const updatedUserConfig = await updateUserConfig(config);
|
||||
setUserConfig(updatedUserConfig);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const videos = await loadDownloadQueue(currentPage, channelFilterFromUrl, showIgnored);
|
||||
|
|
@ -208,7 +214,7 @@ const Download = () => {
|
|||
<input
|
||||
id="showIgnored"
|
||||
onChange={() => {
|
||||
setPartialConfig({ show_ignored_only: !showIgnored });
|
||||
handleUserConfigUpdate({ show_ignored_only: !showIgnored });
|
||||
setRefresh(true);
|
||||
}}
|
||||
type="checkbox"
|
||||
|
|
@ -263,7 +269,7 @@ const Download = () => {
|
|||
<img
|
||||
src={iconAdd}
|
||||
onClick={() => {
|
||||
setPartialConfig({ grid_items: gridItems + 1 });
|
||||
handleUserConfigUpdate({ grid_items: gridItems + 1 });
|
||||
}}
|
||||
alt="grid plus row"
|
||||
/>
|
||||
|
|
@ -272,7 +278,7 @@ const Download = () => {
|
|||
<img
|
||||
src={iconSubstract}
|
||||
onClick={() => {
|
||||
setPartialConfig({ grid_items: gridItems - 1 });
|
||||
handleUserConfigUpdate({ grid_items: gridItems - 1 });
|
||||
}}
|
||||
alt="grid minus row"
|
||||
/>
|
||||
|
|
@ -283,14 +289,14 @@ const Download = () => {
|
|||
<img
|
||||
src={iconGridView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ view_style_downloads: 'grid' });
|
||||
handleUserConfigUpdate({ view_style_downloads: 'grid' });
|
||||
}}
|
||||
alt="grid view"
|
||||
/>
|
||||
<img
|
||||
src={iconListView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ view_style_downloads: 'list' });
|
||||
handleUserConfigUpdate({ view_style_downloads: 'list' });
|
||||
}}
|
||||
alt="list view"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -108,8 +108,6 @@ const Home = () => {
|
|||
const [searchParams] = useSearchParams();
|
||||
const videoId = searchParams.get('videoId');
|
||||
|
||||
const userMeConfig = userConfig.config;
|
||||
|
||||
const [refreshVideoList, setRefreshVideoList] = useState(false);
|
||||
|
||||
const [videoResponse, setVideoReponse] = useState<VideoListByFilterResponseType>();
|
||||
|
|
@ -123,17 +121,17 @@ const Home = () => {
|
|||
const hasVideos = videoResponse?.data?.length !== 0;
|
||||
const showEmbeddedVideo = videoId !== null;
|
||||
|
||||
const isGridView = userMeConfig.view_style_home === ViewStyles.grid;
|
||||
const gridView = isGridView ? `boxed-${userMeConfig.grid_items}` : '';
|
||||
const gridViewGrid = isGridView ? `grid-${userMeConfig.grid_items}` : '';
|
||||
const isGridView = userConfig.view_style_home === ViewStyles.grid;
|
||||
const gridView = isGridView ? `boxed-${userConfig.grid_items}` : '';
|
||||
const gridViewGrid = isGridView ? `grid-${userConfig.grid_items}` : '';
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const videos = await loadVideoListByFilter({
|
||||
page: currentPage,
|
||||
watch: userMeConfig.hide_watched ? 'unwatched' : undefined,
|
||||
sort: userMeConfig.sort_by,
|
||||
order: userMeConfig.sort_order,
|
||||
watch: userConfig.hide_watched ? 'unwatched' : undefined,
|
||||
sort: userConfig.sort_by,
|
||||
order: userConfig.sort_order,
|
||||
});
|
||||
|
||||
try {
|
||||
|
|
@ -150,9 +148,9 @@ const Home = () => {
|
|||
})();
|
||||
}, [
|
||||
refreshVideoList,
|
||||
userMeConfig.sort_by,
|
||||
userMeConfig.sort_order,
|
||||
userMeConfig.hide_watched,
|
||||
userConfig.sort_by,
|
||||
userConfig.sort_order,
|
||||
userConfig.hide_watched,
|
||||
currentPage,
|
||||
pagination?.current_page,
|
||||
showEmbeddedVideo,
|
||||
|
|
@ -171,10 +169,10 @@ const Home = () => {
|
|||
<div className="title-bar">
|
||||
<h1>Continue Watching</h1>
|
||||
</div>
|
||||
<div className={`video-list ${userMeConfig.view_style_home} ${gridViewGrid}`}>
|
||||
<div className={`video-list ${userConfig.view_style_home} ${gridViewGrid}`}>
|
||||
<VideoList
|
||||
videoList={continueVideos}
|
||||
viewLayout={userMeConfig.view_style_home}
|
||||
viewLayout={userConfig.view_style_home}
|
||||
refreshVideoList={setRefreshVideoList}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -189,7 +187,7 @@ const Home = () => {
|
|||
</div>
|
||||
|
||||
<div className={`boxed-content ${gridView}`}>
|
||||
<div className={`video-list ${userMeConfig.view_style_home} ${gridViewGrid}`}>
|
||||
<div className={`video-list ${userConfig.view_style_home} ${gridViewGrid}`}>
|
||||
{!hasVideos && (
|
||||
<>
|
||||
<h2>No videos found...</h2>
|
||||
|
|
@ -204,7 +202,7 @@ const Home = () => {
|
|||
{hasVideos && (
|
||||
<VideoList
|
||||
videoList={videoList}
|
||||
viewLayout={userMeConfig.view_style_home}
|
||||
viewLayout={userConfig.view_style_home}
|
||||
refreshVideoList={setRefreshVideoList}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -81,9 +81,9 @@ const Playlist = () => {
|
|||
const videoInPlaylistCount = pagination?.total_hits;
|
||||
const showEmbeddedVideo = videoId !== null;
|
||||
|
||||
const view = userConfig.config.view_style_home;
|
||||
const gridItems = userConfig.config.grid_items;
|
||||
const hideWatched = userConfig.config.hide_watched;
|
||||
const view = userConfig.view_style_home;
|
||||
const gridItems = userConfig.grid_items;
|
||||
const hideWatched = userConfig.hide_watched;
|
||||
const isGridView = view === ViewStyles.grid;
|
||||
const gridView = isGridView ? `boxed-${gridItems}` : '';
|
||||
const gridViewGrid = isGridView ? `grid-${gridItems}` : '';
|
||||
|
|
@ -112,7 +112,7 @@ const Playlist = () => {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
playlistId,
|
||||
userConfig.config.hide_watched,
|
||||
userConfig.hide_watched,
|
||||
refresh,
|
||||
currentPage,
|
||||
pagination?.current_page,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import Button from '../components/Button';
|
|||
import useIsAdmin from '../functions/useIsAdmin';
|
||||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||
import Notifications from '../components/Notifications';
|
||||
import updateUserConfig, { UserConfigType } from '../api/actions/updateUserConfig';
|
||||
|
||||
export type PlaylistEntryType = {
|
||||
youtube_id: string;
|
||||
|
|
@ -34,7 +35,7 @@ export type PlaylistsResponseType = {
|
|||
};
|
||||
|
||||
const Playlists = () => {
|
||||
const { userConfig, setPartialConfig } = useUserConfigStore();
|
||||
const { userConfig, setUserConfig } = useUserConfigStore();
|
||||
const { currentPage, setCurrentPage } = useOutletContext() as OutletContextType;
|
||||
const isAdmin = useIsAdmin();
|
||||
|
||||
|
|
@ -51,8 +52,8 @@ const Playlists = () => {
|
|||
|
||||
const hasPlaylists = playlistResponse?.data?.length !== 0;
|
||||
|
||||
const view = userConfig.config.view_style_playlist;
|
||||
const showSubedOnly = userConfig.config.show_subed_only;
|
||||
const view = userConfig.view_style_playlist;
|
||||
const showSubedOnly = userConfig.show_subed_only;
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
|
|
@ -66,7 +67,12 @@ const Playlists = () => {
|
|||
setShowNotification(false);
|
||||
})();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [refresh, userConfig.config.show_subed_only, currentPage, pagination?.current_page]);
|
||||
}, [refresh, userConfig.show_subed_only, currentPage, pagination?.current_page]);
|
||||
|
||||
const handleUserConfigUpdate = async (config: Partial<UserConfigType>) => {
|
||||
const updatedUserConfig = await updateUserConfig(config);
|
||||
setUserConfig(updatedUserConfig);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -156,7 +162,7 @@ const Playlists = () => {
|
|||
<input
|
||||
checked={showSubedOnly}
|
||||
onChange={() => {
|
||||
setPartialConfig({ show_subed_only: !showSubedOnly });
|
||||
handleUserConfigUpdate({ show_subed_only: !showSubedOnly });
|
||||
}}
|
||||
type="checkbox"
|
||||
/>
|
||||
|
|
@ -176,14 +182,14 @@ const Playlists = () => {
|
|||
<img
|
||||
src={iconGridView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ view_style_playlist: 'grid' });
|
||||
handleUserConfigUpdate({ view_style_playlist: 'grid' });
|
||||
}}
|
||||
alt="grid view"
|
||||
/>
|
||||
<img
|
||||
src={iconListView}
|
||||
onClick={() => {
|
||||
setPartialConfig({ view_style_playlist: 'list' });
|
||||
handleUserConfigUpdate({ view_style_playlist: 'list' });
|
||||
}}
|
||||
alt="list view"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -39,12 +39,11 @@ const Search = () => {
|
|||
const { userConfig } = useUserConfigStore();
|
||||
const [searchParams] = useSearchParams();
|
||||
const videoId = searchParams.get('videoId');
|
||||
const userMeConfig = userConfig.config;
|
||||
|
||||
const viewVideos = userMeConfig.view_style_home;
|
||||
const viewChannels = userMeConfig.view_style_channel;
|
||||
const viewPlaylists = userMeConfig.view_style_playlist;
|
||||
const gridItems = userMeConfig.grid_items || 3;
|
||||
const viewVideos = userConfig.view_style_home;
|
||||
const viewChannels = userConfig.view_style_channel;
|
||||
const viewPlaylists = userConfig.view_style_playlist;
|
||||
const gridItems = userConfig.grid_items || 3;
|
||||
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState<string>('');
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ const SettingsApplication = () => {
|
|||
<div className="info-box">
|
||||
<div className="info-box-item">
|
||||
<h2 id="subscriptions">Subscription Scan</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<p>Configure how a subscription Scan tracks videos.</p>
|
||||
<ul>
|
||||
|
|
@ -275,7 +275,7 @@ const SettingsApplication = () => {
|
|||
</div>
|
||||
<div className="info-box-item">
|
||||
<h2 id="downloads">Downloads</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<ul>
|
||||
<li>
|
||||
|
|
@ -362,7 +362,7 @@ const SettingsApplication = () => {
|
|||
</div>
|
||||
<div className="info-box-item">
|
||||
<h2 id="format">Download Format</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<ul>
|
||||
<li>
|
||||
|
|
@ -507,7 +507,7 @@ const SettingsApplication = () => {
|
|||
</div>
|
||||
<div className="info-box-item">
|
||||
<h2 id="subtitles">Subtitles</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<p>Additional subtitle options show once you choose a language.</p>
|
||||
<ul>
|
||||
|
|
@ -586,7 +586,7 @@ const SettingsApplication = () => {
|
|||
</div>
|
||||
<div className="info-box-item">
|
||||
<h2 id="comments">Comments</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<p>Additional options show once you set a comment index option.</p>
|
||||
<ul>
|
||||
|
|
@ -650,7 +650,7 @@ const SettingsApplication = () => {
|
|||
</div>
|
||||
<div className="info-box-item">
|
||||
<h2 id="cookie">Cookie</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<p>
|
||||
Importing your cookie will authenticate requests to YT with your user account.
|
||||
|
|
@ -777,7 +777,7 @@ const SettingsApplication = () => {
|
|||
</div>
|
||||
<div className="info-box-item">
|
||||
<h2 id="sntegrations">Integrations</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<ul>
|
||||
<li>The API token is used to make automater requests to TA through the API.</li>
|
||||
|
|
@ -868,7 +868,7 @@ const SettingsApplication = () => {
|
|||
</div>
|
||||
<div className="info-box-item">
|
||||
<h2>Snapshots</h2>
|
||||
{userConfig.config.show_help_text && (
|
||||
{userConfig.show_help_text && (
|
||||
<div className="help-text">
|
||||
<p>
|
||||
Automatically create daily deduplicated snapshots of the index, stored in
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
import { ColourVariants } from '../api/actions/updateUserConfig';
|
||||
import updateUserConfig, { ColourVariants, UserConfigType } from '../api/actions/updateUserConfig';
|
||||
import { ColourConstant } from '../configuration/colours/useColours';
|
||||
import SettingsNavigation from '../components/SettingsNavigation';
|
||||
import Notifications from '../components/Notifications';
|
||||
|
|
@ -10,35 +10,40 @@ import { useEffect, useState } from 'react';
|
|||
import ToggleConfig from '../components/ToggleConfig';
|
||||
|
||||
const SettingsUser = () => {
|
||||
const { userConfig, setPartialConfig } = useUserConfigStore();
|
||||
const { userConfig, setUserConfig } = useUserConfigStore();
|
||||
const isAdmin = useIsAdmin();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [styleSheet, setStyleSheet] = useState<ColourVariants>(userConfig.config.stylesheet);
|
||||
const [styleSheet, setStyleSheet] = useState<ColourVariants>(userConfig.stylesheet);
|
||||
const [styleSheetRefresh, setStyleSheetRefresh] = useState(false);
|
||||
const [pageSize, setPageSize] = useState<number>(userConfig.config.page_size);
|
||||
const [showHelpText, setShowHelpText] = useState(userConfig.config.show_help_text);
|
||||
const [pageSize, setPageSize] = useState<number>(userConfig.page_size);
|
||||
const [showHelpText, setShowHelpText] = useState(userConfig.show_help_text);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setStyleSheet(userConfig.config.stylesheet);
|
||||
setPageSize(userConfig.config.page_size);
|
||||
setShowHelpText(userConfig.config.show_help_text);
|
||||
setStyleSheet(userConfig.stylesheet);
|
||||
setPageSize(userConfig.page_size);
|
||||
setShowHelpText(userConfig.show_help_text);
|
||||
})();
|
||||
}, [userConfig.config.page_size, userConfig.config.stylesheet, userConfig.config.show_help_text]);
|
||||
}, [userConfig.page_size, userConfig.stylesheet, userConfig.show_help_text]);
|
||||
|
||||
const handleStyleSheetChange = async (selectedStyleSheet: ColourVariants) => {
|
||||
setPartialConfig({ stylesheet: selectedStyleSheet });
|
||||
handleUserConfigUpdate({ stylesheet: selectedStyleSheet });
|
||||
setStyleSheet(selectedStyleSheet);
|
||||
setStyleSheetRefresh(true);
|
||||
};
|
||||
|
||||
const handlePageSizeChange = async () => {
|
||||
setPartialConfig({ page_size: pageSize });
|
||||
handleUserConfigUpdate({ page_size: pageSize });
|
||||
};
|
||||
|
||||
const handleShowHelpTextChange = async (configKey: string, configValue: boolean) => {
|
||||
setPartialConfig({ [configKey]: configValue });
|
||||
handleUserConfigUpdate({ [configKey]: configValue });
|
||||
};
|
||||
|
||||
const handleUserConfigUpdate = async (config: Partial<UserConfigType>) => {
|
||||
const updatedUserConfig = await updateUserConfig(config);
|
||||
setUserConfig(updatedUserConfig);
|
||||
};
|
||||
|
||||
const handlePageRefresh = () => {
|
||||
|
|
@ -99,12 +104,10 @@ const SettingsUser = () => {
|
|||
/>
|
||||
|
||||
<div className="button-box">
|
||||
{userConfig.config.page_size !== pageSize && (
|
||||
{userConfig.page_size !== pageSize && (
|
||||
<>
|
||||
<button onClick={handlePageSizeChange}>Update</button>
|
||||
<button onClick={() => setPageSize(userConfig.config.page_size)}>
|
||||
Cancel
|
||||
</button>
|
||||
<button onClick={() => setPageSize(userConfig.page_size)}>Cancel</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
import { create } from 'zustand';
|
||||
import { UserAccountType } from '../pages/Base';
|
||||
|
||||
interface AccountState {
|
||||
userAccount: UserAccountType | null;
|
||||
setUserAccount: (userAccount: UserAccountType) => void;
|
||||
}
|
||||
|
||||
export const useUserAccountStore = create<AccountState>(set => ({
|
||||
userAccount: null,
|
||||
setUserAccount: userAccount => set({ userAccount }),
|
||||
}));
|
||||
|
|
@ -1,45 +1,26 @@
|
|||
import { create } from 'zustand';
|
||||
import updateUserConfig, { UserMeType, UserConfigType } from '../api/actions/updateUserConfig';
|
||||
import { UserConfigType } from '../api/actions/updateUserConfig';
|
||||
|
||||
interface UserConfigState {
|
||||
userConfig: UserMeType;
|
||||
setUserConfig: (userConfig: UserMeType) => void;
|
||||
setPartialConfig: (userConfig: Partial<UserConfigType>) => void;
|
||||
userConfig: UserConfigType;
|
||||
setUserConfig: (userConfig: UserConfigType) => void;
|
||||
}
|
||||
|
||||
export const useUserConfigStore = create<UserConfigState>(set => ({
|
||||
userConfig: {
|
||||
id: 0,
|
||||
name: '',
|
||||
is_superuser: false,
|
||||
is_staff: false,
|
||||
groups: [],
|
||||
user_permissions: [],
|
||||
last_login: '',
|
||||
config: {
|
||||
stylesheet: 'dark.css',
|
||||
page_size: 12,
|
||||
sort_by: 'published',
|
||||
sort_order: 'desc',
|
||||
view_style_home: 'grid',
|
||||
view_style_channel: 'list',
|
||||
view_style_downloads: 'list',
|
||||
view_style_playlist: 'grid',
|
||||
grid_items: 3,
|
||||
hide_watched: false,
|
||||
show_ignored_only: false,
|
||||
show_subed_only: false,
|
||||
show_help_text: true,
|
||||
},
|
||||
stylesheet: 'dark.css',
|
||||
page_size: 12,
|
||||
sort_by: 'published',
|
||||
sort_order: 'desc',
|
||||
view_style_home: 'grid',
|
||||
view_style_channel: 'list',
|
||||
view_style_downloads: 'list',
|
||||
view_style_playlist: 'grid',
|
||||
grid_items: 3,
|
||||
hide_watched: false,
|
||||
show_ignored_only: false,
|
||||
show_subed_only: false,
|
||||
show_help_text: true,
|
||||
},
|
||||
setUserConfig: userConfig => set({ userConfig }),
|
||||
|
||||
setPartialConfig: async (userConfig: Partial<UserConfigType>) => {
|
||||
const userConfigResponse = await updateUserConfig(userConfig);
|
||||
set(state => ({
|
||||
userConfig: state.userConfig
|
||||
? { ...state.userConfig, config: userConfigResponse }
|
||||
: state.userConfig,
|
||||
}));
|
||||
},
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react-swc';
|
||||
import checker from 'vite-plugin-checker';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
plugins: [react(), checker({ typescript: true })],
|
||||
base: '/',
|
||||
server: {
|
||||
host: true,
|
||||
|
|
|
|||
Loading…
Reference in New Issue