diff --git a/package-lock.json b/package-lock.json index e9c8646b..65f5ee3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "font-list": "^1.5.1", "iconv-lite": "^0.6.3", "image-size": "^1.1.0", - "jschardet": "^3.1.0", + "jschardet": "^3.1.2", "long": "^5.2.3", "message2call": "^0.1.3", "music-metadata": "^8.1.4", @@ -41,7 +41,7 @@ "@babel/plugin-transform-runtime": "^7.24.3", "@babel/preset-env": "^7.24.3", "@babel/preset-typescript": "^7.24.1", - "@tsconfig/recommended": "^1.0.3", + "@tsconfig/recommended": "^1.0.4", "@types/better-sqlite3": "^7.6.9", "@types/needle": "^3.3.0", "@types/tunnel": "^0.0.7", @@ -62,14 +62,14 @@ "electron-builder": "^24.13.3", "electron-debug": "^3.2.0", "electron-devtools-installer": "^3.2.0", - "electron-to-chromium": "^1.4.715", + "electron-to-chromium": "^1.4.717", "electron-updater": "^6.1.8", "eslint": "^8.57.0", "eslint-config-standard": "^17.1.0", "eslint-config-standard-with-typescript": "^43.0.1", "eslint-formatter-friendly": "github:lyswhut/eslint-friendly-formatter#2170d1320e2fad13615a9dcf229669f0bb473a53", "eslint-plugin-html": "^8.0.0", - "eslint-plugin-vue": "^9.23.0", + "eslint-plugin-vue": "^9.24.0", "eslint-plugin-vue-pug": "^0.6.2", "eslint-webpack-plugin": "^4.1.0", "html-webpack-plugin": "^5.6.0", @@ -2293,18 +2293,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { "version": "8.57.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", @@ -2760,9 +2748,9 @@ } }, "node_modules/@tsconfig/recommended": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/recommended/-/recommended-1.0.3.tgz", - "integrity": "sha512-+jby/Guq9H8O7NWgCv6X8VAiQE8Dr/nccsCtL74xyHKhu2Knu5EAKmOZj3nLCnLm1KooUzKY+5DsnGVqhM8/wQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/recommended/-/recommended-1.0.4.tgz", + "integrity": "sha512-7RfsHlJYsqASGpV7R7zJ72baBBoqvbTj9dD4SHYSeLSMkMjSUhi15SZQK/7GQPCAmOhEoEC87HneaXihVXF6YA==", "dev": true }, "node_modules/@types/better-sqlite3": { @@ -4862,13 +4850,13 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dev": true, "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -4876,7 +4864,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -4903,22 +4891,6 @@ "ms": "2.0.0" } }, - "node_modules/body-parser/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/body-parser/node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -4937,15 +4909,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/body-parser/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/bonjour-service": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", @@ -5916,6 +5879,15 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -7266,9 +7238,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.715", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.715.tgz", - "integrity": "sha512-XzWNH4ZSa9BwVUQSDorPWAUQ5WGuYz7zJUNpNif40zFCiCl20t8zgylmreNmn26h5kiyw2lg7RfTmeMBsDklqg==", + "version": "1.4.717", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.717.tgz", + "integrity": "sha512-6Fmg8QkkumNOwuZ/5mIbMU9WI3H2fmn5ajcVya64I5Yr5CcNmO7vcLt0Y7c96DCiMO5/9G+4sI2r6eEvdg1F7A==", "dev": true }, "node_modules/electron-updater": { @@ -7888,12 +7860,13 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.23.0.tgz", - "integrity": "sha512-Bqd/b7hGYGrlV+wP/g77tjyFmp81lh5TMw0be9093X02SyelxRRfCI6/IsGq/J7Um0YwB9s0Ry0wlFyjPdmtUw==", + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.24.0.tgz", + "integrity": "sha512-9SkJMvF8NGMT9aQCwFc5rj8Wo1XWSMSHk36i7ZwdI614BU7sIOR28ZjuFPKp8YGymZN12BSEbiSwa7qikp+PBw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", @@ -7920,6 +7893,21 @@ "eslint-plugin-vue": "^9.8.0" } }, + "node_modules/eslint-plugin-vue/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -8037,18 +8025,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -8348,17 +8324,17 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -8395,15 +8371,6 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, - "node_modules/express/node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -8413,22 +8380,6 @@ "ms": "2.0.0" } }, - "node_modules/express/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -9710,6 +9661,31 @@ "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", "dev": true }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", @@ -10661,9 +10637,9 @@ } }, "node_modules/jschardet": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.1.0.tgz", - "integrity": "sha512-MND0yjRsoQ/3iFXce7lqV/iBmqH9oWGUTlty36obRBZjhFDWCLKjXgfxY75wYfwlW7EFqw52tyziy/q4WsQmrA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.1.2.tgz", + "integrity": "sha512-mw3CBZGzW8nUBPYhFU2ztZ/kJ6NClQUQVpyzvFMfznZsoC///ZQ30J2RCUanNsr5yF22LqhgYr/lj807/ZleWA==", "engines": { "node": ">=0.1.90" } @@ -13793,9 +13769,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { "bytes": "3.1.2", @@ -13816,22 +13792,6 @@ "node": ">= 0.8" } }, - "node_modules/raw-body/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/raw-body/node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -13844,15 +13804,6 @@ "node": ">=0.10.0" } }, - "node_modules/raw-body/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -14679,22 +14630,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -16580,6 +16515,18 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -19445,12 +19392,6 @@ "requires": { "type-fest": "^0.20.2" } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true } } }, @@ -19791,9 +19732,9 @@ "dev": true }, "@tsconfig/recommended": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/recommended/-/recommended-1.0.3.tgz", - "integrity": "sha512-+jby/Guq9H8O7NWgCv6X8VAiQE8Dr/nccsCtL74xyHKhu2Knu5EAKmOZj3nLCnLm1KooUzKY+5DsnGVqhM8/wQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/recommended/-/recommended-1.0.4.tgz", + "integrity": "sha512-7RfsHlJYsqASGpV7R7zJ72baBBoqvbTj9dD4SHYSeLSMkMjSUhi15SZQK/7GQPCAmOhEoEC87HneaXihVXF6YA==", "dev": true }, "@types/better-sqlite3": { @@ -21517,13 +21458,13 @@ } }, "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dev": true, "requires": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -21531,7 +21472,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -21551,19 +21492,6 @@ "ms": "2.0.0" } }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -21578,12 +21506,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true } } }, @@ -22336,6 +22258,12 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true + }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -23309,9 +23237,9 @@ } }, "electron-to-chromium": { - "version": "1.4.715", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.715.tgz", - "integrity": "sha512-XzWNH4ZSa9BwVUQSDorPWAUQ5WGuYz7zJUNpNif40zFCiCl20t8zgylmreNmn26h5kiyw2lg7RfTmeMBsDklqg==", + "version": "1.4.717", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.717.tgz", + "integrity": "sha512-6Fmg8QkkumNOwuZ/5mIbMU9WI3H2fmn5ajcVya64I5Yr5CcNmO7vcLt0Y7c96DCiMO5/9G+4sI2r6eEvdg1F7A==", "dev": true }, "electron-updater": { @@ -23626,12 +23554,6 @@ "requires": { "type-fest": "^0.20.2" } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true } } }, @@ -23826,18 +23748,30 @@ "requires": {} }, "eslint-plugin-vue": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.23.0.tgz", - "integrity": "sha512-Bqd/b7hGYGrlV+wP/g77tjyFmp81lh5TMw0be9093X02SyelxRRfCI6/IsGq/J7Um0YwB9s0Ry0wlFyjPdmtUw==", + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.24.0.tgz", + "integrity": "sha512-9SkJMvF8NGMT9aQCwFc5rj8Wo1XWSMSHk36i7ZwdI614BU7sIOR28ZjuFPKp8YGymZN12BSEbiSwa7qikp+PBw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "latest", "vue-eslint-parser": "^9.4.2", "xml-name-validator": "^4.0.0" + }, + "dependencies": { + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + } } }, "eslint-plugin-vue-pug": { @@ -24120,17 +24054,17 @@ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" }, "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dev": true, "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -24164,12 +24098,6 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -24179,19 +24107,6 @@ "ms": "2.0.0" } }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -25141,6 +25056,27 @@ "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", "dev": true }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "dependencies": { + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, "http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", @@ -25801,9 +25737,9 @@ } }, "jschardet": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.1.0.tgz", - "integrity": "sha512-MND0yjRsoQ/3iFXce7lqV/iBmqH9oWGUTlty36obRBZjhFDWCLKjXgfxY75wYfwlW7EFqw52tyziy/q4WsQmrA==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.1.2.tgz", + "integrity": "sha512-mw3CBZGzW8nUBPYhFU2ztZ/kJ6NClQUQVpyzvFMfznZsoC///ZQ30J2RCUanNsr5yF22LqhgYr/lj807/ZleWA==" }, "jsesc": { "version": "2.5.2", @@ -28183,9 +28119,9 @@ "dev": true }, "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "requires": { "bytes": "3.1.2", @@ -28200,19 +28136,6 @@ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -28221,12 +28144,6 @@ "requires": { "safer-buffer": ">= 2.1.2 < 3" } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true } } }, @@ -28864,19 +28781,6 @@ } } }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -30355,6 +30259,12 @@ "prelude-ls": "^1.2.1" } }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", diff --git a/package.json b/package.json index e6e7cd62..7759120f 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "@babel/plugin-transform-runtime": "^7.24.3", "@babel/preset-env": "^7.24.3", "@babel/preset-typescript": "^7.24.1", - "@tsconfig/recommended": "^1.0.3", + "@tsconfig/recommended": "^1.0.4", "@types/better-sqlite3": "^7.6.9", "@types/needle": "^3.3.0", "@types/tunnel": "^0.0.7", @@ -137,14 +137,14 @@ "electron-builder": "^24.13.3", "electron-debug": "^3.2.0", "electron-devtools-installer": "^3.2.0", - "electron-to-chromium": "^1.4.715", + "electron-to-chromium": "^1.4.717", "electron-updater": "^6.1.8", "eslint": "^8.57.0", "eslint-config-standard": "^17.1.0", "eslint-config-standard-with-typescript": "^43.0.1", "eslint-formatter-friendly": "github:lyswhut/eslint-friendly-formatter#2170d1320e2fad13615a9dcf229669f0bb473a53", "eslint-plugin-html": "^8.0.0", - "eslint-plugin-vue": "^9.23.0", + "eslint-plugin-vue": "^9.24.0", "eslint-plugin-vue-pug": "^0.6.2", "eslint-webpack-plugin": "^4.1.0", "html-webpack-plugin": "^5.6.0", @@ -185,7 +185,7 @@ "font-list": "^1.5.1", "iconv-lite": "^0.6.3", "image-size": "^1.1.0", - "jschardet": "^3.1.0", + "jschardet": "^3.1.2", "long": "^5.2.3", "message2call": "^0.1.3", "music-metadata": "^8.1.4", diff --git a/publish/changeLog.md b/publish/changeLog.md index d093f622..1f3d6c34 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -2,6 +2,7 @@ - 主题编辑器添加“深色字体”选项,启用后将减少字体颜色梯度,各类字体(正文、标签字体等)颜色将更接近,这有助于解决创建全透明主题时可能出现的字体配色问题(#1799) - 新增在线自定义源导入功能,允许通过http/https链接导入自定义源 +- 新增HTTP开放API服务,默认关闭,该服务可以为第三方软件提供调用LX的能力,可用API看说明文档(#1824) ### 优化 diff --git a/src/common/defaultSetting.ts b/src/common/defaultSetting.ts index c94e2008..121c4684 100644 --- a/src/common/defaultSetting.ts +++ b/src/common/defaultSetting.ts @@ -136,6 +136,9 @@ const defaultSetting: LX.AppSetting = { 'sync.server.maxSsnapshotNum': 5, 'sync.client.host': '', + 'openAPI.enable': false, + 'openAPI.port': '23330', + // 'theme.id': 'blue_plus', 'theme.id': 'green', 'theme.lightId': 'green', diff --git a/src/common/ipcNames.ts b/src/common/ipcNames.ts index 95adb1e1..d2d5d026 100644 --- a/src/common/ipcNames.ts +++ b/src/common/ipcNames.ts @@ -59,7 +59,7 @@ const modules = { open_dev_tools: 'open_dev_tools', set_power_save_blocker: 'set_power_save_blocker', - progress: 'progress', + player_status: 'player_status', change_tray: 'change_tray', quit_update: 'quit_update', update_check: 'update_check', @@ -134,6 +134,7 @@ const modules = { clear_music_url: 'clear_music_url', get_music_url_count: 'get_music_url_count', + open_api_action: 'open_api_action', sync_action: 'sync_action', sync_get_server_devices: 'sync_get_server_devices', sync_remove_server_device: 'sync_remove_server_device', diff --git a/src/common/types/app_setting.d.ts b/src/common/types/app_setting.d.ts index 3452934b..edc826c7 100644 --- a/src/common/types/app_setting.d.ts +++ b/src/common/types/app_setting.d.ts @@ -619,6 +619,17 @@ declare global { */ 'sync.client.host': string + + /** + * 是否启用开放API服务 + */ + 'openAPI.enable': boolean + + /** + * 同步服务端口号 + */ + 'openAPI.port': '23333' | string + /** * 是否在离开搜索界面时自动清空搜索框 */ diff --git a/src/common/types/open_api.d.ts b/src/common/types/open_api.d.ts new file mode 100644 index 00000000..9b16dfd2 --- /dev/null +++ b/src/common/types/open_api.d.ts @@ -0,0 +1,25 @@ +declare namespace LX { + namespace OpenAPI { + interface Status { + status: boolean + message: string + address: string + } + interface EnableServer { + enable: boolean + port: string + } + + interface ActionBase { + action: A + } + interface ActionData extends ActionBase { + data: D + } + type Action = D extends undefined ? ActionBase : ActionData + + type Actions = Action<'status'> + | Action<'enable', EnableServer> + + } +} diff --git a/src/common/types/player.d.ts b/src/common/types/player.d.ts index 483332ae..161ef813 100644 --- a/src/common/types/player.d.ts +++ b/src/common/types/player.d.ts @@ -15,5 +15,18 @@ declare namespace LX { interface LyricInfo extends LX.Music.LyricInfo { rawlrcInfo: LX.Music.LyricInfo } + + interface Status { + status: 'playing' | 'paused' | 'error' | 'stoped' + name: string + singer: string + albumName: string + picUrl: string + progress: number + duration: number + lyricLineText: string + lyric: string + collect: boolean + } } } diff --git a/src/common/utils/lyric-font-player/index.js b/src/common/utils/lyric-font-player/index.js index d5c4fe8c..4c8ab42e 100644 --- a/src/common/utils/lyric-font-player/index.js +++ b/src/common/utils/lyric-font-player/index.js @@ -227,4 +227,8 @@ export default class Lyric { this._handleLinePlayerOnPlay(num, '', this.linePlayer._currentTime()) } else this.playingLineNum = 0 } + + setAutoPause(autoPause) { + this.linePlayer.setAutoPause(autoPause) + } } diff --git a/src/common/utils/lyric-font-player/line-player.js b/src/common/utils/lyric-font-player/line-player.js index 8d928f9f..1d0e0f42 100644 --- a/src/common/utils/lyric-font-player/line-player.js +++ b/src/common/utils/lyric-font-player/line-player.js @@ -224,4 +224,16 @@ export default class LinePlayer { this.extendedLyrics = extendedLyrics this._init() } + + setAutoPause(autoPause) { + if (autoPause) { + timeoutTools.nextTick = window.requestAnimationFrame.bind(window) + timeoutTools.cancelNextTick = window.cancelAnimationFrame.bind(window) + } else { + timeoutTools.nextTick = (handler) => { + return setTimeout(handler, 80) + } + timeoutTools.cancelNextTick = clearTimeout.bind(global) + } + } } diff --git a/src/common/utils/lyric-font-player/utils.js b/src/common/utils/lyric-font-player/utils.js index e82785ed..47ec21d7 100644 --- a/src/common/utils/lyric-font-player/utils.js +++ b/src/common/utils/lyric-font-player/utils.js @@ -3,6 +3,8 @@ export const getNow = typeof performance == 'object' && window.performance.now ? export class TimeoutTools { constructor(thresholdTime = 80) { + this.nextTick = window.requestAnimationFrame.bind(window) + this.cancelNextTick = window.cancelAnimationFrame.bind(window) this.invokeTime = 0 this.animationFrameId = null this.timeoutId = null @@ -11,7 +13,7 @@ export class TimeoutTools { } run() { - this.animationFrameId = window.requestAnimationFrame(() => { + this.animationFrameId = this.nextTick(() => { this.animationFrameId = null let diff = this.invokeTime - getNow() // console.log('diff', diff) @@ -39,7 +41,7 @@ export class TimeoutTools { clear() { if (this.animationFrameId) { - window.cancelAnimationFrame(this.animationFrameId) + this.cancelNextTick(this.animationFrameId) this.animationFrameId = null } if (this.timeoutId) { diff --git a/src/lang/en-us.json b/src/lang/en-us.json index 8f67e9ca..6326065b 100644 --- a/src/lang/en-us.json +++ b/src/lang/en-us.json @@ -460,6 +460,13 @@ "setting__odc": "Auto clear", "setting__odc_clear_search_input": "Clear the search box when you are not searching", "setting__odc_clear_search_list": "Clear the search list when you are not searching", + "setting__open_api": "Open API", + "setting__open_api_address": "Service address: {address}", + "setting__open_api_enable": "Enable open API service", + "setting__open_api_port": "Service port", + "setting__open_api_port_tip": "Please enter the open API service port", + "setting__open_api_tip": "This function is used to provide third-party software with the ability to call LX Music. You can see the currently available functions: ", + "setting__open_api_tip_link": "Access document", "setting__other": "Extras", "setting__other_dislike_list": "dislike song rule", "setting__other_dislike_list_label": "Number of rules:", diff --git a/src/lang/zh-cn.json b/src/lang/zh-cn.json index bf85afb7..a394e3d6 100644 --- a/src/lang/zh-cn.json +++ b/src/lang/zh-cn.json @@ -460,6 +460,13 @@ "setting__odc": "强迫症设置", "setting__odc_clear_search_input": "离开搜索界面时清空搜索框", "setting__odc_clear_search_list": "离开搜索界面时清空搜索列表", + "setting__open_api": "开放API", + "setting__open_api_address": "服务地址:{address}", + "setting__open_api_enable": "启用开放API服务", + "setting__open_api_port": "服务端口", + "setting__open_api_port_tip": "请输入开放API服务端口", + "setting__open_api_tip": "该功能用于为第三方软件提供调用LX Music的能力,目前可用的功能可以看:", + "setting__open_api_tip_link": "接入文档", "setting__other": "其他", "setting__other_dislike_list": "不喜欢的歌曲规则", "setting__other_dislike_list_label": "规则数量:", diff --git a/src/lang/zh-tw.json b/src/lang/zh-tw.json index 1b99ae90..3f842cca 100644 --- a/src/lang/zh-tw.json +++ b/src/lang/zh-tw.json @@ -460,6 +460,13 @@ "setting__odc": "強迫症設定", "setting__odc_clear_search_input": "離開搜尋介面時清空搜尋框", "setting__odc_clear_search_list": "離開搜尋介面時清空搜尋列表", + "setting__open_api": "開放API", + "setting__open_api_address": "服務地址:{address}", + "setting__open_api_enable": "啟用開放API服務", + "setting__open_api_port": "服務連接埠", + "setting__open_api_port_tip": "請輸入開放API服務端口", + "setting__open_api_tip": "此功能用於為第三方軟體提供呼叫LX Music的能力,目前可用的功能可以看:", + "setting__open_api_tip_link": "接上文件", "setting__other": "其他", "setting__other_dislike_list": "不喜歡的歌曲規則", "setting__other_dislike_list_label": "規則數量:", diff --git a/src/main/app.ts b/src/main/app.ts index f10a4f95..0b443a8b 100644 --- a/src/main/app.ts +++ b/src/main/app.ts @@ -234,6 +234,18 @@ export const initAppSetting = async() => { colors: {}, }, }, + player_status: { + status: 'stoped', + name: '', + singer: '', + albumName: '', + picUrl: '', + progress: 0, + duration: 0, + lyricLineText: '', + lyric: '', + collect: false, + }, } } diff --git a/src/main/event/AppEvent.ts b/src/main/event/AppEvent.ts index 1f8045a5..403f5335 100644 --- a/src/main/event/AppEvent.ts +++ b/src/main/event/AppEvent.ts @@ -52,6 +52,14 @@ export class Event extends EventEmitter { this.emit('deeplink', link) } + player_status(status: Partial) { + for (const [key, value] of Object.entries(status)) { + // @ts-expect-error + global.lx.player_status[key] = value + } + this.emit('player_status', status) + } + hot_key_down(keyInfo: LX.HotKeyDownInfo) { this.emit('hot_key_down', keyInfo) } diff --git a/src/main/modules/openApi/index.ts b/src/main/modules/openApi/index.ts new file mode 100644 index 00000000..e58a7baa --- /dev/null +++ b/src/main/modules/openApi/index.ts @@ -0,0 +1,107 @@ +import http from 'node:http' + +let status: LX.OpenAPI.Status = { + status: false, + message: '', + address: '', +} + +let httpServer: http.Server + +const handleStartServer = async(port = 9000, ip = '127.0.0.1') => new Promise((resolve, reject) => { + httpServer = http.createServer((req, res) => { + // console.log(req.url) + const endUrl = `/${req.url?.split('/').at(-1) ?? ''}` + let code + let msg + switch (endUrl) { + case '/status': + code = 200 + res.setHeader('Content-Type', 'application/json; charset=utf-8') + msg = JSON.stringify({ + status: global.lx.player_status.status, + name: global.lx.player_status.name, + singer: global.lx.player_status.singer, + albumName: global.lx.player_status.albumName, + duration: global.lx.player_status.duration, + progress: global.lx.player_status.progress, + picUrl: global.lx.player_status.picUrl, + lyricLineText: global.lx.player_status.lyricLineText, + }) + break + case '/lyric': + code = 200 + res.setHeader('Content-Type', 'text/plain; charset=utf-8') + msg = global.lx.player_status.lyric + break + default: + code = 401 + msg = 'Forbidden' + break + } + if (!code) return + res.writeHead(code) + res.end(msg) + }) + httpServer.on('error', error => { + console.log(error) + reject(error) + }) + + httpServer.on('listening', () => { + const addr = httpServer.address() + // console.log(addr) + if (!addr) { + reject(new Error('address is null')) + return + } + resolve() + }) + httpServer.listen(port, ip) +}) + +const handleStopServer = async() => new Promise((resolve, reject) => { + if (!httpServer) return + httpServer.close((err) => { + if (err) { + reject(err) + return + } + resolve() + }) +}) + + +export const stopServer = async() => { + if (!status.status) { + status.status = false + status.message = '' + status.address = '' + return status + } + await handleStopServer().then(() => { + status.status = false + status.message = '' + status.address = '' + }).catch(err => { + console.log(err) + status.message = err.message + }) + return status +} +export const startServer = async(port: number) => { + if (status.status) await handleStopServer() + await handleStartServer(port).then(() => { + status.status = true + status.message = '' + status.address = `http://localhost${port == 80 ? '' : ':' + port}` + }).catch(err => { + console.log(err) + status.status = false + status.message = err.message + status.address = '' + }) + return status +} + +export const getStatus = (): LX.OpenAPI.Status => status diff --git a/src/main/modules/winMain/index.ts b/src/main/modules/winMain/index.ts index 933a4008..85e55f81 100644 --- a/src/main/modules/winMain/index.ts +++ b/src/main/modules/winMain/index.ts @@ -1,7 +1,7 @@ import initRendererEvent, { handleKeyDown, hotKeyConfigUpdate } from './rendererEvent' import { APP_EVENT_NAMES } from '@common/constants' -import { createWindow, minimize, toggleHide, toggleMinimize } from './main' +import { createWindow, minimize, setProgressBar, setThumbarButtons, toggleHide, toggleMinimize } from './main' import initUpdate from './autoUpdate' import { HOTKEY_COMMON } from '@common/hotKey' import { quitApp } from '@main/app' @@ -38,6 +38,78 @@ export default () => { global.lx.event_app.on('app_inited', () => { createWindow() }) + + const keys = (['status', 'collect'] as const) satisfies Array + const taskBarButtonFlags: LX.TaskBarButtonFlags = { + empty: true, + collect: false, + play: false, + next: true, + prev: true, + } + const progressStatus = { + progress: 0, + status: 'none' as Electron.ProgressBarOptions['mode'], + } + let showProgress = global.lx.appSetting['player.isShowTaskProgess'] + global.lx.event_app.on('player_status', (status) => { + if (status.status) { + switch (status.status) { + case 'paused': + taskBarButtonFlags.play = false + taskBarButtonFlags.empty &&= false + progressStatus.status = 'paused' + break + case 'error': + taskBarButtonFlags.play = false + taskBarButtonFlags.empty &&= false + progressStatus.status = 'error' + break + case 'playing': + taskBarButtonFlags.play = true + taskBarButtonFlags.empty &&= false + progressStatus.status = 'normal' + break + case 'stoped': + taskBarButtonFlags.play &&= false + taskBarButtonFlags.empty = true + progressStatus.status = 'none' + progressStatus.progress = 0 + break + } + if (showProgress) { + setProgressBar(progressStatus.progress, { + mode: progressStatus.status, + }) + } + } + if (keys.some(k => status[k] != null)) { + if (status.collect != null) taskBarButtonFlags.collect = status.collect + setThumbarButtons(taskBarButtonFlags) + } + if (status.progress) { + const progress = status.progress / global.lx.player_status.duration + if (progress.toFixed(2) == progressStatus.progress.toFixed(2)) return + progressStatus.progress = progress + if (showProgress) { + setProgressBar(progress, { + mode: progressStatus.status, + }) + } + } + }) + global.lx.event_app.on('updated_config', (keys, setting) => { + if (keys.includes('player.isShowTaskProgess')) { + showProgress = setting['player.isShowTaskProgess']! + if (showProgress) { + setProgressBar(progressStatus.progress, { + mode: progressStatus.status, + }) + } else { + setProgressBar(-1, { mode: 'none' }) + } + } + }) } export * from './main' diff --git a/src/main/modules/winMain/rendererEvent/app.ts b/src/main/modules/winMain/rendererEvent/app.ts index 55702e3b..2e6b5574 100644 --- a/src/main/modules/winMain/rendererEvent/app.ts +++ b/src/main/modules/winMain/rendererEvent/app.ts @@ -14,10 +14,8 @@ import { getCacheSize, toggleDevTools, setWindowBounds, - setProgressBar, setIgnoreMouseEvents, // setThumbnailClip, - setThumbarButtons, toggleMinimize, toggleHide, showSelectDialog, @@ -106,13 +104,6 @@ export default () => { setWindowBounds(params) }) - mainOn(WIN_MAIN_RENDERER_EVENT_NAME.progress, ({ params }) => { - // console.log(params) - setProgressBar(params.progress, { - mode: params.mode ?? 'normal', - }) - }) - mainOn(WIN_MAIN_RENDERER_EVENT_NAME.set_ignore_mouse_events, ({ params: isIgnored }) => { isIgnored ? setIgnoreMouseEvents(isIgnored, { forward: true }) @@ -123,8 +114,9 @@ export default () => { // return setThumbnailClip(params) // }) - mainOn(WIN_MAIN_RENDERER_EVENT_NAME.player_action_set_buttons, ({ params }) => { - setThumbarButtons(params) + mainOn(WIN_MAIN_RENDERER_EVENT_NAME.player_status, ({ params }) => { + // setThumbarButtons(params) + global.lx.event_app.player_status(params) }) mainOn(WIN_MAIN_RENDERER_EVENT_NAME.inited, () => { diff --git a/src/main/modules/winMain/rendererEvent/index.ts b/src/main/modules/winMain/rendererEvent/index.ts index 869bb71c..f2200ad7 100644 --- a/src/main/modules/winMain/rendererEvent/index.ts +++ b/src/main/modules/winMain/rendererEvent/index.ts @@ -11,6 +11,7 @@ import data from './data' import music from './music' import download from './download' import soundEffect from './soundEffect' +import openAPI from './openAPI' import { sendEvent } from '../main' export * from './app' @@ -37,6 +38,7 @@ export default () => { music() download() soundEffect() + openAPI() global.lx.event_app.on('updated_config', (keys, setting) => { sendConfigChange(setting) diff --git a/src/main/modules/winMain/rendererEvent/openAPI.ts b/src/main/modules/winMain/rendererEvent/openAPI.ts new file mode 100644 index 00000000..8731af97 --- /dev/null +++ b/src/main/modules/winMain/rendererEvent/openAPI.ts @@ -0,0 +1,18 @@ +import { mainHandle } from '@common/mainIpc' +import { WIN_MAIN_RENDERER_EVENT_NAME } from '@common/ipcNames' +import { + startServer, + stopServer, + getStatus, +} from '@main/modules/openApi' + + +export default () => { + mainHandle(WIN_MAIN_RENDERER_EVENT_NAME.open_api_action, async({ params: data }) => { + switch (data.action) { + case 'enable': + return data.data.enable ? await startServer(parseInt(data.data.port)) : await stopServer() + case 'status': return getStatus() + } + }) +} diff --git a/src/main/types/app.d.ts b/src/main/types/app.d.ts index 13c87adc..2b3b316a 100644 --- a/src/main/types/app.d.ts +++ b/src/main/types/app.d.ts @@ -30,6 +30,7 @@ interface Lx { dbService: DBSeriveTypes } theme: LX.ThemeSetting + player_status: LX.Player.Status } declare global { diff --git a/src/main/types/common.d.ts b/src/main/types/common.d.ts index f139f1e5..378650ee 100644 --- a/src/main/types/common.d.ts +++ b/src/main/types/common.d.ts @@ -14,3 +14,4 @@ import '@common/types/ipc_main' import '@common/types/sound_effect' import '@common/types/dislike_list' import '@common/types/dislike_list_sync' +import '@common/types/open_api' diff --git a/src/renderer/core/lyric.ts b/src/renderer/core/lyric.ts index b9df1b54..bcc05895 100644 --- a/src/renderer/core/lyric.ts +++ b/src/renderer/core/lyric.ts @@ -87,6 +87,7 @@ export const init = () => { onPlay(line, text) { setText(text, Math.max(line, 0)) setStatusText(text) + window.app_event.lyricLinePlay(text) // console.log(line, text) }, onSetLyric(lines, offset) { // listening lyrics seting event @@ -185,6 +186,10 @@ export const setLyric = () => { } } +export const setAutoPause = (autoPause: boolean) => { + lrc.setAutoPause(autoPause) +} + export const play = () => { // if (!musicInfo.lrc) return diff --git a/src/renderer/core/useApp/index.ts b/src/renderer/core/useApp/index.ts index ffb1b152..071e9f4b 100644 --- a/src/renderer/core/useApp/index.ts +++ b/src/renderer/core/useApp/index.ts @@ -4,6 +4,7 @@ import { proxy, isFullscreen, themeId } from '@renderer/store' import { appSetting } from '@renderer/store/setting' import useSync from './useSync' +import useOpenAPI from './useOpenAPI' import useUpdate from './useUpdate' import useDataInit from './useDataInit' import useHandleEnvParams from './useHandleEnvParams' @@ -25,6 +26,7 @@ export default () => { const router = useRouter() const initSyncService = useSync() + const initOpenAPI = useOpenAPI() useEventListener() const initPlayer = usePlayer() const handleEnvParams = useHandleEnvParams() @@ -62,6 +64,7 @@ export default () => { handleEnvParams(envParams) // 处理传入的启动参数 void initDeeplink(envParams) void initSyncService() + void initOpenAPI() sendInited() handleListAutoUpdate() diff --git a/src/renderer/core/useApp/useOpenAPI.ts b/src/renderer/core/useApp/useOpenAPI.ts new file mode 100644 index 00000000..defb2309 --- /dev/null +++ b/src/renderer/core/useApp/useOpenAPI.ts @@ -0,0 +1,42 @@ +import { watch } from '@common/utils/vueTools' +import { appSetting } from '@renderer/store/setting' +import { sendOpenAPIAction } from '@renderer/utils/ipc' +import { openAPI } from '@renderer/store' +import { setAutoPause } from '@renderer/core/lyric' + +export default () => { + const handleEnable = async(enable: boolean, port: string) => { + await sendOpenAPIAction({ + action: 'enable', + data: { + enable, + port, + }, + }).then((status) => { + openAPI.address = status.address + openAPI.message = status.message + }).catch((error) => { + openAPI.address = '' + openAPI.message = error.message + }).finally(() => { + if (openAPI.address) { + setAutoPause(false) + } else { + setAutoPause(true) + } + }) + } + watch(() => appSetting['openAPI.enable'], enable => { + void handleEnable(enable, appSetting['openAPI.port']) + }) + + watch(() => appSetting['openAPI.port'], port => { + void handleEnable(appSetting['openAPI.enable'], port) + }) + + return async() => { + if (appSetting['openAPI.enable']) { + void handleEnable(true, appSetting['openAPI.port']) + } + } +} diff --git a/src/renderer/core/useApp/usePlayer/usePlayProgress.ts b/src/renderer/core/useApp/usePlayer/usePlayProgress.ts index f441c025..4e0b451d 100644 --- a/src/renderer/core/useApp/usePlayer/usePlayProgress.ts +++ b/src/renderer/core/useApp/usePlayer/usePlayProgress.ts @@ -1,7 +1,7 @@ import { onBeforeUnmount, watch } from '@common/utils/vueTools' import { formatPlayTime2, getRandom } from '@common/utils/common' import { throttle } from '@common/utils' -import { setTaskBarProgress, savePlayInfo } from '@renderer/utils/ipc' +import { savePlayInfo } from '@renderer/utils/ipc' import { onTimeupdate, getCurrentTime, getDuration, setCurrentTime, onVisibilityChange } from '@renderer/plugins/player' import { playProgress, setNowPlayTime, setMaxplayTime } from '@renderer/store/player/playProgress' import { musicInfo, playMusicInfo, playInfo } from '@renderer/store/player/state' @@ -14,7 +14,6 @@ const delaySavePlayInfo = throttle(savePlayInfo, 2000) export default () => { let restorePlayTime = 0 - let prevProgressStatus: Electron.ProgressBarOptions['mode'] = 'none' const mediaBuffer: { timeout: NodeJS.Timeout | null playTime: number @@ -75,32 +74,18 @@ export default () => { // if (!isPlay) audio.play() } - const handleSetTaskBarState = (progress: number, status?: Electron.ProgressBarOptions['mode']) => { - if (appSetting['player.isShowTaskProgess']) setTaskBarProgress(progress, status) - } - - const handlePlay = () => { - prevProgressStatus = 'normal' - handleSetTaskBarState(playProgress.progress, prevProgressStatus) - } const handlePause = () => { - prevProgressStatus = 'paused' - handleSetTaskBarState(playProgress.progress, prevProgressStatus) clearBufferTimeout() } const handleStop = () => { setNowPlayTime(0) setMaxplayTime(0) - prevProgressStatus = 'none' - handleSetTaskBarState(playProgress.progress, prevProgressStatus) } const handleError = () => { restorePlayTime ||= getCurrentTime() // 记录出错的播放时间 console.log('handleError') - prevProgressStatus = 'error' - handleSetTaskBarState(playProgress.progress, prevProgressStatus) } const handleLoadeddata = () => { @@ -157,10 +142,6 @@ export default () => { } } - watch(() => playProgress.progress, (newValue, oldValue) => { - if (newValue.toFixed(2) === oldValue.toFixed(2)) return - handleSetTaskBarState(newValue, prevProgressStatus) - }) watch(() => playProgress.nowPlayTime, (newValue, oldValue) => { if (Math.abs(newValue - oldValue) > 2) window.app_event.activePlayProgressTransition() if (appSetting['player.isSavePlayTime'] && !playMusicInfo.isTempPlay) { @@ -183,7 +164,7 @@ export default () => { } }) - window.app_event.on('play', handlePlay) + // window.app_event.on('play', handlePlay) window.app_event.on('pause', handlePause) window.app_event.on('stop', handleStop) window.app_event.on('error', handleError) @@ -213,7 +194,7 @@ export default () => { onBeforeUnmount(() => { rOnTimeupdate() rVisibilityChange() - window.app_event.off('play', handlePlay) + // window.app_event.off('play', handlePlay) window.app_event.off('pause', handlePause) window.app_event.off('stop', handleStop) window.app_event.off('error', handleError) diff --git a/src/renderer/core/useApp/usePlayer/usePlayStatus.ts b/src/renderer/core/useApp/usePlayer/usePlayStatus.ts index b3dadfe6..575168e2 100644 --- a/src/renderer/core/useApp/usePlayer/usePlayStatus.ts +++ b/src/renderer/core/useApp/usePlayer/usePlayStatus.ts @@ -1,55 +1,65 @@ -import { onBeforeUnmount } from '@common/utils/vueTools' -import { setPlayerAction, onPlayerAction } from '@renderer/utils/ipc' +import { onBeforeUnmount, watch } from '@common/utils/vueTools' +import { sendPlayerStatus, onPlayerAction } from '@renderer/utils/ipc' // import store from '@renderer/store' import { loveList } from '@renderer/store/list/state' import { addListMusics, removeListMusics, checkListExistMusic } from '@renderer/store/list/action' -import { playMusicInfo } from '@renderer/store/player/state' +import { playMusicInfo, musicInfo } from '@renderer/store/player/state' import { throttle } from '@common/utils' import { pause, play, playNext, playPrev } from '@renderer/core/player' +import { playProgress } from '@renderer/store/player/playProgress' export default () => { // const setVisibleDesktopLyric = useCommit('setVisibleDesktopLyric') // const setLockDesktopLyric = useCommit('setLockDesktopLyric') + let collect = false - const buttons = { - empty: true, - collect: false, - play: false, - prev: true, - next: true, - lrc: false, - lockLrc: false, - } - const setButtons = () => { - setPlayerAction(buttons) - } const updateCollectStatus = async() => { let status = !!playMusicInfo.musicInfo && await checkListExistMusic(loveList.id, playMusicInfo.musicInfo.id) - if (buttons.collect == status) return false - buttons.collect = status + if (collect == status) return false + collect = status return true } const handlePlay = () => { - buttons.empty &&= false - buttons.play = true - setButtons() + sendPlayerStatus({ status: 'playing' }) } const handlePause = () => { - buttons.empty &&= false - buttons.play = false - setButtons() + sendPlayerStatus({ status: 'paused' }) } const handleStop = () => { if (playMusicInfo.musicInfo != null) return - buttons.collect &&= false - buttons.empty = true - setButtons() + sendPlayerStatus({ status: 'stoped' }) } - const handleSetPlayInfo = () => { - void updateCollectStatus().then(isExist => { - if (isExist) setButtons() + const handleError = () => { + sendPlayerStatus({ status: 'error' }) + } + const handleSetPlayInfo = async() => { + await updateCollectStatus() + sendPlayerStatus({ + collect, + name: musicInfo.name, + singer: musicInfo.singer, + albumName: musicInfo.album, + picUrl: musicInfo.pic ?? '', + lyric: musicInfo.lrc ?? '', + lyricLineText: '', + }) + } + const handleSetLyric = () => { + sendPlayerStatus({ + lyric: musicInfo.lrc ?? '', + lyricLineText: '', + }) + } + const handleSetPic = () => { + sendPlayerStatus({ + picUrl: musicInfo.pic ?? '', + }) + } + const handleSetLyricLine = (text: string) => { + sendPlayerStatus({ + lyricLineText: text, }) } // const handleSetTaskbarThumbnailClip = (clip) => { @@ -57,7 +67,7 @@ export default () => { // } const throttleListChange = throttle(async listIds => { if (!listIds.includes(loveList.id)) return - if (await updateCollectStatus()) setButtons() + if (await updateCollectStatus()) sendPlayerStatus({ collect }) }) // const updateSetting = () => { // const setting = store.getters.setting @@ -82,12 +92,12 @@ export default () => { case 'collect': if (!playMusicInfo.musicInfo) return void addListMusics(loveList.id, ['progress' in playMusicInfo.musicInfo ? playMusicInfo.musicInfo.metadata.musicInfo : playMusicInfo.musicInfo]) - if (await updateCollectStatus()) setButtons() + if (await updateCollectStatus()) sendPlayerStatus({ collect }) break case 'unCollect': if (!playMusicInfo.musicInfo) return void removeListMusics({ listId: loveList.id, ids: ['progress' in playMusicInfo.musicInfo ? playMusicInfo.musicInfo.metadata.musicInfo.id : playMusicInfo.musicInfo.id] }) - if (await updateCollectStatus()) setButtons() + if (await updateCollectStatus()) sendPlayerStatus({ collect }) break // case 'lrc': // setVisibleDesktopLyric(true) @@ -107,10 +117,24 @@ export default () => { // break } }) + watch(() => playProgress.nowPlayTime, (newValue, oldValue) => { + // console.log(playProgress.nowPlayTime, newValue, oldValue) + // if (newValue.toFixed(2) === oldValue.toFixed(2)) return + // console.log(playProgress.nowPlayTime) + sendPlayerStatus({ progress: newValue }) + }) + watch(() => playProgress.maxPlayTime, (newValue) => { + sendPlayerStatus({ duration: newValue }) + }) + window.app_event.on('play', handlePlay) window.app_event.on('pause', handlePause) window.app_event.on('stop', handleStop) + window.app_event.on('error', handleError) window.app_event.on('musicToggled', handleSetPlayInfo) + window.app_event.on('lyricUpdated', handleSetLyric) + window.app_event.on('picUpdated', handleSetPic) + window.app_event.on('lyricLinePlay', handleSetLyricLine) // window.app_event.on(eventTaskbarNames.setTaskbarThumbnailClip, handleSetTaskbarThumbnailClip) window.app_event.on('myListUpdate', throttleListChange) @@ -119,7 +143,11 @@ export default () => { window.app_event.off('play', handlePlay) window.app_event.off('pause', handlePause) window.app_event.off('stop', handleStop) + window.app_event.off('error', handleError) window.app_event.off('musicToggled', handleSetPlayInfo) + window.app_event.off('lyricUpdated', handleSetLyric) + window.app_event.off('picUpdated', handleSetPic) + window.app_event.off('lyricLinePlay', handleSetLyricLine) // window.app_event.off(eventTaskbarNames.setTaskbarThumbnailClip, handleSetTaskbarThumbnailClip) window.app_event.off('myListUpdate', throttleListChange) }) @@ -129,7 +157,14 @@ export default () => { // buttons.lrc = setting.desktopLyric.enable // buttons.lockLrc = setting.desktopLyric.isLock await updateCollectStatus() - if (playMusicInfo.musicInfo != null) buttons.empty = false - setButtons() + if (playMusicInfo.musicInfo == null) return + sendPlayerStatus({ + collect, + name: musicInfo.name, + singer: musicInfo.singer, + albumName: musicInfo.album, + picUrl: musicInfo.pic ?? '', + lyric: musicInfo.lrc ?? '', + }) } } diff --git a/src/renderer/core/useApp/useSettingSync.ts b/src/renderer/core/useApp/useSettingSync.ts index f6d6601f..3737b5dc 100644 --- a/src/renderer/core/useApp/useSettingSync.ts +++ b/src/renderer/core/useApp/useSettingSync.ts @@ -1,7 +1,7 @@ import { watch } from '@common/utils/vueTools' import { isFullscreen, proxy, sync, windowSizeList } from '@renderer/store' import { appSetting } from '@renderer/store/setting' -import { sendSyncAction, setTaskBarProgress, setWindowSize } from '@renderer/utils/ipc' +import { sendSyncAction, setWindowSize } from '@renderer/utils/ipc' import { setLanguage } from '@root/lang' import { setUserApi } from '../apiSource' // import { applyTheme, getThemes } from '@renderer/store/utils' @@ -106,11 +106,4 @@ export default () => { watch(() => appSetting['network.proxy.port'], port => { proxy.port = port }) - - watch(() => appSetting['player.isShowTaskProgess'], val => { - if (val) return - setTimeout(() => { - setTaskBarProgress(-1, 'normal') - }) - }) } diff --git a/src/renderer/event/appEvent.ts b/src/renderer/event/appEvent.ts index 264c3d17..d79105c7 100644 --- a/src/renderer/event/appEvent.ts +++ b/src/renderer/event/appEvent.ts @@ -144,6 +144,11 @@ export class AppEvent extends Event { this.emit('lyricOffsetUpdate') } + // 歌词行播放 + lyricLinePlay(text: string) { + this.emit('lyricLinePlay', text) + } + // 我的列表改变事件 myListUpdate(ids: string[]) { this.emit('myListUpdate', ids) diff --git a/src/renderer/store/index.ts b/src/renderer/store/index.ts index 2f5c9077..18d86098 100644 --- a/src/renderer/store/index.ts +++ b/src/renderer/store/index.ts @@ -73,6 +73,11 @@ export const sync: { }, }) +export const openAPI = reactive({ + address: '', + message: '', +}) + export const windowSizeActive = computed(() => { return windowSizeList.find(i => i.id === appSetting['common.windowSizeId']) ?? windowSizeList[0] diff --git a/src/renderer/types/common.d.ts b/src/renderer/types/common.d.ts index 0691cbb4..7436b111 100644 --- a/src/renderer/types/common.d.ts +++ b/src/renderer/types/common.d.ts @@ -16,3 +16,4 @@ import '@common/types/config_files' import '@common/types/music_metadata' import '@common/types/sound_effect' import '@common/types/dislike_list' +import '@common/types/open_api' diff --git a/src/renderer/utils/ipc.ts b/src/renderer/utils/ipc.ts index 77d9a632..2fedaafc 100644 --- a/src/renderer/utils/ipc.ts +++ b/src/renderer/utils/ipc.ts @@ -172,11 +172,13 @@ export const userApiRequestCancel = (requestKey: LX.UserApi.UserApiRequestCancel // } // } -export const setTaskBarProgress = (progress: number, mode?: Electron.ProgressBarOptions['mode']) => { - rendererSend(WIN_MAIN_RENDERER_EVENT_NAME.progress, { - progress: progress < 0 ? progress : Math.max(0.01, progress), - mode: mode ?? 'normal', - }) +export const sendPlayerStatus = (status: Partial) => { + rendererSend>(WIN_MAIN_RENDERER_EVENT_NAME.player_status, status) +} + + +export const sendOpenAPIAction = async(action: LX.OpenAPI.Actions) => { + return rendererInvoke(WIN_MAIN_RENDERER_EVENT_NAME.open_api_action, action) } export const saveLastStartInfo = (version: string) => { diff --git a/src/renderer/views/Setting/components/SettingOpenAPI.vue b/src/renderer/views/Setting/components/SettingOpenAPI.vue new file mode 100644 index 00000000..e8a43aec --- /dev/null +++ b/src/renderer/views/Setting/components/SettingOpenAPI.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/src/renderer/views/Setting/index.vue b/src/renderer/views/Setting/index.vue index d1e7cfa1..1cbd5673 100644 --- a/src/renderer/views/Setting/index.vue +++ b/src/renderer/views/Setting/index.vue @@ -60,6 +60,7 @@ import SettingSearch from './components/SettingSearch.vue' import SettingList from './components/SettingList.vue' import SettingDownload from './components/SettingDownload.vue' import SettingSync from './components/SettingSync/index.vue' +import SettingOpenAPI from './components/SettingOpenAPI.vue' import SettingHotKey from './components/SettingHotKey.vue' import SettingNetwork from './components/SettingNetwork.vue' import SettingOdc from './components/SettingOdc.vue' @@ -79,6 +80,7 @@ export default { SettingList, SettingDownload, SettingSync, + SettingOpenAPI, SettingHotKey, SettingNetwork, SettingOdc, @@ -102,8 +104,9 @@ export default { { id: 'SettingSearch', title: t('setting__search') }, { id: 'SettingList', title: t('setting__list') }, { id: 'SettingDownload', title: t('setting__download') }, - { id: 'SettingSync', title: t('setting__sync') }, { id: 'SettingHotKey', title: t('setting__hot_key') }, + { id: 'SettingSync', title: t('setting__sync') }, + { id: 'SettingOpenAPI', title: t('setting__open_api') }, { id: 'SettingNetwork', title: t('setting__network') }, { id: 'SettingOdc', title: t('setting__odc') }, { id: 'SettingBackup', title: t('setting__backup') },