mirror of
https://github.com/SrIzan10/osu-radio.git
synced 2026-05-01 10:55:12 +00:00
chore: update ESLint config (#80)
Co-authored-by: dudubtw <carloseduardo108090@hotmail.com>
This commit is contained in:
committed by
GitHub
parent
0778a3d306
commit
5eb6a34397
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
uses: ./.github/actions/setup
|
||||
|
||||
- name: Run Eslint
|
||||
run: npm run lint:check
|
||||
run: npm run lint
|
||||
|
||||
format:
|
||||
timeout-minutes: 10
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
/** @type {import("prettier").Options} */
|
||||
export default {
|
||||
printWidth: 100,
|
||||
plugins: ["@trivago/prettier-plugin-sort-imports", "prettier-plugin-tailwindcss"],
|
||||
plugins: [
|
||||
"@trivago/prettier-plugin-sort-imports",
|
||||
"prettier-plugin-tailwindcss",
|
||||
"prettier-plugin-packagejson",
|
||||
],
|
||||
};
|
||||
|
||||
21
eslint.config.js
Normal file
21
eslint.config.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import eslint from "@eslint/js";
|
||||
import solid from "eslint-plugin-solid";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
{
|
||||
ignores: ["**/out", "**/build", "**/dist"],
|
||||
},
|
||||
{
|
||||
files: ["**/*"],
|
||||
rules: {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["src/renderer/**/*.tsx"],
|
||||
...solid.configs["flat/recommended"],
|
||||
},
|
||||
);
|
||||
@@ -1,37 +0,0 @@
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
import js from "@eslint/js";
|
||||
import typescriptEslint from "@typescript-eslint/eslint-plugin";
|
||||
import tsParser from "@typescript-eslint/parser";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all,
|
||||
});
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: ["**/out", "**/build", "**/dist"],
|
||||
},
|
||||
...compat.extends("plugin:@typescript-eslint/recommended"),
|
||||
{
|
||||
plugins: {
|
||||
"@typescript-eslint": typescriptEslint,
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["**/*"],
|
||||
|
||||
rules: {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
},
|
||||
},
|
||||
];
|
||||
398
package-lock.json
generated
398
package-lock.json
generated
@@ -12,7 +12,7 @@
|
||||
"@electron-toolkit/preload": "^3.0.1",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"@floating-ui/dom": "^1.6.11",
|
||||
"@types/graceful-fs": "^4.1.6",
|
||||
"@types/graceful-fs": "^4.1.9",
|
||||
"@xhayper/discord-rpc": "^1.2.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -30,25 +30,27 @@
|
||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||
"@electron/notarize": "^2.5.0",
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "^9.11.1",
|
||||
"@eslint/js": "^9.13.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/node": "^22.7.4",
|
||||
"@typescript-eslint/eslint-plugin": "^8.8.0",
|
||||
"@typescript-eslint/parser": "^8.8.0",
|
||||
"@types/eslint__eslintrc": "^2.1.2",
|
||||
"@types/eslint__js": "^8.42.3",
|
||||
"@types/node": "^22.7.7",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"electron": "^32.1.2",
|
||||
"electron-builder": "^25.1.7",
|
||||
"electron-vite": "^2.3.0",
|
||||
"eslint": "^9.11.1",
|
||||
"eslint": "^9.13.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-solid": "^0.14.3",
|
||||
"postcss": "^8.4.47",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-packagejson": "^2.5.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.8",
|
||||
"solid-js": "^1.7.6",
|
||||
"tailwindcss": "^3.4.13",
|
||||
"typescript": "~5.5.0",
|
||||
"typescript": "~5.6.3",
|
||||
"typescript-eslint": "^8.10.0",
|
||||
"vite": "^5.4.8",
|
||||
"vite-plugin-lucide-preprocess": "^1.1.1",
|
||||
"vite-plugin-solid": "^2.7.0"
|
||||
@@ -1348,9 +1350,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/core": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz",
|
||||
"integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==",
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz",
|
||||
"integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
@@ -1382,9 +1384,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "9.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz",
|
||||
"integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==",
|
||||
"version": "9.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz",
|
||||
"integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -1575,6 +1577,30 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz",
|
||||
"integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18.18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanfs/node": {
|
||||
"version": "0.16.5",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz",
|
||||
"integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@humanfs/core": "^0.19.0",
|
||||
"@humanwhocodes/retry": "^0.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/module-importer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
|
||||
@@ -1590,9 +1616,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/retry": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz",
|
||||
"integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==",
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
|
||||
"integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
@@ -2767,6 +2793,37 @@
|
||||
"@types/ms": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
|
||||
"integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint__eslintrc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint__eslintrc/-/eslint__eslintrc-2.1.2.tgz",
|
||||
"integrity": "sha512-qXvzPFY7Rz05xD8ZApXJ3S8xStQD2Ibzu3EFIF0UMNOAfLY5xUu3H61q0JrHo2OXD6rcFG75yUxNQbkKtFKBSw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/eslint": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint__js": {
|
||||
"version": "8.42.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz",
|
||||
"integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/eslint": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||
@@ -2841,9 +2898,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz",
|
||||
"integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==",
|
||||
"version": "22.7.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.7.tgz",
|
||||
"integrity": "sha512-SRxCrrg9CL/y54aiMCG3edPKdprgMVGDXjA3gB8UmmBW5TcXzRUYAh8EWzTnSJFAd1rgImPELza+A3bJ+qxz8Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
@@ -2889,17 +2946,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz",
|
||||
"integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==",
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.10.0.tgz",
|
||||
"integrity": "sha512-phuB3hoP7FFKbRXxjl+DRlQDuJqhpOnm5MmtROXyWi3uS/Xg2ZXqiQfcG2BJHiN4QKyzdOJi3NEn/qTnjUlkmQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.8.0",
|
||||
"@typescript-eslint/type-utils": "8.8.0",
|
||||
"@typescript-eslint/utils": "8.8.0",
|
||||
"@typescript-eslint/visitor-keys": "8.8.0",
|
||||
"@typescript-eslint/scope-manager": "8.10.0",
|
||||
"@typescript-eslint/type-utils": "8.10.0",
|
||||
"@typescript-eslint/utils": "8.10.0",
|
||||
"@typescript-eslint/visitor-keys": "8.10.0",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.3.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
@@ -2923,16 +2980,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz",
|
||||
"integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==",
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.10.0.tgz",
|
||||
"integrity": "sha512-E24l90SxuJhytWJ0pTQydFT46Nk0Z+bsLKo/L8rtQSL93rQ6byd1V/QbDpHUTdLPOMsBCcYXZweADNCfOCmOAg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.8.0",
|
||||
"@typescript-eslint/types": "8.8.0",
|
||||
"@typescript-eslint/typescript-estree": "8.8.0",
|
||||
"@typescript-eslint/visitor-keys": "8.8.0",
|
||||
"@typescript-eslint/scope-manager": "8.10.0",
|
||||
"@typescript-eslint/types": "8.10.0",
|
||||
"@typescript-eslint/typescript-estree": "8.10.0",
|
||||
"@typescript-eslint/visitor-keys": "8.10.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2952,14 +3009,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz",
|
||||
"integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==",
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.10.0.tgz",
|
||||
"integrity": "sha512-AgCaEjhfql9MDKjMUxWvH7HjLeBqMCBfIaBbzzIcBbQPZE7CPh1m6FF+L75NUMJFMLYhCywJXIDEMa3//1A0dw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.8.0",
|
||||
"@typescript-eslint/visitor-keys": "8.8.0"
|
||||
"@typescript-eslint/types": "8.10.0",
|
||||
"@typescript-eslint/visitor-keys": "8.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -2970,14 +3027,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz",
|
||||
"integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==",
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.10.0.tgz",
|
||||
"integrity": "sha512-PCpUOpyQSpxBn230yIcK+LeCQaXuxrgCm2Zk1S+PTIRJsEfU6nJ0TtwyH8pIwPK/vJoA+7TZtzyAJSGBz+s/dg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "8.8.0",
|
||||
"@typescript-eslint/utils": "8.8.0",
|
||||
"@typescript-eslint/typescript-estree": "8.10.0",
|
||||
"@typescript-eslint/utils": "8.10.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
@@ -2995,9 +3052,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz",
|
||||
"integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==",
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.10.0.tgz",
|
||||
"integrity": "sha512-k/E48uzsfJCRRbGLapdZgrX52csmWJ2rcowwPvOZ8lwPUv3xW6CcFeJAXgx4uJm+Ge4+a4tFOkdYvSpxhRhg1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -3009,14 +3066,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz",
|
||||
"integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==",
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.10.0.tgz",
|
||||
"integrity": "sha512-3OE0nlcOHaMvQ8Xu5gAfME3/tWVDpb/HxtpUZ1WeOAksZ/h/gwrBzCklaGzwZT97/lBbbxJ16dMA98JMEngW4w==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.8.0",
|
||||
"@typescript-eslint/visitor-keys": "8.8.0",
|
||||
"@typescript-eslint/types": "8.10.0",
|
||||
"@typescript-eslint/visitor-keys": "8.10.0",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -3064,16 +3121,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz",
|
||||
"integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==",
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.10.0.tgz",
|
||||
"integrity": "sha512-Oq4uZ7JFr9d1ZunE/QKy5egcDRXT/FrS2z/nlxzPua2VHFtmMvFNDvpq1m/hq0ra+T52aUezfcjGRIB7vNJF9w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "8.8.0",
|
||||
"@typescript-eslint/types": "8.8.0",
|
||||
"@typescript-eslint/typescript-estree": "8.8.0"
|
||||
"@typescript-eslint/scope-manager": "8.10.0",
|
||||
"@typescript-eslint/types": "8.10.0",
|
||||
"@typescript-eslint/typescript-estree": "8.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -3087,13 +3144,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz",
|
||||
"integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==",
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.10.0.tgz",
|
||||
"integrity": "sha512-k8nekgqwr7FadWk548Lfph6V3r9OVqjzAIVskE7orMZR23cGJjAOVazsZSJW+ElyjfTM4wx/1g88Mi70DDtG9A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.8.0",
|
||||
"@typescript-eslint/types": "8.10.0",
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
},
|
||||
"engines": {
|
||||
@@ -4668,6 +4725,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/detect-indent": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz",
|
||||
"integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||
@@ -4677,6 +4744,19 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-newline": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz",
|
||||
"integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-node": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
|
||||
@@ -4712,6 +4792,19 @@
|
||||
"p-limit": "^3.1.0 "
|
||||
}
|
||||
},
|
||||
"node_modules/dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-type": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/discord-api-types": {
|
||||
"version": "0.37.101",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.101.tgz",
|
||||
@@ -5182,22 +5275,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.11.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz",
|
||||
"integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==",
|
||||
"version": "9.13.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz",
|
||||
"integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.11.0",
|
||||
"@eslint/config-array": "^0.18.0",
|
||||
"@eslint/core": "^0.6.0",
|
||||
"@eslint/core": "^0.7.0",
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "9.11.1",
|
||||
"@eslint/js": "9.13.0",
|
||||
"@eslint/plugin-kit": "^0.2.0",
|
||||
"@humanfs/node": "^0.16.5",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@humanwhocodes/retry": "^0.3.0",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
"@humanwhocodes/retry": "^0.3.1",
|
||||
"@types/estree": "^1.0.6",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"ajv": "^6.12.4",
|
||||
@@ -5205,9 +5298,9 @@
|
||||
"cross-spawn": "^7.0.2",
|
||||
"debug": "^4.3.2",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^8.0.2",
|
||||
"eslint-visitor-keys": "^4.0.0",
|
||||
"espree": "^10.1.0",
|
||||
"eslint-scope": "^8.1.0",
|
||||
"eslint-visitor-keys": "^4.1.0",
|
||||
"espree": "^10.2.0",
|
||||
"esquery": "^1.5.0",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
@@ -5217,13 +5310,11 @@
|
||||
"ignore": "^5.2.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"is-glob": "^4.0.0",
|
||||
"is-path-inside": "^3.0.3",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"minimatch": "^3.1.2",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.9.3",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"text-table": "^0.2.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -5884,6 +5975,19 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stdin": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
|
||||
"integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
@@ -5899,6 +6003,16 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/git-hooks-list": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz",
|
||||
"integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/fisker/git-hooks-list?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
@@ -5982,6 +6096,26 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/globby": {
|
||||
"version": "13.2.2",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz",
|
||||
"integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dir-glob": "^3.0.1",
|
||||
"fast-glob": "^3.3.0",
|
||||
"ignore": "^5.2.4",
|
||||
"merge2": "^1.4.1",
|
||||
"slash": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||
@@ -6509,14 +6643,17 @@
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-path-inside": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||
"node_modules/is-plain-obj": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
|
||||
"integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-potential-custom-element-name": {
|
||||
@@ -7853,6 +7990,16 @@
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/pe-library": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz",
|
||||
@@ -8131,6 +8278,25 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-packagejson": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.3.tgz",
|
||||
"integrity": "sha512-ATMEEXr+ywls1kgrZEWl4SBPEm0uDdyDAjyNzUC0/Z8WZTD3RqbJcQDR+Dau+wYkW9KHK6zqQIsFyfn+9aduWg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sort-package-json": "2.10.1",
|
||||
"synckit": "0.9.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prettier": ">= 1.16.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"prettier": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-tailwindcss": {
|
||||
"version": "0.6.8",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.8.tgz",
|
||||
@@ -8842,6 +9008,19 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/slash": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
|
||||
"integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/slice-ansi": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
|
||||
@@ -8950,6 +9129,33 @@
|
||||
"solid-js": "^1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/sort-object-keys": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz",
|
||||
"integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sort-package-json": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.10.1.tgz",
|
||||
"integrity": "sha512-d76wfhgUuGypKqY72Unm5LFnMpACbdxXsLPcL27pOsSrmVqH3PztFp1uq+Z22suk15h7vXmTesuh2aEjdCqb5w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"detect-indent": "^7.0.1",
|
||||
"detect-newline": "^4.0.0",
|
||||
"get-stdin": "^9.0.0",
|
||||
"git-hooks-list": "^3.0.0",
|
||||
"globby": "^13.1.2",
|
||||
"is-plain-obj": "^4.1.0",
|
||||
"semver": "^7.6.0",
|
||||
"sort-object-keys": "^1.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"sort-package-json": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@@ -9247,9 +9453,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/synckit": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz",
|
||||
"integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==",
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
|
||||
"integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -9578,9 +9784,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
|
||||
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
|
||||
"version": "5.6.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
|
||||
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -9591,6 +9797,30 @@
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript-eslint": {
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.10.0.tgz",
|
||||
"integrity": "sha512-YIu230PeN7z9zpu/EtqCIuRVHPs4iSlqW6TEvjbyDAE3MZsSl2RXBo+5ag+lbABCG8sFM1WVKEXhlQ8Ml8A3Fw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "8.10.0",
|
||||
"@typescript-eslint/parser": "8.10.0",
|
||||
"@typescript-eslint/utils": "8.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.19.8.tgz",
|
||||
|
||||
46
package.json
46
package.json
@@ -2,32 +2,32 @@
|
||||
"name": "osu-radio",
|
||||
"version": "1.0.0",
|
||||
"description": "Application to play your osu! songs.",
|
||||
"main": "./out/main/index.js",
|
||||
"type": "module",
|
||||
"author": "@CaptSiro",
|
||||
"homepage": "https://github.com/Team-BTMC/osu-radio",
|
||||
"author": "@CaptSiro",
|
||||
"type": "module",
|
||||
"main": "./out/main/index.js",
|
||||
"scripts": {
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"lint": "eslint . --fix",
|
||||
"lint:check": "eslint .",
|
||||
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
|
||||
"typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false",
|
||||
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
||||
"start": "electron-vite preview",
|
||||
"build": "npm run typecheck && electron-vite build",
|
||||
"build:linux": "electron-vite build && electron-builder --linux --config",
|
||||
"build:mac": "electron-vite build && electron-builder --mac --config",
|
||||
"build:win": "npm run build && electron-builder --win --config",
|
||||
"dev": "electron-vite dev",
|
||||
"dev:watch": "electron-vite dev --watch",
|
||||
"build": "npm run typecheck && electron-vite build",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"build:win": "npm run build && electron-builder --win --config",
|
||||
"build:mac": "electron-vite build && electron-builder --mac --config",
|
||||
"build:linux": "electron-vite build && electron-builder --linux --config"
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"start": "electron-vite preview",
|
||||
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
||||
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
|
||||
"typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron-toolkit/preload": "^3.0.1",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"@floating-ui/dom": "^1.6.11",
|
||||
"@types/graceful-fs": "^4.1.6",
|
||||
"@types/graceful-fs": "^4.1.9",
|
||||
"@xhayper/discord-rpc": "^1.2.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -45,25 +45,27 @@
|
||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||
"@electron/notarize": "^2.5.0",
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "^9.11.1",
|
||||
"@eslint/js": "^9.13.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/node": "^22.7.4",
|
||||
"@typescript-eslint/eslint-plugin": "^8.8.0",
|
||||
"@typescript-eslint/parser": "^8.8.0",
|
||||
"@types/eslint__eslintrc": "^2.1.2",
|
||||
"@types/eslint__js": "^8.42.3",
|
||||
"@types/node": "^22.7.7",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"electron": "^32.1.2",
|
||||
"electron-builder": "^25.1.7",
|
||||
"electron-vite": "^2.3.0",
|
||||
"eslint": "^9.11.1",
|
||||
"eslint": "^9.13.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-solid": "^0.14.3",
|
||||
"postcss": "^8.4.47",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-packagejson": "^2.5.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.8",
|
||||
"solid-js": "^1.7.6",
|
||||
"tailwindcss": "^3.4.13",
|
||||
"typescript": "~5.5.0",
|
||||
"typescript": "~5.6.3",
|
||||
"typescript-eslint": "^8.10.0",
|
||||
"vite": "^5.4.8",
|
||||
"vite-plugin-lucide-preprocess": "^1.1.1",
|
||||
"vite-plugin-solid": "^2.7.0"
|
||||
|
||||
@@ -51,14 +51,14 @@ export class TemplateTokenizer {
|
||||
switch (this.char) {
|
||||
case "\0":
|
||||
return createToken(Tokens.EOF, this.char, this.position);
|
||||
case "\\":
|
||||
case "\\": {
|
||||
const next = this.peek();
|
||||
if (next === "{" || next === "}") {
|
||||
this.readChar();
|
||||
return createToken(Tokens.Text, this.char, this.position);
|
||||
}
|
||||
|
||||
return createToken(Tokens.Text, this.char, this.position);
|
||||
}
|
||||
case "{":
|
||||
return createToken(Tokens.LeftSquirly, this.char, this.position);
|
||||
case "}":
|
||||
|
||||
@@ -52,7 +52,7 @@ async function configureOsuDir(mainWindow: BrowserWindow) {
|
||||
let tables: Awaited<DirParseResult>;
|
||||
const settings = Storage.getTable("settings");
|
||||
|
||||
do {
|
||||
while (true) {
|
||||
await Router.dispatch(mainWindow, "changeScene", "dir-select");
|
||||
const dir = await dirSubmit();
|
||||
|
||||
@@ -91,7 +91,7 @@ async function configureOsuDir(mainWindow: BrowserWindow) {
|
||||
// All went smoothly. Save osu directory and continue with import procedure
|
||||
settings.write("osuSongsDir", dir);
|
||||
break;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
// Show finished state
|
||||
await Router.dispatch(mainWindow, "loadingScene::update", {
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
import "../assets/css/bar.css";
|
||||
import { clamp } from "../lib/tungsten/math";
|
||||
import { Component, createEffect, createSignal, onMount } from "solid-js";
|
||||
|
||||
type BarAlignment = "vertical" | "v" | "horizontal" | "h";
|
||||
|
||||
function isVertical(alignment?: BarAlignment): boolean {
|
||||
return alignment === "vertical" || alignment === "v";
|
||||
}
|
||||
|
||||
type BarProps = {
|
||||
alignment?: BarAlignment;
|
||||
fill: number;
|
||||
setFill?: (fill: number) => any;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const Bar: Component<BarProps> = (props) => {
|
||||
const [fill, setFill] = createSignal(props.fill);
|
||||
let bar: HTMLDivElement | undefined, handle: HTMLDivElement | undefined;
|
||||
|
||||
onMount(() => {
|
||||
createEffect(() => {
|
||||
const f = fill();
|
||||
bar?.style.setProperty("--fill-per", `${clamp(0, 1, f) * 100}%`);
|
||||
|
||||
if (props.setFill !== undefined) {
|
||||
props.setFill(clamp(0, 1, f));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const calculateFill = (evt: PointerEvent) => {
|
||||
if (props.disabled === true || !bar) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rect: DOMRect = bar.getBoundingClientRect();
|
||||
|
||||
if (isVertical(props.alignment)) {
|
||||
setFill(clamp(0, 1, -(evt.clientY - rect.top) / rect.height + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
setFill(clamp(0, 1, (evt.clientX - rect.left) / rect.width));
|
||||
};
|
||||
|
||||
const onDown = (evt: PointerEvent) => {
|
||||
if (props.disabled === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
handle?.setPointerCapture(evt.pointerId);
|
||||
|
||||
handle?.addEventListener("pointermove", calculateFill);
|
||||
handle?.addEventListener(
|
||||
"pointerup",
|
||||
() => handle.removeEventListener("pointermove", calculateFill),
|
||||
{ once: true },
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={bar}
|
||||
classList={{
|
||||
bar: true,
|
||||
vertical: props.alignment !== undefined,
|
||||
editable: props.setFill !== undefined,
|
||||
}}
|
||||
style={{
|
||||
"--fill-per": clamp(0, 1, props.fill) * 100 + "%",
|
||||
}}
|
||||
onPointerDown={calculateFill}
|
||||
data-disabled={props.disabled}
|
||||
>
|
||||
<div class="filling-container">
|
||||
<div class="filling"></div>
|
||||
</div>
|
||||
|
||||
<div ref={handle} class="handle" onPointerDown={onDown}></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Bar;
|
||||
@@ -1,71 +0,0 @@
|
||||
import "../assets/css/gradient.css";
|
||||
import Impulse from "../lib/Impulse";
|
||||
import { Component, createEffect, createSignal, JSXElement, onCleanup, onMount } from "solid-js";
|
||||
|
||||
export type GradientColors = {
|
||||
top: string;
|
||||
bottom: string;
|
||||
};
|
||||
|
||||
export const [gradientColors, setGradientColors] = createSignal<GradientColors>({
|
||||
top: "dodgerblue",
|
||||
bottom: "crimson",
|
||||
});
|
||||
|
||||
type GradientProps = {
|
||||
classTop?: string;
|
||||
classBottom?: string;
|
||||
update?: Impulse;
|
||||
children: JSXElement;
|
||||
};
|
||||
|
||||
const Gradient: Component<GradientProps> = (props) => {
|
||||
let bottomLayer: HTMLDivElement | undefined;
|
||||
|
||||
const calculateBackground = () => {
|
||||
if (!bottomLayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rect: DOMRect = bottomLayer.getBoundingClientRect();
|
||||
|
||||
bottomLayer.style.setProperty("--left", `${Math.round(-rect.left)}px`);
|
||||
bottomLayer.style.setProperty("--top", `${Math.round(-rect.top)}px`);
|
||||
|
||||
bottomLayer.style.setProperty("--right", `${Math.round(rect.left + rect.width)}px`);
|
||||
bottomLayer.style.setProperty("--bottom", `${Math.round(rect.top + rect.height)}px`);
|
||||
|
||||
bottomLayer.style.setProperty("--width", `${Math.round(window.innerWidth * 1.25)}px`);
|
||||
bottomLayer.style.setProperty("--height", `${Math.round(window.innerHeight * 1.25)}px`);
|
||||
};
|
||||
|
||||
if (props.update !== undefined) {
|
||||
props.update.listen(calculateBackground);
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
calculateBackground();
|
||||
window.addEventListener("resize", calculateBackground);
|
||||
});
|
||||
|
||||
onCleanup(() => {
|
||||
window.removeEventListener("resize", calculateBackground);
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
const colors = gradientColors();
|
||||
|
||||
document.documentElement.style.setProperty("--circle-0", colors.top);
|
||||
document.documentElement.style.setProperty("--circle-1", colors.bottom);
|
||||
});
|
||||
|
||||
return (
|
||||
<div ref={bottomLayer} class={`bottom-layer ${props.classBottom ?? ""}`}>
|
||||
<div class={`gradient-layer`}>
|
||||
<div class={`top-layer ${props.classTop ?? ""}`}>{props.children}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Gradient;
|
||||
@@ -1,49 +0,0 @@
|
||||
import "../assets/css/select.css";
|
||||
import { Component, For, onMount, Setter } from "solid-js";
|
||||
|
||||
export type SelectOption = {
|
||||
value: string;
|
||||
text: string;
|
||||
selected?: boolean;
|
||||
};
|
||||
|
||||
type SelectProps = {
|
||||
setValue: Setter<string>;
|
||||
options: SelectOption[];
|
||||
selected?: string;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const Select: Component<SelectProps> = (props) => {
|
||||
let select: HTMLSelectElement | undefined;
|
||||
|
||||
onMount(() => {
|
||||
if (!select) {
|
||||
return;
|
||||
}
|
||||
|
||||
props.setValue(select.value);
|
||||
});
|
||||
|
||||
return (
|
||||
<select
|
||||
class={"button-like select"}
|
||||
ref={select}
|
||||
onchange={() => select && props.setValue(select.value)}
|
||||
disabled={props.disabled}
|
||||
>
|
||||
<For each={props.options}>
|
||||
{(option) => (
|
||||
<option
|
||||
value={option.value}
|
||||
selected={option.selected === true || option.value === props.selected}
|
||||
>
|
||||
{option.text}
|
||||
</option>
|
||||
)}
|
||||
</For>
|
||||
</select>
|
||||
);
|
||||
};
|
||||
|
||||
export default Select;
|
||||
@@ -1,85 +0,0 @@
|
||||
import { Component, JSX, onMount, Setter, Signal } from "solid-js";
|
||||
|
||||
type TextFieldProps = {
|
||||
value: Signal<string>;
|
||||
setInput?: Setter<HTMLElement | undefined>;
|
||||
children?: JSX.Element;
|
||||
};
|
||||
|
||||
const TextField: Component<TextFieldProps> = (props) => {
|
||||
const [value, setValue] = props.value;
|
||||
let input: HTMLInputElement | undefined;
|
||||
|
||||
onMount(() => {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.setInput !== undefined) {
|
||||
props.setInput(input);
|
||||
}
|
||||
|
||||
input.textContent = value();
|
||||
});
|
||||
|
||||
const onInput = () => {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
setValue(
|
||||
String(input.textContent).replaceAll(
|
||||
String.fromCharCode(160), // non-breaking space
|
||||
String.fromCharCode(32), // breaking space
|
||||
) ?? "",
|
||||
);
|
||||
};
|
||||
|
||||
const onPaste = (evt: ClipboardEvent) => {
|
||||
const selection = window.getSelection();
|
||||
if (selection === null || !evt.clipboardData) return;
|
||||
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
|
||||
selection.deleteFromDocument();
|
||||
selection.getRangeAt(0).insertNode(document.createTextNode(evt.clipboardData.getData("Text")));
|
||||
selection.collapseToEnd();
|
||||
|
||||
onInput();
|
||||
};
|
||||
|
||||
const clear = () => {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
input.textContent = "";
|
||||
onInput();
|
||||
input.focus();
|
||||
};
|
||||
|
||||
return (
|
||||
<div class="button-like flex w-full items-center gap-2 overflow-hidden p-2 focus-within:outline-2 focus-within:transition-none hover:cursor-text">
|
||||
{props.children}
|
||||
<div
|
||||
class="flex-1 overflow-hidden whitespace-nowrap focus:outline-none"
|
||||
ref={input}
|
||||
onInput={onInput}
|
||||
onKeyDown={(evt) => evt.stopPropagation()}
|
||||
onPaste={onPaste}
|
||||
contenteditable={true}
|
||||
spellcheck={false}
|
||||
></div>
|
||||
<button
|
||||
class="mr-1 grid place-items-center bg-transparent p-0 hover:cursor-pointer hover:bg-transparent focus:outline-none"
|
||||
onClick={clear}
|
||||
title="Clear text input"
|
||||
>
|
||||
{/* TODO: Add clear icon */}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TextField;
|
||||
@@ -2,7 +2,6 @@ import { Optional } from "../../../../@types";
|
||||
import "../../assets/css/notice/notice.css";
|
||||
import Impulse from "../../lib/Impulse";
|
||||
import { none, orDefault, some } from "../../lib/rust-like-utils-client/Optional";
|
||||
import Gradient from "../Gradient";
|
||||
import { hideNotice } from "./NoticeContainer";
|
||||
import { XIcon } from "lucide-solid";
|
||||
import { Accessor, Component, createSignal } from "solid-js";
|
||||
@@ -32,7 +31,9 @@ const Notice: Component<NoticeProps> = (props) => {
|
||||
|
||||
try {
|
||||
pauseDrain();
|
||||
} catch {}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const [drain, setDrainTime, pauseDrain] = createDrainAnimation(
|
||||
@@ -53,30 +54,28 @@ const Notice: Component<NoticeProps> = (props) => {
|
||||
data-id={props.notice.id}
|
||||
ref={onRef}
|
||||
>
|
||||
<Gradient update={props.updateGradient}>
|
||||
<div class={"notice " + (props.notice.class !== "notice" ? props.notice.class : "")}>
|
||||
<div class="content">
|
||||
<div class="head">
|
||||
<h3>{props.notice.title}</h3>
|
||||
<button onClick={removeNotice}>
|
||||
<XIcon size={20} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p>{props.notice.content}</p>
|
||||
<div class={"notice " + (props.notice.class !== "notice" ? props.notice.class : "")}>
|
||||
<div class="content">
|
||||
<div class="head">
|
||||
<h3>{props.notice.title}</h3>
|
||||
<button onClick={removeNotice}>
|
||||
<XIcon size={20} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="timeout"
|
||||
classList={{
|
||||
pause: drain().isNone,
|
||||
}}
|
||||
style={{
|
||||
animation: orDefault(drain(), undefined),
|
||||
}}
|
||||
></div>
|
||||
<p>{props.notice.content}</p>
|
||||
</div>
|
||||
</Gradient>
|
||||
|
||||
<div
|
||||
class="timeout"
|
||||
classList={{
|
||||
pause: drain().isNone,
|
||||
}}
|
||||
style={{
|
||||
animation: orDefault(drain(), undefined),
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export default function NoScene() {
|
||||
return <div class="scene"></div>;
|
||||
return <div class="scene" />;
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import "../../assets/css/search/tag-item.css";
|
||||
import { XIcon } from "lucide-solid";
|
||||
import { Component } from "solid-js";
|
||||
|
||||
export type TagItemProps = {
|
||||
name: string;
|
||||
isSpecial: boolean;
|
||||
onRemove: (name: string) => any;
|
||||
onChange: (name: string) => any;
|
||||
};
|
||||
|
||||
const TagItem: Component<TagItemProps> = (props) => {
|
||||
let container;
|
||||
|
||||
const changeState = (evt: Event) => {
|
||||
evt.preventDefault();
|
||||
props.onChange(props.name);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={container}
|
||||
class={"tag"}
|
||||
classList={{ special: props.isSpecial === true }}
|
||||
onContextMenu={changeState}
|
||||
>
|
||||
<span>{props.name}</span>
|
||||
<button onClick={() => props.onRemove(props.name)}>
|
||||
<XIcon size={20} />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagItem;
|
||||
@@ -1,160 +0,0 @@
|
||||
import "../../assets/css/search/tag-select.css";
|
||||
import Gradient from "../Gradient";
|
||||
import TextField from "../form/TextField";
|
||||
import TagItem from "./TagItem";
|
||||
import { TagIcon } from "lucide-solid";
|
||||
import { Component, createEffect, createSignal, For, Signal } from "solid-js";
|
||||
|
||||
export type Tag = {
|
||||
name: string;
|
||||
isSpecial?: boolean;
|
||||
};
|
||||
|
||||
type TagSelectProps = {
|
||||
/** Must have ```json
|
||||
* { equals: false }
|
||||
* ``` */
|
||||
tags: Signal<Tag[]>;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const TagSelect: Component<TagSelectProps> = (props) => {
|
||||
const [tags, setTags] = props.tags;
|
||||
const tagSignal = createSignal("");
|
||||
const [tagField, setTagField] = createSignal<HTMLElement | undefined>();
|
||||
let dialog: HTMLDialogElement | undefined;
|
||||
|
||||
const openDialog = () => {
|
||||
dialog?.showModal();
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
};
|
||||
|
||||
const closeDialog = () => {
|
||||
dialog?.close();
|
||||
const field = tagField();
|
||||
|
||||
if (field === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
field.textContent = "";
|
||||
};
|
||||
|
||||
const onKeyDown = (evt: KeyboardEvent) => {
|
||||
if (evt.key !== "Enter") {
|
||||
return;
|
||||
}
|
||||
|
||||
const input = tagField();
|
||||
|
||||
if (input === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
|
||||
if (input.textContent === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newTags = input.textContent.trim().split(" ");
|
||||
const oldTags = tags();
|
||||
|
||||
for (let i = 0; i < newTags.length; i++) {
|
||||
if (newTags[i] === "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const index = oldTags.findIndex((t) => t.name === newTags[i]);
|
||||
|
||||
if (index !== -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
oldTags.push({ name: newTags[i] });
|
||||
}
|
||||
|
||||
setTags(oldTags);
|
||||
|
||||
input.textContent = "";
|
||||
input.focus();
|
||||
};
|
||||
|
||||
createEffect(() => {
|
||||
const input = tagField();
|
||||
|
||||
if (input === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
input.addEventListener("keydown", onKeyDown);
|
||||
});
|
||||
|
||||
const onTagRemove = (name: string) => {
|
||||
const t = tags();
|
||||
const index = t.findIndex((x) => x.name === name);
|
||||
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
t.splice(index, 1);
|
||||
setTags(t);
|
||||
};
|
||||
|
||||
const onTagChange = (name: string) => {
|
||||
const t = tags();
|
||||
const index = t.findIndex((x) => x.name === name);
|
||||
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
t[index] = {
|
||||
name,
|
||||
isSpecial: !t[index].isSpecial,
|
||||
};
|
||||
|
||||
setTags(t);
|
||||
};
|
||||
|
||||
return (
|
||||
<div class={"tags"}>
|
||||
<button
|
||||
onClick={openDialog}
|
||||
disabled={props.disabled}
|
||||
title={"Add/Remove tags for searching"}
|
||||
>
|
||||
<TagIcon size={20} />
|
||||
</button>
|
||||
<dialog ref={dialog} class={"tag-select"}>
|
||||
<Gradient classTop={"tag-select-container"}>
|
||||
<TextField value={tagSignal} setInput={setTagField} />
|
||||
|
||||
<span class={"hint"}>
|
||||
Type the name of a tag into input above and press enter to add it. After it is added you
|
||||
can right-click it and change it to exclude songs with given tag.
|
||||
</span>
|
||||
|
||||
<div class={"tags-container"}>
|
||||
<For each={tags()}>
|
||||
{(tag: Tag) => (
|
||||
<TagItem
|
||||
name={tag.name}
|
||||
isSpecial={tag.isSpecial === true}
|
||||
onRemove={onTagRemove}
|
||||
onChange={onTagChange}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
|
||||
<button onClick={closeDialog}>Close</button>
|
||||
</Gradient>
|
||||
</dialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagSelect;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, Show } from "solid-js";
|
||||
import { Component, For, Show } from "solid-js";
|
||||
|
||||
type SettingDropdownProps = {
|
||||
label: string;
|
||||
@@ -27,9 +27,9 @@ const SettingDropdown: Component<SettingDropdownProps> = (props) => {
|
||||
disabled={props.disabled}
|
||||
onChange={changeOption}
|
||||
>
|
||||
{Array.from(props.options.keys()).map((option) => (
|
||||
<option value={option}>{option}</option>
|
||||
))}
|
||||
<For each={Array.from(props.options.keys())}>
|
||||
{(option) => <option value={option}>{option}</option>}
|
||||
</For>
|
||||
</select>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { cn } from "../../lib/css.utils";
|
||||
import Dropdown from "../dropdown/Dropdown";
|
||||
import { changeAudioDevice } from "@renderer/components/song/song.utils";
|
||||
import { GlobeIcon, LucideIcon, Volume2Icon } from "lucide-solid";
|
||||
import { Component, createEffect, createSignal, JSX, onMount } from "solid-js";
|
||||
import { Component, createEffect, createSignal, For, JSX, onMount } from "solid-js";
|
||||
|
||||
const Settings: Component = () => {
|
||||
return (
|
||||
@@ -22,14 +22,14 @@ type SettingsSectionProps = JSX.IntrinsicElements["div"] & {
|
||||
Icon: LucideIcon;
|
||||
};
|
||||
|
||||
const SettingsSection: Component<SettingsSectionProps> = ({ title, Icon, children, ...rest }) => {
|
||||
const SettingsSection: Component<SettingsSectionProps> = (props) => {
|
||||
return (
|
||||
<div class={cn("flex flex-col gap-6", rest.class)}>
|
||||
<div class={cn("flex flex-col gap-6", props.class)}>
|
||||
<div class="flex items-center gap-3">
|
||||
<Icon class="text-text opacity-70" size={16} />
|
||||
<h3 class="text-base text-text">{title}</h3>
|
||||
<props.Icon class="text-text opacity-70" size={16} />
|
||||
<h3 class="text-base text-text">{props.title}</h3>
|
||||
</div>
|
||||
{children}
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -39,13 +39,13 @@ type SettingProps = JSX.IntrinsicElements["div"] & {
|
||||
name: string;
|
||||
};
|
||||
|
||||
const Setting: Component<SettingProps> = ({ label, name, children, ...rest }) => {
|
||||
const Setting: Component<SettingProps> = (props) => {
|
||||
return (
|
||||
<div class={cn("flex flex-col gap-2.5", rest.class)}>
|
||||
<label class="text-sm font-semibold text-text" for={name}>
|
||||
{label}
|
||||
<div class={cn("flex flex-col gap-2.5", props.class)}>
|
||||
<label class="text-sm font-semibold text-text" for={props.name}>
|
||||
{props.label}
|
||||
</label>
|
||||
{children}
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -85,9 +85,9 @@ const AudioDeviceSetting: Component = () => {
|
||||
</Dropdown.SelectTrigger>
|
||||
|
||||
<Dropdown.List value={selectedAudioDevice} onValueChange={handleValueChange}>
|
||||
{Array.from(audioDevices().keys()).map((audioDevice) => (
|
||||
<Dropdown.Item value={audioDevice}>{audioDevice}</Dropdown.Item>
|
||||
))}
|
||||
<For each={Array.from(audioDevices().keys())}>
|
||||
{(audioDevice) => <Dropdown.Item value={audioDevice}>{audioDevice}</Dropdown.Item>}
|
||||
</For>
|
||||
</Dropdown.List>
|
||||
</Dropdown>
|
||||
</Setting>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
export default function SongHint(): HTMLElement {
|
||||
return (
|
||||
<div class="flex items-center rounded-md bg-black bg-opacity-80 p-2 shadow-lg">
|
||||
<div class="mr-3 h-12 w-12 rounded-md bg-gray-700"></div>
|
||||
<div class="mr-3 h-12 w-12 rounded-md bg-gray-700" />
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-2 h-4 w-32 rounded bg-gray-700"></div>
|
||||
<div class="h-3 w-24 rounded bg-gray-600"></div>
|
||||
<div class="mb-2 h-4 w-32 rounded bg-gray-700" />
|
||||
<div class="h-3 w-24 rounded bg-gray-600" />
|
||||
</div>
|
||||
</div>
|
||||
) as HTMLElement;
|
||||
|
||||
@@ -4,7 +4,7 @@ import SongHint from "../SongHint";
|
||||
import SongImage from "../SongImage";
|
||||
import { ignoreClickInContextMenu } from "../context-menu/SongContextMenu";
|
||||
import { song as selectedSong } from "../song.utils";
|
||||
import { Component, createSignal, onMount } from "solid-js";
|
||||
import { Component, createMemo, onMount } from "solid-js";
|
||||
|
||||
type SongItemProps = {
|
||||
song: Song;
|
||||
@@ -16,71 +16,54 @@ type SongItemProps = {
|
||||
children?: any;
|
||||
};
|
||||
|
||||
const SongItem: Component<SongItemProps> = ({
|
||||
group,
|
||||
onSelect,
|
||||
song,
|
||||
children,
|
||||
draggable: isDraggable,
|
||||
onDrop,
|
||||
selectable,
|
||||
}) => {
|
||||
const showSignal = createSignal(false);
|
||||
const [, setCoords] = createSignal<[number, number]>([0, 0], { equals: false });
|
||||
const SongItem: Component<SongItemProps> = (props) => {
|
||||
let item: HTMLDivElement | undefined;
|
||||
|
||||
const showMenu = (evt: MouseEvent) => {
|
||||
if (children === undefined) {
|
||||
showSignal[1](false);
|
||||
return;
|
||||
}
|
||||
|
||||
setCoords([evt.clientX, evt.clientY]);
|
||||
showSignal[1](true);
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
draggable(item, {
|
||||
onClick: ignoreClickInContextMenu(() => onSelect(song.path)),
|
||||
onDrop: onDrop ?? (() => {}),
|
||||
onClick: ignoreClickInContextMenu(() => props.onSelect(props.song.path)),
|
||||
onDrop: props.onDrop ?? (() => {}),
|
||||
createHint: SongHint,
|
||||
useOnlyAsOnClickBinder: !isDraggable || selectedSong().path === song.path,
|
||||
useOnlyAsOnClickBinder: !props.draggable || selectedSong().path === props.song.path,
|
||||
});
|
||||
|
||||
if (selectable === true) {
|
||||
item.dataset.path = song.path;
|
||||
if (props.selectable === true) {
|
||||
item.dataset.path = props.song.path;
|
||||
}
|
||||
});
|
||||
|
||||
const isActive = createMemo(() => {
|
||||
return selectedSong().path === props.song.path;
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
class="group relative isolate select-none rounded-md"
|
||||
classList={{
|
||||
"outline outline-2 outline-accent": selectedSong().path === song.path,
|
||||
"outline outline-2 outline-accent": isActive(),
|
||||
}}
|
||||
data-active={selectedSong().path === song.path}
|
||||
data-active={isActive()}
|
||||
ref={item}
|
||||
data-url={song.bg}
|
||||
onContextMenu={showMenu}
|
||||
data-url={props.song.bg}
|
||||
>
|
||||
<SongImage
|
||||
class="absolute inset-0 z-[-1] h-full w-full rounded-md bg-cover bg-center bg-no-repeat opacity-30 group-hover:opacity-90"
|
||||
classList={{
|
||||
"opacity-90": selectedSong().path === song.path,
|
||||
"opacity-90": isActive(),
|
||||
}}
|
||||
src={song.bg}
|
||||
group={group}
|
||||
src={props.song.bg}
|
||||
group={props.group}
|
||||
/>
|
||||
|
||||
<div class="flex min-h-[72px] flex-col justify-center overflow-hidden rounded-md bg-black/50 p-3">
|
||||
<h3 class="text-shadow text-[22px] font-extrabold leading-7 shadow-black/60">
|
||||
{song.title}
|
||||
{props.song.title}
|
||||
</h3>
|
||||
<p class="text-base text-subtext">{song.artist}</p>
|
||||
<p class="text-base text-subtext">{props.song.artist}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Optional, Order } from "../../../../../@types";
|
||||
import { Optional, Order, Tag } from "../../../../../@types";
|
||||
import { SearchQueryError } from "../../../../../main/lib/search-parser/@search-types";
|
||||
import { Tag } from "../../search/TagSelect";
|
||||
import { setSongsSearch } from "../song-list/song-list.utils";
|
||||
import SongListSearchOrderBy from "./SongListSearchOrderBy";
|
||||
import { SearchIcon } from "lucide-solid";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Button from "@renderer/components/button/Button";
|
||||
import Dropdown from "@renderer/components/dropdown/Dropdown";
|
||||
import { ArrowDownAzIcon, ArrowUpZaIcon } from "lucide-solid";
|
||||
import { Component, createMemo, createSignal, Match, Setter, Switch } from "solid-js";
|
||||
import { Component, createMemo, createSignal, For, Match, Setter, Switch } from "solid-js";
|
||||
import { OrderDirection, OrderOptions, Order } from "src/@types";
|
||||
|
||||
type OrderOption = {
|
||||
@@ -84,14 +84,16 @@ const SongListSearchOrderBy: Component<OrderSelectProps> = (props) => {
|
||||
}}
|
||||
value={option}
|
||||
>
|
||||
{orderOptions.map((option) => (
|
||||
<Dropdown.Item
|
||||
class="px-4 py-2 transition-colors duration-200 hover:bg-accent/20"
|
||||
value={option.value}
|
||||
>
|
||||
{option.text}
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
<For each={orderOptions}>
|
||||
{(option) => (
|
||||
<Dropdown.Item
|
||||
class="px-4 py-2 transition-colors duration-200 hover:bg-accent/20"
|
||||
value={option.value}
|
||||
>
|
||||
{option.text}
|
||||
</Dropdown.Item>
|
||||
)}
|
||||
</For>
|
||||
</Dropdown.List>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
||||
@@ -16,17 +16,18 @@ export type SongViewProps = {
|
||||
playlist?: string;
|
||||
};
|
||||
|
||||
const SongList: Component<SongViewProps> = (props) => {
|
||||
const tagsSignal = createSignal<Tag[]>([], { equals: false });
|
||||
const [tags] = tagsSignal;
|
||||
const DEFAULT_TAGS_VALUE: Tag[] = [];
|
||||
const DEFAULT_ORDER_VALUE: Order = { option: "title", direction: "asc" };
|
||||
|
||||
const [order, setOrder] = createSignal<Order>({ option: "title", direction: "asc" });
|
||||
const SongList: Component<SongViewProps> = (props) => {
|
||||
const [tags, setTags] = createSignal(DEFAULT_TAGS_VALUE, { equals: false });
|
||||
const [order, setOrder] = createSignal(DEFAULT_ORDER_VALUE);
|
||||
const [count, setCount] = createSignal(0);
|
||||
|
||||
const [payload, setPayload] = createSignal<SongsQueryPayload>({
|
||||
view: props,
|
||||
order: order(),
|
||||
tags: tags(),
|
||||
order: DEFAULT_ORDER_VALUE,
|
||||
tags: DEFAULT_TAGS_VALUE,
|
||||
});
|
||||
|
||||
const [searchError, setSearchError] = createSignal<Optional<SearchQueryError>>(none(), {
|
||||
@@ -75,7 +76,12 @@ const SongList: Component<SongViewProps> = (props) => {
|
||||
return (
|
||||
<div class="flex h-full flex-col">
|
||||
<div class="sticky top-0 z-10">
|
||||
<SongListSearch tags={tagsSignal} setOrder={setOrder} count={count} error={searchError} />
|
||||
<SongListSearch
|
||||
tags={[tags, setTags]}
|
||||
setOrder={setOrder}
|
||||
count={count}
|
||||
error={searchError}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex-grow overflow-y-auto p-5 py-0">
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export default function NoScene() {
|
||||
return <div class="scene"></div>;
|
||||
return <div class="scene" />;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
JSXElement,
|
||||
Match,
|
||||
onCleanup,
|
||||
onMount,
|
||||
Setter,
|
||||
Show,
|
||||
Switch,
|
||||
@@ -53,7 +54,7 @@ const Nav: Component = () => {
|
||||
const [os, setOs] = createSignal<NodeJS.Platform>();
|
||||
const [maximized, setMaximized] = createSignal<boolean>(false);
|
||||
|
||||
createEffect(async () => {
|
||||
onMount(async () => {
|
||||
const fetchOS = async () => {
|
||||
return await window.api.request("os::platform");
|
||||
};
|
||||
@@ -64,10 +65,17 @@ const Nav: Component = () => {
|
||||
|
||||
setOs(await fetchOS());
|
||||
setMaximized(await fetchMaximized());
|
||||
});
|
||||
|
||||
window.api.listen("window::maximizeChange", (maximized: boolean) => {
|
||||
createEffect(() => {
|
||||
const resizeListener = (maximized: boolean) => {
|
||||
setMaximized(maximized);
|
||||
});
|
||||
};
|
||||
|
||||
window.api.listen("window::maximizeChange", resizeListener);
|
||||
return () => {
|
||||
window.api.removeListener("window::maximizeChange", resizeListener);
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -101,13 +109,13 @@ function WindowControls(props: { maximized: Accessor<boolean>; setMaximized: Set
|
||||
return (
|
||||
<div class="nav-window-controls">
|
||||
<button
|
||||
onclick={async () => window.api.request("window::minimize")}
|
||||
onClick={async () => window.api.request("window::minimize")}
|
||||
class="nav-window-control"
|
||||
>
|
||||
<MinusIcon size={20} />
|
||||
</button>
|
||||
<button
|
||||
onclick={async () => {
|
||||
onClick={async () => {
|
||||
window.api.request("window::maximize");
|
||||
props.setMaximized(!props.maximized());
|
||||
}}
|
||||
@@ -116,7 +124,7 @@ function WindowControls(props: { maximized: Accessor<boolean>; setMaximized: Set
|
||||
{props.maximized() ? <Minimize2Icon size={20} /> : <SquareIcon size={18} />}
|
||||
</button>
|
||||
<button
|
||||
onclick={async () => window.api.request("window::close")}
|
||||
onClick={async () => window.api.request("window::close")}
|
||||
class="nav-window-control close"
|
||||
>
|
||||
<XIcon size={20} />
|
||||
@@ -128,19 +136,19 @@ function WindowControls(props: { maximized: Accessor<boolean>; setMaximized: Set
|
||||
type NavItemProps = Pick<Tab, "value" | "Icon"> & {
|
||||
children: JSXElement;
|
||||
};
|
||||
const NavItem: Component<NavItemProps> = ({ children, value, Icon }) => {
|
||||
const NavItem: Component<NavItemProps> = (props) => {
|
||||
return (
|
||||
<button
|
||||
class={`nav-item flex items-center gap-4 rounded-sm px-4 py-1 hover:bg-surface ${mainActiveTab() === value ? "bg-surface" : ""}`}
|
||||
onclick={() => setMainActiveTab(value)}
|
||||
class={`nav-item flex items-center gap-4 rounded-sm px-4 py-1 hover:bg-surface ${mainActiveTab() === props.value ? "bg-surface" : ""}`}
|
||||
onClick={() => setMainActiveTab(props.value)}
|
||||
>
|
||||
<span class={`${mainActiveTab() === value ? "" : "opacity-70"}`}>
|
||||
<Icon size={20} />
|
||||
<span class={`${mainActiveTab() === props.value ? "" : "opacity-70"}`}>
|
||||
<props.Icon size={20} />
|
||||
</span>
|
||||
<span
|
||||
class={`text-base font-semibold ${mainActiveTab() === value ? "text-text" : "text-subtext"}`}
|
||||
class={`text-base font-semibold ${mainActiveTab() === props.value ? "text-text" : "text-subtext"}`}
|
||||
>
|
||||
{children}
|
||||
{props.children}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user