mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-03 23:30:09 -05:00
[web] Fix styles to comply with Bulma 1.0
This commit is contained in:
parent
b2fbbd3fa0
commit
8140e008f0
427
web-src/package-lock.json
generated
427
web-src/package-lock.json
generated
@ -65,12 +65,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.26.3",
|
"version": "7.26.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz",
|
||||||
"integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==",
|
"integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.26.3"
|
"@babel/types": "^7.26.7"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
@ -80,9 +80,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.26.3",
|
"version": "7.26.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz",
|
||||||
"integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
|
"integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.25.9",
|
"@babel/helper-string-parser": "^7.25.9",
|
||||||
@ -526,13 +526,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/config-array": {
|
"node_modules/@eslint/config-array": {
|
||||||
"version": "0.19.1",
|
"version": "0.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
|
||||||
"integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==",
|
"integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/object-schema": "^2.1.5",
|
"@eslint/object-schema": "^2.1.6",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"minimatch": "^3.1.2"
|
"minimatch": "^3.1.2"
|
||||||
},
|
},
|
||||||
@ -541,9 +541,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/core": {
|
"node_modules/@eslint/core": {
|
||||||
"version": "0.9.1",
|
"version": "0.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz",
|
||||||
"integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==",
|
"integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -578,9 +578,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.17.0",
|
"version": "9.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
|
||||||
"integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==",
|
"integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -588,9 +588,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/object-schema": {
|
"node_modules/@eslint/object-schema": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
|
||||||
"integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==",
|
"integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -598,12 +598,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/plugin-kit": {
|
"node_modules/@eslint/plugin-kit": {
|
||||||
"version": "0.2.4",
|
"version": "0.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz",
|
||||||
"integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==",
|
"integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@eslint/core": "^0.10.0",
|
||||||
"levn": "^0.4.1"
|
"levn": "^0.4.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -840,9 +841,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher": {
|
"node_modules/@parcel/watcher": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
|
||||||
"integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==",
|
"integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -861,25 +862,25 @@
|
|||||||
"url": "https://opencollective.com/parcel"
|
"url": "https://opencollective.com/parcel"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@parcel/watcher-android-arm64": "2.5.0",
|
"@parcel/watcher-android-arm64": "2.5.1",
|
||||||
"@parcel/watcher-darwin-arm64": "2.5.0",
|
"@parcel/watcher-darwin-arm64": "2.5.1",
|
||||||
"@parcel/watcher-darwin-x64": "2.5.0",
|
"@parcel/watcher-darwin-x64": "2.5.1",
|
||||||
"@parcel/watcher-freebsd-x64": "2.5.0",
|
"@parcel/watcher-freebsd-x64": "2.5.1",
|
||||||
"@parcel/watcher-linux-arm-glibc": "2.5.0",
|
"@parcel/watcher-linux-arm-glibc": "2.5.1",
|
||||||
"@parcel/watcher-linux-arm-musl": "2.5.0",
|
"@parcel/watcher-linux-arm-musl": "2.5.1",
|
||||||
"@parcel/watcher-linux-arm64-glibc": "2.5.0",
|
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
|
||||||
"@parcel/watcher-linux-arm64-musl": "2.5.0",
|
"@parcel/watcher-linux-arm64-musl": "2.5.1",
|
||||||
"@parcel/watcher-linux-x64-glibc": "2.5.0",
|
"@parcel/watcher-linux-x64-glibc": "2.5.1",
|
||||||
"@parcel/watcher-linux-x64-musl": "2.5.0",
|
"@parcel/watcher-linux-x64-musl": "2.5.1",
|
||||||
"@parcel/watcher-win32-arm64": "2.5.0",
|
"@parcel/watcher-win32-arm64": "2.5.1",
|
||||||
"@parcel/watcher-win32-ia32": "2.5.0",
|
"@parcel/watcher-win32-ia32": "2.5.1",
|
||||||
"@parcel/watcher-win32-x64": "2.5.0"
|
"@parcel/watcher-win32-x64": "2.5.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-android-arm64": {
|
"node_modules/@parcel/watcher-android-arm64": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
|
||||||
"integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==",
|
"integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -898,9 +899,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-darwin-arm64": {
|
"node_modules/@parcel/watcher-darwin-arm64": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
|
||||||
"integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==",
|
"integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -919,9 +920,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-darwin-x64": {
|
"node_modules/@parcel/watcher-darwin-x64": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
|
||||||
"integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==",
|
"integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -940,9 +941,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-freebsd-x64": {
|
"node_modules/@parcel/watcher-freebsd-x64": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
|
||||||
"integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==",
|
"integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -961,9 +962,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
|
||||||
"integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==",
|
"integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -982,9 +983,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm-musl": {
|
"node_modules/@parcel/watcher-linux-arm-musl": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
|
||||||
"integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==",
|
"integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -1003,9 +1004,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
|
||||||
"integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==",
|
"integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1024,9 +1025,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
|
||||||
"integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==",
|
"integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1045,9 +1046,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
|
||||||
"integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==",
|
"integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1066,9 +1067,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-x64-musl": {
|
"node_modules/@parcel/watcher-linux-x64-musl": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
|
||||||
"integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==",
|
"integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1087,9 +1088,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-win32-arm64": {
|
"node_modules/@parcel/watcher-win32-arm64": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
|
||||||
"integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==",
|
"integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1108,9 +1109,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-win32-ia32": {
|
"node_modules/@parcel/watcher-win32-ia32": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
|
||||||
"integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==",
|
"integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@ -1129,9 +1130,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-win32-x64": {
|
"node_modules/@parcel/watcher-win32-x64": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
|
||||||
"integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==",
|
"integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1173,9 +1174,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.2.tgz",
|
||||||
"integrity": "sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==",
|
"integrity": "sha512-6Fyg9yQbwJR+ykVdT9sid1oc2ewejS6h4wzQltmJfSW53N60G/ah9pngXGANdy9/aaE/TcUFpWosdm7JXS1WTQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -1187,9 +1188,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.2.tgz",
|
||||||
"integrity": "sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==",
|
"integrity": "sha512-K5GfWe+vtQ3kyEbihrimM38UgX57UqHp+oME7X/EX9Im6suwZfa7Hsr8AtzbJvukTpwMGs+4s29YMSO3rwWtsw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1201,9 +1202,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.2.tgz",
|
||||||
"integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==",
|
"integrity": "sha512-PSN58XG/V/tzqDb9kDGutUruycgylMlUE59f40ny6QIRNsTEIZsrNQTJKUN2keMMSmlzgunMFqyaGLmly39sug==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1215,9 +1216,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.2.tgz",
|
||||||
"integrity": "sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==",
|
"integrity": "sha512-gQhK788rQJm9pzmXyfBB84VHViDERhAhzGafw+E5mUpnGKuxZGkMVDa3wgDFKT6ukLC5V7QTifzsUKdNVxp5qQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1229,9 +1230,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.2.tgz",
|
||||||
"integrity": "sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==",
|
"integrity": "sha512-eiaHgQwGPpxLC3+zTAcdKl4VsBl3r0AiJOd1Um/ArEzAjN/dbPK1nROHrVkdnoE6p7Svvn04w3f/jEZSTVHunA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1243,9 +1244,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.2.tgz",
|
||||||
"integrity": "sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==",
|
"integrity": "sha512-lhdiwQ+jf8pewYOTG4bag0Qd68Jn1v2gO1i0mTuiD+Qkt5vNfHVK/jrT7uVvycV8ZchlzXp5HDVmhpzjC6mh0g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1257,9 +1258,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.2.tgz",
|
||||||
"integrity": "sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==",
|
"integrity": "sha512-lfqTpWjSvbgQP1vqGTXdv+/kxIznKXZlI109WkIFPbud41bjigjNmOAAKoazmRGx+k9e3rtIdbq2pQZPV1pMig==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -1271,9 +1272,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.2.tgz",
|
||||||
"integrity": "sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==",
|
"integrity": "sha512-RGjqULqIurqqv+NJTyuPgdZhka8ImMLB32YwUle2BPTDqDoXNgwFjdjQC59FbSk08z0IqlRJjrJ0AvDQ5W5lpw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -1285,9 +1286,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.2.tgz",
|
||||||
"integrity": "sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==",
|
"integrity": "sha512-ZvkPiheyXtXlFqHpsdgscx+tZ7hoR59vOettvArinEspq5fxSDSgfF+L5wqqJ9R4t+n53nyn0sKxeXlik7AY9Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1299,9 +1300,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.2.tgz",
|
||||||
"integrity": "sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==",
|
"integrity": "sha512-UlFk+E46TZEoxD9ufLKDBzfSG7Ki03fo6hsNRRRHF+KuvNZ5vd1RRVQm8YZlGsjcJG8R252XFK0xNPay+4WV7w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1313,9 +1314,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.2.tgz",
|
||||||
"integrity": "sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==",
|
"integrity": "sha512-hJhfsD9ykx59jZuuoQgYT1GEcNNi3RCoEmbo5OGfG8RlHOiVS7iVNev9rhLKh7UBYq409f4uEw0cclTXx8nh8Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@ -1327,9 +1328,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.2.tgz",
|
||||||
"integrity": "sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==",
|
"integrity": "sha512-g/O5IpgtrQqPegvqopvmdCF9vneLE7eqYfdPWW8yjPS8f63DNam3U4ARL1PNNB64XHZDHKpvO2Giftf43puB8Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@ -1341,9 +1342,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.2.tgz",
|
||||||
"integrity": "sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==",
|
"integrity": "sha512-bSQijDC96M6PuooOuXHpvXUYiIwsnDmqGU8+br2U7iPoykNi9JtMUpN7K6xml29e0evK0/g0D1qbAUzWZFHY5Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@ -1355,9 +1356,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.2.tgz",
|
||||||
"integrity": "sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==",
|
"integrity": "sha512-49TtdeVAsdRuiUHXPrFVucaP4SivazetGUVH8CIxVsNsaPHV4PFkpLmH9LeqU/R4Nbgky9lzX5Xe1NrzLyraVA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@ -1369,9 +1370,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.2.tgz",
|
||||||
"integrity": "sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==",
|
"integrity": "sha512-j+jFdfOycLIQ7FWKka9Zd3qvsIyugg5LeZuHF6kFlXo6MSOc6R1w37YUVy8VpAKd81LMWGi5g9J25P09M0SSIw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1383,9 +1384,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.2.tgz",
|
||||||
"integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==",
|
"integrity": "sha512-aDPHyM/D2SpXfSNCVWCxyHmOqN9qb7SWkY1+vaXqMNMXslZYnwh9V/UCudl6psyG0v6Ukj7pXanIpfZwCOEMUg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1397,9 +1398,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.2.tgz",
|
||||||
"integrity": "sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==",
|
"integrity": "sha512-LQRkCyUBnAo7r8dbEdtNU08EKLCJMgAk2oP5H3R7BnUlKLqgR3dUjrLBVirmc1RK6U6qhtDw29Dimeer8d5hzQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -1411,9 +1412,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.2.tgz",
|
||||||
"integrity": "sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==",
|
"integrity": "sha512-wt8OhpQUi6JuPFkm1wbVi1BByeag87LDFzeKSXzIdGcX4bMLqORTtKxLoCbV57BHYNSUSOKlSL4BYYUghainYA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@ -1425,9 +1426,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.2.tgz",
|
||||||
"integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==",
|
"integrity": "sha512-rUrqINax0TvrPBXrFKg0YbQx18NpPN3NNrgmaao9xRNbTwek7lOXObhx8tQy8gelmQ/gLaGy1WptpU2eKJZImg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -1795,9 +1796,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/core-js": {
|
"node_modules/core-js": {
|
||||||
"version": "3.39.0",
|
"version": "3.40.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz",
|
||||||
"integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==",
|
"integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
@ -1974,19 +1975,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.17.0",
|
"version": "9.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz",
|
||||||
"integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==",
|
"integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
"@eslint/config-array": "^0.19.0",
|
"@eslint/config-array": "^0.19.0",
|
||||||
"@eslint/core": "^0.9.0",
|
"@eslint/core": "^0.10.0",
|
||||||
"@eslint/eslintrc": "^3.2.0",
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
"@eslint/js": "9.17.0",
|
"@eslint/js": "9.19.0",
|
||||||
"@eslint/plugin-kit": "^0.2.3",
|
"@eslint/plugin-kit": "^0.2.5",
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@humanwhocodes/retry": "^0.4.1",
|
"@humanwhocodes/retry": "^0.4.1",
|
||||||
@ -2207,9 +2208,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
"version": "3.3.2",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||||
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2217,7 +2218,7 @@
|
|||||||
"@nodelib/fs.walk": "^1.2.3",
|
"@nodelib/fs.walk": "^1.2.3",
|
||||||
"glob-parent": "^5.1.2",
|
"glob-parent": "^5.1.2",
|
||||||
"merge2": "^1.3.0",
|
"merge2": "^1.3.0",
|
||||||
"micromatch": "^4.0.4"
|
"micromatch": "^4.0.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.6.0"
|
"node": ">=8.6.0"
|
||||||
@ -2251,9 +2252,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.18.0",
|
"version": "1.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
|
||||||
"integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
|
"integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2427,9 +2428,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
||||||
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
|
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2747,18 +2748,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mlly": {
|
"node_modules/mlly": {
|
||||||
"version": "1.7.3",
|
"version": "1.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
|
||||||
"integrity": "sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==",
|
"integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "^8.14.0",
|
"acorn": "^8.14.0",
|
||||||
"pathe": "^1.1.2",
|
"pathe": "^2.0.1",
|
||||||
"pkg-types": "^1.2.1",
|
"pkg-types": "^1.3.0",
|
||||||
"ufo": "^1.5.4"
|
"ufo": "^1.5.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mlly/node_modules/pathe": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@ -2922,9 +2930,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pinia": {
|
"node_modules/pinia": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz",
|
||||||
"integrity": "sha512-ohZj3jla0LL0OH5PlLTDMzqKiVw2XARmC1XYLdLWIPBMdhDW/123ZWr4zVAhtJm+aoSkFa13pYXskAvAscIkhQ==",
|
"integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/devtools-api": "^6.6.3",
|
"@vue/devtools-api": "^6.6.3",
|
||||||
@ -2944,21 +2952,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pkg-types": {
|
"node_modules/pkg-types": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
|
||||||
"integrity": "sha512-kS7yWjVFCkIw9hqdJBoMxDdzEngmkr5FXeWZZfQ6GoYacjVnsW6l2CcYW/0ThD0vF4LPJgVYnrg4d0uuhwYQbg==",
|
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"confbox": "^0.1.8",
|
"confbox": "^0.1.8",
|
||||||
"mlly": "^1.7.3",
|
"mlly": "^1.7.4",
|
||||||
"pathe": "^1.1.2"
|
"pathe": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pkg-types/node_modules/pathe": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.49",
|
"version": "8.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
|
||||||
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
|
"integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@ -2975,7 +2990,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.7",
|
"nanoid": "^3.3.8",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
"source-map-js": "^1.2.1"
|
"source-map-js": "^1.2.1"
|
||||||
},
|
},
|
||||||
@ -3061,13 +3076,13 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "4.0.2",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz",
|
||||||
"integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
|
"integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 14.16.0"
|
"node": ">= 14.18.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -3102,9 +3117,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.29.1",
|
"version": "4.34.2",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.2.tgz",
|
||||||
"integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==",
|
"integrity": "sha512-sBDUoxZEaqLu9QeNalL8v3jw6WjPku4wfZGyTU7l7m1oC+rpRihXc/n/H+4148ZkGz5Xli8CHMns//fFGKvpIQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -3118,25 +3133,25 @@
|
|||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.29.1",
|
"@rollup/rollup-android-arm-eabi": "4.34.2",
|
||||||
"@rollup/rollup-android-arm64": "4.29.1",
|
"@rollup/rollup-android-arm64": "4.34.2",
|
||||||
"@rollup/rollup-darwin-arm64": "4.29.1",
|
"@rollup/rollup-darwin-arm64": "4.34.2",
|
||||||
"@rollup/rollup-darwin-x64": "4.29.1",
|
"@rollup/rollup-darwin-x64": "4.34.2",
|
||||||
"@rollup/rollup-freebsd-arm64": "4.29.1",
|
"@rollup/rollup-freebsd-arm64": "4.34.2",
|
||||||
"@rollup/rollup-freebsd-x64": "4.29.1",
|
"@rollup/rollup-freebsd-x64": "4.34.2",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.29.1",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.34.2",
|
||||||
"@rollup/rollup-linux-arm-musleabihf": "4.29.1",
|
"@rollup/rollup-linux-arm-musleabihf": "4.34.2",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.29.1",
|
"@rollup/rollup-linux-arm64-gnu": "4.34.2",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.29.1",
|
"@rollup/rollup-linux-arm64-musl": "4.34.2",
|
||||||
"@rollup/rollup-linux-loongarch64-gnu": "4.29.1",
|
"@rollup/rollup-linux-loongarch64-gnu": "4.34.2",
|
||||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.29.1",
|
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.2",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.29.1",
|
"@rollup/rollup-linux-riscv64-gnu": "4.34.2",
|
||||||
"@rollup/rollup-linux-s390x-gnu": "4.29.1",
|
"@rollup/rollup-linux-s390x-gnu": "4.34.2",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.29.1",
|
"@rollup/rollup-linux-x64-gnu": "4.34.2",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.29.1",
|
"@rollup/rollup-linux-x64-musl": "4.34.2",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.29.1",
|
"@rollup/rollup-win32-arm64-msvc": "4.34.2",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.29.1",
|
"@rollup/rollup-win32-ia32-msvc": "4.34.2",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.29.1",
|
"@rollup/rollup-win32-x64-msvc": "4.34.2",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3165,9 +3180,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sass": {
|
"node_modules/sass": {
|
||||||
"version": "1.83.0",
|
"version": "1.83.4",
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.83.0.tgz",
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.83.4.tgz",
|
||||||
"integrity": "sha512-qsSxlayzoOjdvXMVLkzF84DJFc2HZEL/rFyGIKbbilYtAvlCxyuzUeff9LawTn4btVnLKg75Z8MMr1lxU1lfGw==",
|
"integrity": "sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -3186,9 +3201,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.6.3",
|
"version": "7.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -3326,9 +3341,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/unplugin": {
|
"node_modules/unplugin": {
|
||||||
"version": "1.16.0",
|
"version": "1.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz",
|
||||||
"integrity": "sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ==",
|
"integrity": "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,27 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<navbar-top />
|
||||||
<navbar-top />
|
<vue-progress-bar class="has-background-info" />
|
||||||
<vue-progress-bar class="has-background-info" />
|
<router-view v-slot="{ Component }">
|
||||||
<router-view v-slot="{ Component }">
|
<component :is="Component" />
|
||||||
<component :is="Component" />
|
</router-view>
|
||||||
</router-view>
|
<modal-dialog-remote-pairing
|
||||||
|
:show="pairing_active"
|
||||||
<modal-dialog-remote-pairing
|
@close="pairing_active = false"
|
||||||
:show="pairing_active"
|
/>
|
||||||
@close="pairing_active = false"
|
<modal-dialog-update
|
||||||
/>
|
:show="show_update_dialog"
|
||||||
<modal-dialog-update
|
@close="show_update_dialog = false"
|
||||||
:show="show_update_dialog"
|
/>
|
||||||
@close="show_update_dialog = false"
|
<notification-list v-show="!show_burger_menu" />
|
||||||
/>
|
<navbar-bottom />
|
||||||
<notification-list v-show="!show_burger_menu" />
|
<div
|
||||||
<navbar-bottom />
|
v-show="show_burger_menu || show_player_menu"
|
||||||
<div
|
class="overlay-fullscreen"
|
||||||
v-show="show_burger_menu || show_player_menu"
|
@click="show_burger_menu = show_player_menu = false"
|
||||||
class="fd-overlay-fullscreen"
|
/>
|
||||||
@click="show_burger_menu = show_player_menu = false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -64,5 +64,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<a class="navbar-item" :href="href" @click.stop.prevent="open">
|
<a :href="href" @click.stop.prevent="open">
|
||||||
<slot />
|
<slot />
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
@ -8,7 +8,7 @@
|
|||||||
import { useUIStore } from '@/stores/ui'
|
import { useUIStore } from '@/stores/ui'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NavbarItemLink',
|
name: 'ControlLink',
|
||||||
props: {
|
props: {
|
||||||
to: { required: true, type: Object }
|
to: { required: true, type: Object }
|
||||||
},
|
},
|
62
web-src/src/components/ControlMainVolume.vue
Normal file
62
web-src/src/components/ControlMainVolume.vue
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<template>
|
||||||
|
<div class="media is-align-items-center mb-0">
|
||||||
|
<div class="media-left">
|
||||||
|
<a class="button is-small" @click="toggle">
|
||||||
|
<mdicon class="icon" :name="icon" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="media-content">
|
||||||
|
<div class="is-size-7 is-uppercase" v-text="$t('navigation.volume')" />
|
||||||
|
<control-slider
|
||||||
|
v-model:value="player.volume"
|
||||||
|
:cursor="cursor"
|
||||||
|
:max="100"
|
||||||
|
@change="changeVolume"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ControlSlider from '@/components/ControlSlider.vue'
|
||||||
|
import { mdiCancel } from '@mdi/js'
|
||||||
|
import { usePlayerStore } from '@/stores/player'
|
||||||
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ControlVolume',
|
||||||
|
components: { ControlSlider },
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
player: usePlayerStore()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cursor: mdiCancel,
|
||||||
|
old_volume: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
icon() {
|
||||||
|
return this.player.volume > 0 ? 'volume-high' : 'volume-off'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'player.volume'() {
|
||||||
|
if (this.player.volume > 0) {
|
||||||
|
this.old_volume = this.player.volume
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
changeVolume(value) {
|
||||||
|
webapi.player_volume(this.player.volume)
|
||||||
|
},
|
||||||
|
toggle() {
|
||||||
|
this.player.volume = this.player.volume > 0 ? 0 : this.old_volume
|
||||||
|
this.changeVolume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
79
web-src/src/components/ControlOutputVolume.vue
Normal file
79
web-src/src/components/ControlOutputVolume.vue
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<div class="media is-align-items-center mb-0">
|
||||||
|
<div class="media-left">
|
||||||
|
<a
|
||||||
|
class="button is-small"
|
||||||
|
:class="{ 'has-text-grey-light': !output.selected }"
|
||||||
|
@click="toggle"
|
||||||
|
>
|
||||||
|
<mdicon class="icon" :name="icon" :title="output.type" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="media-content">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
:class="{ 'has-text-grey-light': !output.selected }"
|
||||||
|
v-text="output.name"
|
||||||
|
/>
|
||||||
|
<control-slider
|
||||||
|
v-model:value="volume"
|
||||||
|
:disabled="!output.selected"
|
||||||
|
:max="100"
|
||||||
|
:cursor="cursor"
|
||||||
|
@change="changeVolume"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ControlSlider from '@/components/ControlSlider.vue'
|
||||||
|
import { mdiCancel } from '@mdi/js'
|
||||||
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ControlOutputVolume',
|
||||||
|
components: {
|
||||||
|
ControlSlider
|
||||||
|
},
|
||||||
|
props: { output: { required: true, type: Object } },
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cursor: mdiCancel,
|
||||||
|
volume: this.output.selected ? this.output.volume : 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
icon() {
|
||||||
|
if (this.output.type.startsWith('AirPlay')) {
|
||||||
|
return 'cast-variant'
|
||||||
|
} else if (this.output.type === 'Chromecast') {
|
||||||
|
return 'cast'
|
||||||
|
} else if (this.output.type === 'fifo') {
|
||||||
|
return 'pipe'
|
||||||
|
}
|
||||||
|
return 'server'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
output() {
|
||||||
|
this.volume = this.output.volume
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
changeVolume() {
|
||||||
|
webapi.player_output_volume(this.output.id, this.volume)
|
||||||
|
},
|
||||||
|
toggle() {
|
||||||
|
const values = {
|
||||||
|
selected: !this.output.selected
|
||||||
|
}
|
||||||
|
webapi.output_update(this.output.id, values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<a v-if="visible" :disabled="disabled" @click="seek">
|
<a v-if="visible" :disabled="disabled" @click="seek">
|
||||||
<mdicon
|
<mdicon
|
||||||
|
class="icon"
|
||||||
name="rewind-10"
|
name="rewind-10"
|
||||||
:size="icon_size"
|
|
||||||
:title="$t('player.button.seek-backward')"
|
:title="$t('player.button.seek-backward')"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
@ -14,10 +14,9 @@ import { useQueueStore } from '@/stores/queue'
|
|||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlayerButtonSeekBack',
|
name: 'ControlPlayerBack',
|
||||||
props: {
|
props: {
|
||||||
icon_size: { default: 16, type: Number },
|
offset: { required: true, type: Number }
|
||||||
seek_ms: { required: true, type: Number }
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
@ -52,7 +51,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
seek() {
|
seek() {
|
||||||
if (!this.disabled) {
|
if (!this.disabled) {
|
||||||
webapi.player_seek(this.seek_ms * -1)
|
webapi.player_seek(this.offset * -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<a :class="{ 'is-info': is_consume }" @click="toggle_consume_mode">
|
<a :class="{ 'is-info': is_consume }" @click="toggle">
|
||||||
<mdicon
|
<mdicon
|
||||||
class="icon"
|
class="icon"
|
||||||
name="fire"
|
name="fire"
|
||||||
:size="icon_size"
|
size="16"
|
||||||
:title="$t('player.button.consume')"
|
:title="$t('player.button.consume')"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
@ -14,10 +14,7 @@ import { usePlayerStore } from '@/stores/player'
|
|||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlayerButtonConsume',
|
name: 'ControlPlayerConsume',
|
||||||
props: {
|
|
||||||
icon_size: { default: 16, type: Number }
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
@ -32,11 +29,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
toggle_consume_mode() {
|
toggle() {
|
||||||
webapi.player_consume(!this.is_consume)
|
webapi.player_consume(!this.is_consume)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<a v-if="visible" :disabled="disabled" @click="seek">
|
<a v-if="visible" :disabled="disabled" @click="seek">
|
||||||
<mdicon
|
<mdicon
|
||||||
|
class="icon"
|
||||||
name="fast-forward-30"
|
name="fast-forward-30"
|
||||||
:size="icon_size"
|
|
||||||
:title="$t('player.button.seek-forward')"
|
:title="$t('player.button.seek-forward')"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
@ -14,10 +14,9 @@ import { useQueueStore } from '@/stores/queue'
|
|||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlayerButtonSeekForward',
|
name: 'ControlPlayerForward',
|
||||||
props: {
|
props: {
|
||||||
icon_size: { default: 16, type: Number },
|
offset: { required: true, type: Number }
|
||||||
seek_ms: { required: true, type: Number }
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
@ -52,7 +51,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
seek() {
|
seek() {
|
||||||
if (!this.disabled) {
|
if (!this.disabled) {
|
||||||
webapi.player_seek(this.seek_ms)
|
webapi.player_seek(this.offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<a :class="{ 'is-info': is_active }" @click="toggle_lyrics">
|
<a :class="{ 'is-info': is_active }" @click="toggle">
|
||||||
<mdicon
|
<mdicon
|
||||||
class="icon"
|
class="icon"
|
||||||
:name="icon_name"
|
:name="icon"
|
||||||
:size="icon_size"
|
:size="16"
|
||||||
:title="$t('player.button.toggle-lyrics')"
|
:title="$t('player.button.toggle-lyrics')"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
@ -13,10 +13,7 @@
|
|||||||
import { useLyricsStore } from '@/stores/lyrics'
|
import { useLyricsStore } from '@/stores/lyrics'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlayerButtonLyrics',
|
name: 'ControlPlayerLyrics',
|
||||||
props: {
|
|
||||||
icon_size: { default: 16, type: Number }
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
@ -25,7 +22,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
icon_name() {
|
icon() {
|
||||||
return this.is_active ? 'script-text-play' : 'script-text-outline'
|
return this.is_active ? 'script-text-play' : 'script-text-outline'
|
||||||
},
|
},
|
||||||
is_active() {
|
is_active() {
|
||||||
@ -34,11 +31,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
toggle_lyrics() {
|
toggle() {
|
||||||
this.lyricsStore.pane = !this.lyricsStore.pane
|
this.lyricsStore.pane = !this.lyricsStore.pane
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<a :disabled="disabled" @click="play_next">
|
<a :disabled="disabled" @click="play_next">
|
||||||
<mdicon
|
<mdicon
|
||||||
|
class="icon"
|
||||||
name="skip-forward"
|
name="skip-forward"
|
||||||
:size="icon_size"
|
|
||||||
:title="$t('player.button.skip-forward')"
|
:title="$t('player.button.skip-forward')"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
@ -13,10 +13,7 @@ import { useQueueStore } from '@/stores/queue'
|
|||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlayerButtonNext',
|
name: 'ControlPlayerNext',
|
||||||
props: {
|
|
||||||
icon_size: { default: 16, type: Number }
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
disabled() {
|
disabled() {
|
||||||
@ -29,11 +26,8 @@ export default {
|
|||||||
if (this.disabled) {
|
if (this.disabled) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
webapi.player_next()
|
webapi.player_next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,10 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<a :disabled="disabled" @click="toggle_play_pause">
|
<a :disabled="disabled" @click="toggle">
|
||||||
<mdicon
|
<mdicon class="icon" :name="icon" :title="$t(`player.button.${icon}`)" />
|
||||||
:name="icon_name"
|
|
||||||
:size="icon_size"
|
|
||||||
:title="$t(`player.button.${icon_name}`)"
|
|
||||||
/>
|
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -15,9 +11,8 @@ import { useQueueStore } from '@/stores/queue'
|
|||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlayerButtonPlayPause',
|
name: 'ControlPlayerPlay',
|
||||||
props: {
|
props: {
|
||||||
icon_size: { default: 16, type: Number },
|
|
||||||
show_disabled_message: Boolean
|
show_disabled_message: Boolean
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -33,7 +28,7 @@ export default {
|
|||||||
disabled() {
|
disabled() {
|
||||||
return this.queueStore?.count <= 0
|
return this.queueStore?.count <= 0
|
||||||
},
|
},
|
||||||
icon_name() {
|
icon() {
|
||||||
if (!this.is_playing) {
|
if (!this.is_playing) {
|
||||||
return 'play'
|
return 'play'
|
||||||
} else if (this.is_pause_allowed) {
|
} else if (this.is_pause_allowed) {
|
||||||
@ -51,7 +46,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
toggle_play_pause() {
|
toggle() {
|
||||||
if (this.disabled) {
|
if (this.disabled) {
|
||||||
if (this.show_disabled_message) {
|
if (this.show_disabled_message) {
|
||||||
this.notificationsStore.add({
|
this.notificationsStore.add({
|
||||||
@ -74,5 +69,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<a :disabled="disabled" @click="play_previous">
|
<a :disabled="disabled" @click="play_previous">
|
||||||
<mdicon
|
<mdicon
|
||||||
|
class="icon"
|
||||||
name="skip-backward"
|
name="skip-backward"
|
||||||
:size="icon_size"
|
|
||||||
:title="$t('player.button.skip-backward')"
|
:title="$t('player.button.skip-backward')"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
@ -13,10 +13,7 @@ import { useQueueStore } from '@/stores/queue'
|
|||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlayerButtonPrevious',
|
name: 'ControlPlayerPrevious',
|
||||||
props: {
|
|
||||||
icon_size: { default: 16, type: Number }
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
@ -40,5 +37,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<a :class="{ 'is-info': !is_repeat_off }" @click="toggle_repeat_mode">
|
<a :class="{ 'is-info': !is_repeat_off }" @click="toggle">
|
||||||
<mdicon
|
<mdicon
|
||||||
class="icon"
|
class="icon"
|
||||||
:name="icon_name"
|
:name="icon"
|
||||||
:size="icon_size"
|
:size="16"
|
||||||
:title="$t(`player.button.${icon_name}`)"
|
:title="$t(`player.button.${icon}`)"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
@ -14,19 +14,14 @@ import { usePlayerStore } from '@/stores/player'
|
|||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlayerButtonRepeat',
|
name: 'ControlPlayerRepeat',
|
||||||
props: {
|
|
||||||
icon_size: { default: 16, type: Number }
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
playerStore: usePlayerStore()
|
playerStore: usePlayerStore()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
icon_name() {
|
icon() {
|
||||||
if (this.is_repeat_all) {
|
if (this.is_repeat_all) {
|
||||||
return 'repeat'
|
return 'repeat'
|
||||||
} else if (this.is_repeat_single) {
|
} else if (this.is_repeat_single) {
|
||||||
@ -46,7 +41,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
toggle_repeat_mode() {
|
toggle() {
|
||||||
if (this.is_repeat_all) {
|
if (this.is_repeat_all) {
|
||||||
webapi.player_repeat('single')
|
webapi.player_repeat('single')
|
||||||
} else if (this.is_repeat_single) {
|
} else if (this.is_repeat_single) {
|
||||||
@ -58,5 +53,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<a :class="{ 'is-info': is_shuffle }" @click="toggle_shuffle_mode">
|
<a :class="{ 'is-info': is_shuffle }" @click="toggle">
|
||||||
<mdicon
|
<mdicon
|
||||||
class="icon"
|
class="icon"
|
||||||
:name="icon_name"
|
:name="icon"
|
||||||
:size="icon_size"
|
:size="16"
|
||||||
:title="$t(`player.button.${icon_name}`)"
|
:title="$t(`player.button.${icon}`)"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
@ -14,20 +14,14 @@ import { usePlayerStore } from '@/stores/player'
|
|||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlayerButtonShuffle',
|
name: 'ControlPlayerShuffle',
|
||||||
|
|
||||||
props: {
|
|
||||||
icon_size: { default: 16, type: Number }
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
playerStore: usePlayerStore()
|
playerStore: usePlayerStore()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
icon_name() {
|
icon() {
|
||||||
if (this.is_shuffle) {
|
if (this.is_shuffle) {
|
||||||
return 'shuffle'
|
return 'shuffle'
|
||||||
}
|
}
|
||||||
@ -37,13 +31,10 @@ export default {
|
|||||||
return this.playerStore.shuffle
|
return this.playerStore.shuffle
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
toggle_shuffle_mode() {
|
toggle() {
|
||||||
webapi.player_shuffle(!this.is_shuffle)
|
webapi.player_shuffle(!this.is_shuffle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
89
web-src/src/components/ControlSetting.vue
Normal file
89
web-src/src/components/ControlSetting.vue
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<template>
|
||||||
|
<fieldset :disabled="disabled">
|
||||||
|
<div class="field">
|
||||||
|
<label v-if="$slots.label" class="label has-text-weight-normal">
|
||||||
|
<slot name="label" />
|
||||||
|
</label>
|
||||||
|
<div class="control" :class="{ 'has-icons-right': isSuccess || isError }">
|
||||||
|
<slot name="input" :setting="setting" :update="update" />
|
||||||
|
<mdicon
|
||||||
|
v-if="isSuccess || isError"
|
||||||
|
class="icon is-right"
|
||||||
|
:name="isSuccess ? 'check' : 'close'"
|
||||||
|
size="16"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p v-if="$slots.help" class="help">
|
||||||
|
<slot name="help" />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useSettingsStore } from '@/stores/settings'
|
||||||
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ControlSetting',
|
||||||
|
props: {
|
||||||
|
category: { required: true, type: String },
|
||||||
|
disabled: Boolean,
|
||||||
|
name: { required: true, type: String },
|
||||||
|
placeholder: { default: '', type: String }
|
||||||
|
},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
settingsStore: useSettingsStore()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
timerDelay: 2000,
|
||||||
|
timerId: -1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
isError() {
|
||||||
|
return this.timerId === -2
|
||||||
|
},
|
||||||
|
isSuccess() {
|
||||||
|
return this.timerId >= 0
|
||||||
|
},
|
||||||
|
setting() {
|
||||||
|
return this.settingsStore.setting(this.category, this.name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
update(event, sanitise) {
|
||||||
|
const value = sanitise?.(event.target)
|
||||||
|
if (value === this.setting.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const setting = {
|
||||||
|
category: this.category,
|
||||||
|
name: this.name,
|
||||||
|
value
|
||||||
|
}
|
||||||
|
webapi
|
||||||
|
.settings_update(this.category, setting)
|
||||||
|
.then(() => {
|
||||||
|
window.clearTimeout(this.timerId)
|
||||||
|
this.settingsStore.update(setting)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.timerId = -2
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.timerId = window.setTimeout(() => {
|
||||||
|
this.timerId = -1
|
||||||
|
}, this.timerDelay)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
46
web-src/src/components/ControlSettingIntegerField.vue
Normal file
46
web-src/src/components/ControlSettingIntegerField.vue
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<template>
|
||||||
|
<control-setting
|
||||||
|
:category="category"
|
||||||
|
:disabled="disabled"
|
||||||
|
:name="name"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<slot name="label" />
|
||||||
|
</template>
|
||||||
|
<template #input="{ setting, update }">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
inputmode="numeric"
|
||||||
|
min="0"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:value="setting.value"
|
||||||
|
@input="update($event, sanitise)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #help>
|
||||||
|
<slot name="help" />
|
||||||
|
</template>
|
||||||
|
</control-setting>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ControlSetting from '@/components/ControlSetting.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ControlSettingIntegerField',
|
||||||
|
components: { ControlSetting },
|
||||||
|
props: {
|
||||||
|
category: { required: true, type: String },
|
||||||
|
disabled: Boolean,
|
||||||
|
name: { required: true, type: String },
|
||||||
|
placeholder: { default: '', type: String }
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
sanitise(target) {
|
||||||
|
const value = parseInt(target.value.replace(/\D+/gu, ''), 10) || 0
|
||||||
|
return (target.value = value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
39
web-src/src/components/ControlSettingSwitch.vue
Normal file
39
web-src/src/components/ControlSettingSwitch.vue
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<template>
|
||||||
|
<control-setting :category="category" :disabled="disabled" :name="name">
|
||||||
|
<template #input="{ setting, update }">
|
||||||
|
<control-switch
|
||||||
|
:model-value="setting.value"
|
||||||
|
@update:model-value="
|
||||||
|
(value) => update({ target: { checked: value } }, sanitise)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<slot name="label" />
|
||||||
|
</template>
|
||||||
|
<template #help>
|
||||||
|
<slot name="help" />
|
||||||
|
</template>
|
||||||
|
</control-switch>
|
||||||
|
</template>
|
||||||
|
</control-setting>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ControlSetting from '@/components/ControlSetting.vue'
|
||||||
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ControlSettingSwitch',
|
||||||
|
components: { ControlSetting, ControlSwitch },
|
||||||
|
props: {
|
||||||
|
category: { required: true, type: String },
|
||||||
|
disabled: { default: false, type: Boolean },
|
||||||
|
name: { required: true, type: String }
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
sanitise(target) {
|
||||||
|
return target.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
44
web-src/src/components/ControlSettingTextField.vue
Normal file
44
web-src/src/components/ControlSettingTextField.vue
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<control-setting
|
||||||
|
:category="category"
|
||||||
|
:disabled="disabled"
|
||||||
|
:name="name"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<slot name="label" />
|
||||||
|
</template>
|
||||||
|
<template #input="{ setting, update }">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
inputmode="text"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:value="setting.value"
|
||||||
|
@input="update($event, sanitise)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #help>
|
||||||
|
<slot name="help" />
|
||||||
|
</template>
|
||||||
|
</control-setting>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ControlSetting from '@/components/ControlSetting.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ControlSettingTextField',
|
||||||
|
components: { ControlSetting },
|
||||||
|
props: {
|
||||||
|
category: { required: true, type: String },
|
||||||
|
disabled: Boolean,
|
||||||
|
name: { required: true, type: String },
|
||||||
|
placeholder: { default: '', type: String }
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
sanitise(target) {
|
||||||
|
return target.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -32,3 +32,112 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@use 'bulma/sass/utilities/mixins';
|
||||||
|
|
||||||
|
@mixin thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: var(--th);
|
||||||
|
height: var(--th);
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--bulma-light);
|
||||||
|
border: 1px solid var(--bulma-grey-lighter);
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
background: var(--bulma-grey-lighter);
|
||||||
|
border: 1px solid var(--bulma-grey-dark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin thumb-inactive {
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: var(--bulma-light);
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
background-color: var(--bulma-grey-dark);
|
||||||
|
border: 1px solid var(--bulma-grey-darker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin track {
|
||||||
|
height: calc(var(--sh));
|
||||||
|
border-radius: calc(var(--sh) / 2);
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--bulma-dark) var(--sx),
|
||||||
|
var(--bulma-grey-lighter) var(--sx)
|
||||||
|
);
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--bulma-grey-lighter) var(--sx),
|
||||||
|
var(--bulma-grey-dark) var(--sx)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin track-inactive {
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--bulma-grey-light) var(--sx),
|
||||||
|
var(--bulma-light) var(--sx)
|
||||||
|
);
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--bulma-grey-dark) var(--sx),
|
||||||
|
var(--bulma-black-ter) var(--sx)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='range'].slider {
|
||||||
|
--sh: 0.25rem;
|
||||||
|
--th: calc(var(--sh) * 4);
|
||||||
|
background-color: transparent;
|
||||||
|
@include mixins.mobile {
|
||||||
|
--th: calc(var(--sh) * 5);
|
||||||
|
}
|
||||||
|
& {
|
||||||
|
--sx: calc(var(--th) / 2 + (var(--ratio) * (100% - var(--th))));
|
||||||
|
-webkit-appearance: none;
|
||||||
|
min-width: 250px;
|
||||||
|
height: calc(var(--sh) * 5);
|
||||||
|
width: 100% !important;
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
&::-webkit-slider-thumb {
|
||||||
|
@include thumb;
|
||||||
|
& {
|
||||||
|
margin-top: calc((var(--th) - var(--sh)) / -2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&::-moz-range-thumb {
|
||||||
|
@include thumb;
|
||||||
|
}
|
||||||
|
&::-webkit-slider-runnable-track {
|
||||||
|
@include track;
|
||||||
|
}
|
||||||
|
&::-moz-range-track {
|
||||||
|
@include track;
|
||||||
|
}
|
||||||
|
&.is-inactive {
|
||||||
|
cursor: var(--cursor, not-allowed);
|
||||||
|
&::-webkit-slider-thumb {
|
||||||
|
@include thumb-inactive;
|
||||||
|
}
|
||||||
|
&::-webkit-slider-runnable-track {
|
||||||
|
@include track-inactive;
|
||||||
|
}
|
||||||
|
&::-moz-range-thumb {
|
||||||
|
@include thumb-inactive;
|
||||||
|
}
|
||||||
|
&::-moz-range-track {
|
||||||
|
@include track-inactive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
107
web-src/src/components/ControlStreamVolume.vue
Normal file
107
web-src/src/components/ControlStreamVolume.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<template>
|
||||||
|
<div class="media is-align-items-center mb-0">
|
||||||
|
<div class="media-left">
|
||||||
|
<a
|
||||||
|
class="button is-small"
|
||||||
|
:class="{
|
||||||
|
'has-text-grey-light': !playing && !loading,
|
||||||
|
'is-loading': loading
|
||||||
|
}"
|
||||||
|
@click="togglePlay"
|
||||||
|
>
|
||||||
|
<mdicon class="icon" name="broadcast" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="media-content is-align-items-center">
|
||||||
|
<div class="is-flex" :class="{ 'has-text-grey-light': !playing }">
|
||||||
|
<div class="is-size-7 is-uppercase" v-text="$t('navigation.stream')" />
|
||||||
|
<a href="stream.mp3" class="ml-2" target="_blank">
|
||||||
|
<mdicon class="icon is-small" name="open-in-new" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<control-slider
|
||||||
|
v-model:value="volume"
|
||||||
|
:cursor="cursor"
|
||||||
|
:disabled="!playing"
|
||||||
|
:max="100"
|
||||||
|
@change="changeVolume"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ControlSlider from '@/components/ControlSlider.vue'
|
||||||
|
import audio from '@/lib/Audio'
|
||||||
|
import { mdiCancel } from '@mdi/js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ControlStreamVolume',
|
||||||
|
components: { ControlSlider },
|
||||||
|
emits: ['change', 'mute'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cursor: mdiCancel,
|
||||||
|
loading: false,
|
||||||
|
playing: false,
|
||||||
|
volume: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setupAudio()
|
||||||
|
},
|
||||||
|
unmounted() {
|
||||||
|
this.closeAudio()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
changeVolume() {
|
||||||
|
audio.setVolume(this.volume / 100)
|
||||||
|
},
|
||||||
|
closeAudio() {
|
||||||
|
audio.stop()
|
||||||
|
this.playing = false
|
||||||
|
},
|
||||||
|
playChannel() {
|
||||||
|
if (this.playing) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
audio.play('/stream.mp3')
|
||||||
|
audio.setVolume(this.volume / 100)
|
||||||
|
},
|
||||||
|
setupAudio() {
|
||||||
|
const a = audio.setup()
|
||||||
|
a.addEventListener('waiting', () => {
|
||||||
|
this.playing = false
|
||||||
|
this.loading = true
|
||||||
|
})
|
||||||
|
a.addEventListener('playing', () => {
|
||||||
|
this.playing = true
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
a.addEventListener('ended', () => {
|
||||||
|
this.playing = false
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
a.addEventListener('error', () => {
|
||||||
|
this.closeAudio()
|
||||||
|
this.notificationsStore.add({
|
||||||
|
text: this.$t('navigation.stream-error'),
|
||||||
|
type: 'danger'
|
||||||
|
})
|
||||||
|
this.playing = false
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
togglePlay() {
|
||||||
|
if (this.loading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.playing) {
|
||||||
|
this.closeAudio()
|
||||||
|
}
|
||||||
|
this.playChannel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
78
web-src/src/components/ControlSwitch.vue
Normal file
78
web-src/src/components/ControlSwitch.vue
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<template>
|
||||||
|
<div class="field">
|
||||||
|
<label class="toggle">
|
||||||
|
<div class="control is-flex is-align-content-center">
|
||||||
|
<input
|
||||||
|
:checked="modelValue"
|
||||||
|
type="checkbox"
|
||||||
|
class="toggle-checkbox"
|
||||||
|
@change="$emit('update:modelValue', !modelValue)"
|
||||||
|
/>
|
||||||
|
<div class="toggle-switch" />
|
||||||
|
<slot name="label" />
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<div v-if="$slots.help" class="help">
|
||||||
|
<slot name="help" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ControlSwitch',
|
||||||
|
props: {
|
||||||
|
modelValue: Boolean
|
||||||
|
},
|
||||||
|
emits: ['update:modelValue']
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.toggle {
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
&-switch {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--bulma-grey-lighter);
|
||||||
|
border-radius: 1rem;
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
transition: background 0.25s;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
background: var(--bulma-white);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
position: absolute;
|
||||||
|
top: 0.125rem;
|
||||||
|
left: 0.125rem;
|
||||||
|
transition: left 0.25s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover &-switch:before {
|
||||||
|
background: var(--bulma-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-checkbox {
|
||||||
|
position: absolute;
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
&:checked + .toggle-switch {
|
||||||
|
background: var(--bulma-dark);
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
left: 1.375rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<section>
|
<section>
|
||||||
<nav class="buttons is-centered mb-4 fd-is-square">
|
<nav class="buttons is-centered mb-4">
|
||||||
<router-link
|
<router-link
|
||||||
v-for="index in indices"
|
v-for="index in indices"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="button is-small"
|
class="button is-small is-square"
|
||||||
:to="{ hash: `#index_${index}`, query: $route.query }"
|
:to="{ hash: `#index_${index}`, query: $route.query }"
|
||||||
>
|
>
|
||||||
{{ index }}
|
{{ index }}
|
||||||
@ -20,4 +20,11 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style scoped>
|
||||||
|
.is-square {
|
||||||
|
height: 1.75rem;
|
||||||
|
min-width: 1.75rem;
|
||||||
|
padding-left: 0.25rem;
|
||||||
|
padding-right: 0.25rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,37 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.itemId">
|
<template v-for="item in items" :key="item.itemId">
|
||||||
<div v-if="!item.isItem" class="mt-6 mb-5 py-2">
|
<div v-if="!item.isItem" class="py-5">
|
||||||
<span
|
<span
|
||||||
:id="`index_${item.index}`"
|
:id="`index_${item.index}`"
|
||||||
class="tag is-info is-light is-small has-text-weight-bold"
|
class="tag is-small has-text-weight-bold"
|
||||||
v-text="item.index"
|
v-text="item.index"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="media is-align-items-center" @click="open(item.item)">
|
<div
|
||||||
<div
|
v-else
|
||||||
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
|
@click="open(item.item)"
|
||||||
|
>
|
||||||
|
<cover-artwork
|
||||||
v-if="settingsStore.show_cover_artwork_in_album_lists"
|
v-if="settingsStore.show_cover_artwork_in_album_lists"
|
||||||
class="media-left"
|
:url="item.item.artwork_url"
|
||||||
>
|
:artist="item.item.artist"
|
||||||
<cover-artwork
|
:album="item.item.name"
|
||||||
:url="item.item.artwork_url"
|
class="media-left fd-has-shadow fd-cover fd-cover-small-image"
|
||||||
:artist="item.item.artist"
|
/>
|
||||||
:album="item.item.name"
|
<div class="media-content">
|
||||||
class="is-clickable fd-has-shadow fd-cover fd-cover-small-image"
|
<div class="is-size-6 has-text-weight-bold" v-text="item.item.name" />
|
||||||
|
<div
|
||||||
|
class="is-size-7 has-text-grey has-text-weight-bold"
|
||||||
|
v-text="item.item.artist"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="item.item.date_released && item.item.media_kind === 'music'"
|
||||||
|
class="is-size-7 has-text-grey"
|
||||||
|
v-text="$filters.date(item.item.date_released)"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div class="media-content is-clickable is-clipped">
|
|
||||||
<div>
|
|
||||||
<h1 class="title is-6" v-text="item.item.name" />
|
|
||||||
<h2
|
|
||||||
class="subtitle is-7 has-text-grey has-text-weight-bold"
|
|
||||||
v-text="item.item.artist"
|
|
||||||
/>
|
|
||||||
<h2
|
|
||||||
v-if="item.item.date_released && item.item.media_kind === 'music'"
|
|
||||||
class="subtitle is-7 has-text-grey"
|
|
||||||
v-text="$filters.date(item.item.date_released)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
<a @click.prevent.stop="open_dialog(item.item)">
|
<a @click.prevent.stop="open_dialog(item.item)">
|
||||||
@ -49,7 +47,7 @@
|
|||||||
@remove-podcast="open_remove_podcast_dialog()"
|
@remove-podcast="open_remove_podcast_dialog()"
|
||||||
@play-count-changed="play_count_changed()"
|
@play-count-changed="play_count_changed()"
|
||||||
/>
|
/>
|
||||||
<modal-dialog
|
<modal-dialog-action
|
||||||
:close_action="$t('page.podcast.cancel')"
|
:close_action="$t('page.podcast.cancel')"
|
||||||
:delete_action="$t('page.podcast.remove')"
|
:delete_action="$t('page.podcast.remove')"
|
||||||
:show="show_remove_podcast_modal"
|
:show="show_remove_podcast_modal"
|
||||||
@ -64,20 +62,20 @@
|
|||||||
<b v-text="rss_playlist_to_remove.name" />)
|
<b v-text="rss_playlist_to_remove.name" />)
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</modal-dialog>
|
</modal-dialog-action>
|
||||||
</teleport>
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CoverArtwork from '@/components/CoverArtwork.vue'
|
import CoverArtwork from '@/components/CoverArtwork.vue'
|
||||||
import ModalDialog from '@/components/ModalDialog.vue'
|
import ModalDialogAction from '@/components/ModalDialogAction.vue'
|
||||||
import ModalDialogAlbum from '@/components/ModalDialogAlbum.vue'
|
import ModalDialogAlbum from '@/components/ModalDialogAlbum.vue'
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
import { useSettingsStore } from '@/stores/settings'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ListAlbums',
|
name: 'ListAlbums',
|
||||||
components: { CoverArtwork, ModalDialog, ModalDialogAlbum },
|
components: { CoverArtwork, ModalDialogAction, ModalDialogAlbum },
|
||||||
props: {
|
props: {
|
||||||
items: { required: true, type: Object },
|
items: { required: true, type: Object },
|
||||||
media_kind: { default: '', type: String }
|
media_kind: { default: '', type: String }
|
||||||
@ -148,5 +146,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,28 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.id">
|
<template v-for="item in items" :key="item.id">
|
||||||
<div class="media is-align-items-center" @click="open(item)">
|
<div
|
||||||
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
|
@click="open(item)"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-if="settingsStore.show_cover_artwork_in_album_lists"
|
v-if="settingsStore.show_cover_artwork_in_album_lists"
|
||||||
class="media-left is-clickable"
|
class="media-left"
|
||||||
>
|
>
|
||||||
<cover-artwork
|
<cover-artwork
|
||||||
:url="artwork_url(item)"
|
:url="artwork_url(item)"
|
||||||
:artist="item.artist"
|
:artist="item.artist"
|
||||||
:album="item.name"
|
:album="item.name"
|
||||||
class="is-clickable fd-has-shadow fd-cover fd-cover-small-image"
|
class="fd-has-shadow fd-cover fd-cover-small-image"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-content is-clickable is-clipped">
|
<div class="media-content">
|
||||||
<h1 class="title is-6" v-text="item.name" />
|
<div class="is-size-6 has-text-weight-bold" v-text="item.name" />
|
||||||
<h2
|
<div
|
||||||
class="subtitle is-7 has-text-grey has-text-weight-bold"
|
class="is-size-7 has-text-weight-bold has-text-grey"
|
||||||
v-text="item.artists[0]?.name"
|
v-text="item.artists[0]?.name"
|
||||||
/>
|
/>
|
||||||
<h2
|
<div
|
||||||
class="subtitle is-7 has-text-grey"
|
class="is-size-7 has-text-grey"
|
||||||
v-text="
|
v-text="$filters.date(item.release_date)"
|
||||||
[item.album_type, $filters.date(item.release_date)].join(', ')
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
@ -76,5 +77,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.itemId">
|
<template v-for="item in items" :key="item.itemId">
|
||||||
<div v-if="!item.isItem" class="mt-6 mb-5 py-2">
|
<div v-if="!item.isItem" class="py-5">
|
||||||
<div class="media-content is-clipped">
|
<div class="media-content">
|
||||||
<span
|
<span
|
||||||
:id="`index_${item.index}`"
|
:id="`index_${item.index}`"
|
||||||
class="tag is-info is-light is-small has-text-weight-bold"
|
class="tag is-small has-text-weight-bold"
|
||||||
v-text="item.index"
|
v-text="item.index"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="media is-align-items-center" @click="open(item.item)">
|
<div
|
||||||
<div class="media-content is-clickable is-clipped">
|
v-else
|
||||||
<h1 class="title is-6" v-text="item.item.name" />
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
|
@click="open(item.item)"
|
||||||
|
>
|
||||||
|
<div class="media-content">
|
||||||
|
<p class="title is-6" v-text="item.item.name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
<a @click.prevent.stop="open_dialog(item.item)">
|
<a @click.prevent.stop="open_dialog(item.item)">
|
||||||
@ -60,5 +64,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.id">
|
<template v-for="item in items" :key="item.id">
|
||||||
<div class="media is-align-items-center">
|
<div class="media is-align-items-center mb-0">
|
||||||
<div class="media-content is-clickable is-clipped" @click="open(item)">
|
<div class="media-content is-clickable" @click="open(item)">
|
||||||
<h1 class="title is-6" v-text="item.name" />
|
<p class="title is-6" v-text="item.name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
<a @click.prevent.stop="open_dialog(item)">
|
<a @click.prevent.stop="open_dialog(item)">
|
||||||
@ -45,5 +45,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.itemId">
|
<template v-for="item in items" :key="item.itemId">
|
||||||
<div v-if="!item.isItem" class="mt-6 mb-5 py-2">
|
<div v-if="!item.isItem" class="py-5">
|
||||||
<div class="media-content is-clipped">
|
<div class="media-content">
|
||||||
<span
|
<span
|
||||||
:id="`index_${item.index}`"
|
:id="`index_${item.index}`"
|
||||||
class="tag is-info is-light is-small has-text-weight-bold"
|
class="tag is-small has-text-weight-bold"
|
||||||
v-text="item.index"
|
v-text="item.index"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="media is-align-items-center" @click="open(item.item)">
|
<div
|
||||||
<div class="media-content is-clickable is-clipped">
|
v-else
|
||||||
<h1 class="title is-6" v-text="item.item.name" />
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
|
@click="open(item.item)"
|
||||||
|
>
|
||||||
|
<div class="media-content">
|
||||||
|
<p class="title is-6" v-text="item.item.name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
<a @click.prevent.stop="open_dialog(item.item)">
|
<a @click.prevent.stop="open_dialog(item.item)">
|
||||||
@ -62,5 +66,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="$route.query.directory" class="media is-align-items-center">
|
<div v-if="$route.query.directory" class="media is-align-items-center mb-0">
|
||||||
<figure class="media-left is-clickable" @click="open_parent">
|
<mdicon
|
||||||
<mdicon class="icon" name="chevron-left" size="16" />
|
class="icon media-left is-clickable"
|
||||||
</figure>
|
name="chevron-left"
|
||||||
<div class="media-content is-clipped">
|
@click="open_parent"
|
||||||
|
/>
|
||||||
|
<div class="media-content">
|
||||||
<nav class="breadcrumb">
|
<nav class="breadcrumb">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="directory in directories" :key="directory.index">
|
<li v-for="directory in directories" :key="directory.index">
|
||||||
@ -19,12 +21,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-for="item in items" :key="item.path">
|
<template v-for="item in items" :key="item.path">
|
||||||
<div class="media is-align-items-center" @click="open(item)">
|
<div
|
||||||
<figure class="media-left is-clickable">
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
<mdicon class="icon" name="folder" size="16" />
|
@click="open(item)"
|
||||||
</figure>
|
>
|
||||||
<div class="media-content is-clickable is-clipped">
|
<mdicon class="media-left icon" name="folder" />
|
||||||
<h1 class="title is-6" v-text="item.name" />
|
<div class="media-content">
|
||||||
|
<p class="title is-6" v-text="item.name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
<a @click.prevent.stop="open_dialog(item)">
|
<a @click.prevent.stop="open_dialog(item)">
|
||||||
@ -90,5 +93,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.itemId">
|
<template v-for="item in items" :key="item.itemId">
|
||||||
<div v-if="!item.isItem" class="mt-6 mb-5 py-2">
|
<div v-if="!item.isItem" class="py-5">
|
||||||
<div class="media-content is-clipped">
|
<div class="media-content">
|
||||||
<span
|
<span
|
||||||
:id="`index_${item.index}`"
|
:id="`index_${item.index}`"
|
||||||
class="tag is-info is-light is-small has-text-weight-bold"
|
class="tag is-small has-text-weight-bold"
|
||||||
v-text="item.index"
|
v-text="item.index"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="media is-align-items-center" @click="open(item.item)">
|
<div
|
||||||
<div class="media-content is-clickable is-clipped">
|
v-else
|
||||||
<h1 class="title is-6" v-text="item.item.name" />
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
|
@click="open(item.item)"
|
||||||
|
>
|
||||||
|
<div class="media-content">
|
||||||
|
<p class="title is-6" v-text="item.item.name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
<a @click.prevent.stop="open_dialog(item.item)">
|
<a @click.prevent.stop="open_dialog(item.item)">
|
||||||
@ -63,5 +67,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,26 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="is_next || !show_only_next_items"
|
v-if="is_next || !show_only_next_items"
|
||||||
class="media is-align-items-center"
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
|
@click="play"
|
||||||
>
|
>
|
||||||
<div v-if="edit_mode" class="media-left">
|
<div v-if="edit_mode" class="media-left">
|
||||||
<mdicon
|
<mdicon
|
||||||
class="icon has-text-grey fd-is-movable handle"
|
class="icon has-text-grey is-movable"
|
||||||
name="drag-horizontal"
|
name="drag-horizontal"
|
||||||
size="16"
|
size="18"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-content is-clickable is-clipped" @click="play">
|
<div class="media-content">
|
||||||
<h1
|
<div
|
||||||
class="title is-6"
|
class="is-size-6 has-text-weight-bold"
|
||||||
:class="{
|
:class="{
|
||||||
'has-text-primary': item.id === player.item_id,
|
'has-text-primary': item.id === player.item_id,
|
||||||
'has-text-grey-light': !is_next
|
'has-text-grey-light': !is_next
|
||||||
}"
|
}"
|
||||||
v-text="item.title"
|
v-text="item.title"
|
||||||
/>
|
/>
|
||||||
<h2
|
<div
|
||||||
class="subtitle is-7 has-text-weight-bold"
|
class="is-size-7 has-text-weight-bold"
|
||||||
:class="{
|
:class="{
|
||||||
'has-text-primary': item.id === player.item_id,
|
'has-text-primary': item.id === player.item_id,
|
||||||
'has-text-grey-light': !is_next,
|
'has-text-grey-light': !is_next,
|
||||||
@ -28,8 +29,8 @@
|
|||||||
}"
|
}"
|
||||||
v-text="item.artist"
|
v-text="item.artist"
|
||||||
/>
|
/>
|
||||||
<h2
|
<div
|
||||||
class="subtitle is-7"
|
class="is-size-7"
|
||||||
:class="{
|
:class="{
|
||||||
'has-text-primary': item.id === player.item_id,
|
'has-text-primary': item.id === player.item_id,
|
||||||
'has-text-grey-light': !is_next,
|
'has-text-grey-light': !is_next,
|
||||||
@ -81,4 +82,8 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style scoped>
|
||||||
|
.is-movable {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.itemId">
|
<template v-for="item in items" :key="item.itemId">
|
||||||
<div class="media is-align-items-center" @click="open(item.item)">
|
<div
|
||||||
<figure class="media-left is-clickable">
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
<mdicon class="icon" :name="icon_name(item.item)" size="16" />
|
@click="open(item.item)"
|
||||||
</figure>
|
>
|
||||||
<div class="media-content is-clickable is-clipped">
|
<mdicon class="media-left icon" :name="icon(item.item)" />
|
||||||
<h1 class="title is-6" v-text="item.item.name" />
|
<div class="media-content">
|
||||||
|
<p class="title is-6" v-text="item.item.name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
<a @click.prevent.stop="open_dialog(item.item)">
|
<a @click.prevent.stop="open_dialog(item.item)">
|
||||||
@ -39,7 +40,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
icon_name(item) {
|
icon(item) {
|
||||||
if (item.type === 'folder') {
|
if (item.type === 'folder') {
|
||||||
return 'folder'
|
return 'folder'
|
||||||
} else if (item.type === 'rss') {
|
} else if (item.type === 'rss') {
|
||||||
@ -61,5 +62,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.id">
|
<template v-for="item in items" :key="item.id">
|
||||||
<div class="media is-align-items-center">
|
<div
|
||||||
<div class="media-content is-clickable is-clipped" @click="open(item)">
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
<h1 class="title is-6" v-text="item.name" />
|
@click="open(item)"
|
||||||
<h2 class="subtitle is-7" v-text="item.owner.display_name" />
|
>
|
||||||
|
<div class="media-content">
|
||||||
|
<div class="is-size-6 has-text-weight-bold" v-text="item.name" />
|
||||||
|
<div
|
||||||
|
class="is-size-7 has-text-weight-bold has-text-grey"
|
||||||
|
v-text="item.owner.display_name"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
<a @click.prevent.stop="open_dialog(item)">
|
<a @click.prevent.stop="open_dialog(item)">
|
||||||
@ -46,5 +52,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,35 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.itemId">
|
<template v-for="item in items" :key="item.itemId">
|
||||||
<div v-if="!item.isItem" class="mt-6 mb-5 py-2">
|
<div v-if="!item.isItem" class="py-5">
|
||||||
<span
|
<span
|
||||||
:id="`index_${item.index}`"
|
:id="`index_${item.index}`"
|
||||||
class="tag is-info is-light is-small has-text-weight-bold"
|
class="tag is-small has-text-weight-bold"
|
||||||
v-text="item.index"
|
v-text="item.index"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="media is-align-items-center"
|
class="media is-align-items-center is-clickable mb-0"
|
||||||
:class="{ 'with-progress': show_progress }"
|
:class="{ 'with-progress': show_progress }"
|
||||||
@click="play(item.item)"
|
@click="play(item.item)"
|
||||||
>
|
>
|
||||||
<figure v-if="show_icon" class="media-left is-clickable">
|
<mdicon v-if="show_icon" class="media-left icon" name="file-outline" />
|
||||||
<mdicon class="icon" name="file-outline" size="16" />
|
<div class="media-content">
|
||||||
</figure>
|
<div
|
||||||
<div class="media-content is-clickable is-clipped">
|
class="is-size-6 has-text-weight-bold"
|
||||||
<h1
|
|
||||||
class="title is-6"
|
|
||||||
:class="{
|
:class="{
|
||||||
'has-text-grey':
|
'has-text-grey':
|
||||||
item.item.media_kind === 'podcast' && item.item.play_count > 0
|
item.item.media_kind === 'podcast' && item.item.play_count > 0
|
||||||
}"
|
}"
|
||||||
v-text="item.item.title"
|
v-text="item.item.title"
|
||||||
/>
|
/>
|
||||||
<h2
|
<div
|
||||||
class="subtitle is-7 has-text-grey has-text-weight-bold"
|
class="is-size-7 has-text-weight-bold has-text-grey"
|
||||||
v-text="item.item.artist"
|
v-text="item.item.artist"
|
||||||
/>
|
/>
|
||||||
<h2 class="subtitle is-7 has-text-grey" v-text="item.item.album" />
|
<div class="is-size-7 has-text-grey" v-text="item.item.album" />
|
||||||
<progress
|
<progress
|
||||||
v-if="show_progress && item.item.seek_ms > 0"
|
v-if="show_progress && item.item.seek_ms > 0"
|
||||||
class="progress is-info"
|
class="progress is-info"
|
||||||
@ -103,4 +101,8 @@ export default {
|
|||||||
.progress {
|
.progress {
|
||||||
height: 0.25rem;
|
height: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.media.with-progress {
|
||||||
|
margin-top: 0.375rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-for="item in items" :key="item.id">
|
<template v-for="item in items" :key="item.id">
|
||||||
<div class="media is-align-items-center">
|
<div class="media is-align-items-center mb-0">
|
||||||
<div
|
<div
|
||||||
class="media-content is-clipped"
|
class="media-content"
|
||||||
:class="{
|
:class="{
|
||||||
'is-clickable': item.is_playable,
|
'is-clickable': item.is_playable,
|
||||||
'fd-is-not-allowed': !item.is_playable
|
'is-not-allowed': !item.is_playable
|
||||||
}"
|
}"
|
||||||
@click="play(item)"
|
@click="play(item)"
|
||||||
>
|
>
|
||||||
<h1
|
<div
|
||||||
class="title is-6"
|
class="is-size-6 has-text-weight-bold"
|
||||||
:class="{ 'has-text-grey-light': !item.is_playable }"
|
:class="{ 'has-text-grey-light': !item.is_playable }"
|
||||||
v-text="item.name"
|
v-text="item.name"
|
||||||
/>
|
/>
|
||||||
<h2
|
<div
|
||||||
class="subtitle is-7 has-text-weight-bold"
|
class="is-size-7 has-text-weight-bold"
|
||||||
:class="{
|
:class="{
|
||||||
'has-text-grey': item.is_playable,
|
'has-text-grey': item.is_playable,
|
||||||
'has-text-grey-light': !item.is_playable
|
'has-text-grey-light': !item.is_playable
|
||||||
}"
|
}"
|
||||||
v-text="item.artists[0].name"
|
v-text="item.artists[0].name"
|
||||||
/>
|
/>
|
||||||
<h2 class="subtitle is-7 has-text-grey" v-text="item.album.name" />
|
<div class="is-size-7 has-text-grey" v-text="item.album.name" />
|
||||||
<h2 v-if="!item.is_playable" class="subtitle is-7">
|
<div v-if="!item.is_playable" class="is-size-7 has-text-grey">
|
||||||
(<span v-text="$t('list.spotify.not-playable-track')" />
|
(<span v-text="$t('list.spotify.not-playable-track')" />
|
||||||
<span
|
<span
|
||||||
v-if="item.restrictions?.reason"
|
v-if="item.restrictions?.reason"
|
||||||
@ -33,7 +33,7 @@
|
|||||||
})
|
})
|
||||||
"
|
"
|
||||||
/>)
|
/>)
|
||||||
</h2>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right">
|
||||||
<a @click.prevent.stop="open_dialog(item)">
|
<a @click.prevent.stop="open_dialog(item)">
|
||||||
@ -83,4 +83,8 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style scoped>
|
||||||
|
.is-not-allowed {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -223,4 +223,14 @@ export default {
|
|||||||
.lyrics div:last-child {
|
.lyrics div:last-child {
|
||||||
padding-bottom: calc(25vh - 3rem);
|
padding-bottom: calc(25vh - 3rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Lyrics animation */
|
||||||
|
@keyframes pop-color {
|
||||||
|
0% {
|
||||||
|
color: var(--bulma-black);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
color: var(--bulma-success);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -5,38 +5,13 @@
|
|||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<p v-if="title" class="title is-4" v-text="title" />
|
<slot name="content" />
|
||||||
<slot name="modal-content" />
|
|
||||||
</div>
|
</div>
|
||||||
<footer class="card-footer is-clipped">
|
<footer class="card-footer is-clipped">
|
||||||
<a class="card-footer-item has-text-dark" @click="$emit('close')">
|
<slot name="footer" />
|
||||||
<mdicon class="icon" name="cancel" size="16" />
|
|
||||||
<span class="is-size-7" v-text="close_action" />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
v-if="delete_action"
|
|
||||||
class="card-footer-item has-background-danger has-text-white has-text-weight-bold"
|
|
||||||
@click="$emit('delete')"
|
|
||||||
>
|
|
||||||
<mdicon class="icon" name="delete" size="16" />
|
|
||||||
<span class="is-size-7" v-text="delete_action" />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
v-if="ok_action"
|
|
||||||
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
|
|
||||||
@click="$emit('ok')"
|
|
||||||
>
|
|
||||||
<mdicon class="icon" name="check" size="16" />
|
|
||||||
<span class="is-size-7" v-text="ok_action" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
|
||||||
class="modal-close is-large"
|
|
||||||
aria-label="close"
|
|
||||||
@click="$emit('close')"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
@ -45,14 +20,35 @@
|
|||||||
export default {
|
export default {
|
||||||
name: 'ModalDialog',
|
name: 'ModalDialog',
|
||||||
props: {
|
props: {
|
||||||
close_action: { default: '', type: String },
|
show: Boolean
|
||||||
delete_action: { default: '', type: String },
|
|
||||||
ok_action: { default: '', type: String },
|
|
||||||
show: Boolean,
|
|
||||||
title: { required: true, type: String }
|
|
||||||
},
|
},
|
||||||
emits: ['delete', 'close', 'ok']
|
emits: ['close'],
|
||||||
|
watch: {
|
||||||
|
show(value) {
|
||||||
|
const { classList } = document.querySelector('html')
|
||||||
|
if (value) {
|
||||||
|
classList.add('is-clipped')
|
||||||
|
} else {
|
||||||
|
classList.remove('is-clipped')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style scoped>
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
.fade-enter-active {
|
||||||
|
transition: opacity 0.5s ease;
|
||||||
|
}
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.fade-enter-to,
|
||||||
|
.fade-leave-from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
53
web-src/src/components/ModalDialogAction.vue
Normal file
53
web-src/src/components/ModalDialogAction.vue
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<template>
|
||||||
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
|
<template #content>
|
||||||
|
<p v-if="title" class="title is-4" v-text="title" />
|
||||||
|
<slot name="modal-content" />
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="$emit('close')">
|
||||||
|
<mdicon class="icon" name="cancel" size="16" />
|
||||||
|
<span class="is-size-7" v-text="close_action" />
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
v-if="delete_action"
|
||||||
|
class="card-footer-item has-background-danger"
|
||||||
|
@click="$emit('delete')"
|
||||||
|
>
|
||||||
|
<mdicon class="icon" name="delete" size="16" />
|
||||||
|
<span class="is-size-7" v-text="delete_action" />
|
||||||
|
</a>
|
||||||
|
<a v-if="ok_action" class="card-footer-item" @click="$emit('ok')">
|
||||||
|
<mdicon class="icon" name="check" size="16" />
|
||||||
|
<span class="is-size-7" v-text="ok_action" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ModalDialogAction',
|
||||||
|
components: { ModalDialog },
|
||||||
|
props: {
|
||||||
|
close_action: { default: '', type: String },
|
||||||
|
delete_action: { default: '', type: String },
|
||||||
|
ok_action: { default: '', type: String },
|
||||||
|
show: Boolean,
|
||||||
|
title: { required: true, type: String }
|
||||||
|
},
|
||||||
|
emits: ['delete', 'close', 'ok'],
|
||||||
|
watch: {
|
||||||
|
show() {
|
||||||
|
const { classList } = document.querySelector('html')
|
||||||
|
if (this.show) {
|
||||||
|
classList.add('is-clipped')
|
||||||
|
} else {
|
||||||
|
classList.remove('is-clipped')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -1,68 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<p class="title is-4" v-text="$t('dialog.add.rss.title')" />
|
||||||
<div class="modal-content">
|
<div class="field">
|
||||||
<form class="card" @submit.prevent="add_stream">
|
<p class="control has-icons-left">
|
||||||
<div class="card-content">
|
<input
|
||||||
<p class="title is-4" v-text="$t('dialog.add.rss.title')" />
|
ref="url_field"
|
||||||
<div class="field">
|
v-model="url"
|
||||||
<p class="control has-icons-left">
|
class="input"
|
||||||
<input
|
type="url"
|
||||||
ref="url_field"
|
pattern="http[s]?://.+"
|
||||||
v-model="url"
|
required
|
||||||
class="input is-shadowless"
|
:placeholder="$t('dialog.add.rss.placeholder')"
|
||||||
type="url"
|
:disabled="loading"
|
||||||
pattern="http[s]?://.+"
|
@input="check_url"
|
||||||
required
|
/>
|
||||||
:placeholder="$t('dialog.add.rss.placeholder')"
|
<mdicon class="icon is-left" name="rss" size="16" />
|
||||||
:disabled="loading"
|
</p>
|
||||||
@input="check_url"
|
<p class="help" v-text="$t('dialog.add.rss.help')" />
|
||||||
/>
|
|
||||||
<mdicon class="icon is-left" name="rss" size="16" />
|
|
||||||
</p>
|
|
||||||
<p class="help" v-text="$t('dialog.add.rss.help')" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer v-if="loading" class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark">
|
|
||||||
<mdicon class="icon" name="web" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.add.rss.processing')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
<footer v-else class="card-footer is-clipped">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="$emit('close')">
|
|
||||||
<mdicon class="icon" name="cancel" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.add.rss.cancel')" />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
:class="{ 'is-disabled': disabled }"
|
|
||||||
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
|
|
||||||
@click="add_stream"
|
|
||||||
>
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.add.rss.add')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
</template>
|
||||||
class="modal-close is-large"
|
<template v-if="loading" #footer>
|
||||||
aria-label="close"
|
<a class="card-footer-item has-text-dark">
|
||||||
@click="$emit('close')"
|
<mdicon class="icon" name="web" size="16" />
|
||||||
/>
|
<span class="is-size-7" v-text="$t('dialog.add.rss.processing')" />
|
||||||
</div>
|
</a>
|
||||||
</transition>
|
</template>
|
||||||
|
<template v-else #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="$emit('close')">
|
||||||
|
<mdicon class="icon" name="cancel" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.add.rss.cancel')" />
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
:class="{ 'is-disabled': disabled }"
|
||||||
|
class="card-footer-item"
|
||||||
|
@click="add_stream"
|
||||||
|
>
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.add.rss.add')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogAddRss',
|
name: 'ModalDialogAddRss',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { show: Boolean },
|
props: { show: Boolean },
|
||||||
emits: ['close', 'podcast-added'],
|
emits: ['close', 'podcast-added'],
|
||||||
|
|
||||||
@ -107,5 +94,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,75 +1,64 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<form @submit.prevent="play">
|
||||||
<div class="modal-content">
|
<p class="title is-4" v-text="$t('dialog.add.stream.title')" />
|
||||||
<form class="card" @submit.prevent="play">
|
<div class="field">
|
||||||
<div class="card-content">
|
<p class="control has-icons-left">
|
||||||
<p class="title is-4" v-text="$t('dialog.add.stream.title')" />
|
<input
|
||||||
<div class="field">
|
ref="url_field"
|
||||||
<p class="control has-icons-left">
|
v-model="url"
|
||||||
<input
|
class="input"
|
||||||
ref="url_field"
|
type="url"
|
||||||
v-model="url"
|
pattern="http[s]?://.+"
|
||||||
class="input is-shadowless"
|
required
|
||||||
type="url"
|
:placeholder="$t('dialog.add.stream.placeholder')"
|
||||||
pattern="http[s]?://.+"
|
:disabled="loading"
|
||||||
required
|
@input="check_url"
|
||||||
:placeholder="$t('dialog.add.stream.placeholder')"
|
/>
|
||||||
:disabled="loading"
|
<mdicon class="icon is-left" name="web" size="16" />
|
||||||
@input="check_url"
|
</p>
|
||||||
/>
|
</div>
|
||||||
<mdicon class="icon is-left" name="web" size="16" />
|
</form>
|
||||||
</p>
|
</template>
|
||||||
</div>
|
<template v-if="loading" #footer>
|
||||||
</div>
|
<a class="card-footer-item has-text-dark">
|
||||||
<footer v-if="loading" class="card-footer">
|
<mdicon class="icon" name="web" size="16" />
|
||||||
<a class="card-footer-item has-text-dark">
|
<span class="is-size-7" v-text="$t('dialog.add.stream.loading')" />
|
||||||
<mdicon class="icon" name="web" size="16" />
|
</a>
|
||||||
<span
|
</template>
|
||||||
class="is-size-7"
|
<template v-else #footer>
|
||||||
v-text="$t('dialog.add.stream.loading')"
|
<a class="card-footer-item has-text-dark" @click="$emit('close')">
|
||||||
/>
|
<mdicon class="icon" name="cancel" size="16" />
|
||||||
</a>
|
<span class="is-size-7" v-text="$t('dialog.add.stream.cancel')" />
|
||||||
</footer>
|
</a>
|
||||||
<footer v-else class="card-footer is-clipped">
|
<a
|
||||||
<a class="card-footer-item has-text-dark" @click="$emit('close')">
|
:class="{ 'is-disabled': disabled }"
|
||||||
<mdicon class="icon" name="cancel" size="16" />
|
class="card-footer-item has-text-dark"
|
||||||
<span class="is-size-7" v-text="$t('dialog.add.stream.cancel')" />
|
@click="add_stream"
|
||||||
</a>
|
>
|
||||||
<a
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
:class="{ 'is-disabled': disabled }"
|
<span class="is-size-7" v-text="$t('dialog.add.stream.add')" />
|
||||||
class="card-footer-item has-text-dark"
|
</a>
|
||||||
@click="add_stream"
|
<a
|
||||||
>
|
:class="{ 'is-disabled': disabled }"
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
class="card-footer-item has-text-dark"
|
||||||
<span class="is-size-7" v-text="$t('dialog.add.stream.add')" />
|
@click="play"
|
||||||
</a>
|
>
|
||||||
<a
|
<mdicon class="icon" name="play" size="16" />
|
||||||
:class="{ 'is-disabled': disabled }"
|
<span class="is-size-7" v-text="$t('dialog.add.stream.play')" />
|
||||||
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
|
</a>
|
||||||
@click="play"
|
</template>
|
||||||
>
|
</modal-dialog>
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.add.stream.play')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="modal-close is-large"
|
|
||||||
aria-label="close"
|
|
||||||
@click="$emit('close')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogAddUrlStream',
|
name: 'ModalDialogAddUrlStream',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { show: Boolean },
|
props: { show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -125,5 +114,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,116 +1,107 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<div class="title is-4">
|
||||||
<div class="modal-content">
|
<a @click="open" v-text="item.name" />
|
||||||
<div class="card">
|
</div>
|
||||||
<div class="card-content">
|
<cover-artwork
|
||||||
<cover-artwork
|
:url="item.artwork_url"
|
||||||
:url="item.artwork_url"
|
:artist="item.artist"
|
||||||
:artist="item.artist"
|
:album="item.name"
|
||||||
:album="item.name"
|
class="fd-has-shadow fd-cover fd-cover-normal-image mb-3"
|
||||||
class="fd-has-shadow fd-cover fd-cover-normal-image mb-5"
|
/>
|
||||||
/>
|
<div v-if="media_kind_resolved === 'podcast'" class="buttons">
|
||||||
<p class="title is-4">
|
<a
|
||||||
<a class="has-text-link" @click="open" v-text="item.name" />
|
class="button is-small"
|
||||||
</p>
|
@click="mark_played"
|
||||||
<div v-if="media_kind_resolved === 'podcast'" class="buttons">
|
v-text="$t('dialog.album.mark-as-played')"
|
||||||
<a
|
/>
|
||||||
class="button is-small"
|
<a
|
||||||
@click="mark_played"
|
v-if="item.data_kind === 'url'"
|
||||||
v-text="$t('dialog.album.mark-as-played')"
|
class="button is-small"
|
||||||
/>
|
@click="$emit('remove-podcast')"
|
||||||
<a
|
v-text="$t('dialog.album.remove-podcast')"
|
||||||
v-if="item.data_kind === 'url'"
|
/>
|
||||||
class="button is-small"
|
</div>
|
||||||
@click="$emit('remove-podcast')"
|
<div v-if="item.artist" class="mb-3">
|
||||||
v-text="$t('dialog.album.remove-podcast')"
|
<div
|
||||||
/>
|
class="is-size-7 is-uppercase"
|
||||||
</div>
|
v-text="$t('dialog.album.artist')"
|
||||||
<div class="content is-small">
|
/>
|
||||||
<p v-if="item.artist">
|
<div class="title is-6">
|
||||||
<span class="heading" v-text="$t('dialog.album.artist')" />
|
<a @click="open_artist" v-text="item.artist" />
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_artist"
|
|
||||||
v-text="item.artist"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.date_released">
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.album.release-date')"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.date(item.date_released)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-else-if="item.year">
|
|
||||||
<span class="heading" v-text="$t('dialog.album.year')" />
|
|
||||||
<span class="title is-6" v-text="item.year" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.album.tracks')" />
|
|
||||||
<span class="title is-6" v-text="item.track_count" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.album.duration')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.durationInHours(item.length_ms)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.album.type')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="
|
|
||||||
`${$t(`media.kind.${item.media_kind}`)} - ${$t(`data.kind.${item.data_kind}`)}`
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.album.added-on')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.datetime(item.time_added)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.album.add')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.album.add-next')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.album.play')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div v-if="item.date_released" class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.album.release-date')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div class="title is-6" v-text="$filters.date(item.date_released)" />
|
||||||
</transition>
|
</div>
|
||||||
|
<div v-else-if="item.year" class="mb-3">
|
||||||
|
<div class="is-size-7 is-uppercase" v-text="$t('dialog.album.year')" />
|
||||||
|
<div class="title is-6" v-text="item.year" />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.album.tracks')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.track_count" />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.album.duration')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="$filters.durationInHours(item.length_ms)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="is-size-7 is-uppercase" v-text="$t('dialog.album.type')" />
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="
|
||||||
|
`${$t(`media.kind.${item.media_kind}`)} - ${$t(`data.kind.${item.data_kind}`)}`
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.album.added-on')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="$filters.datetime(item.time_added)" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.album.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.album.add-next')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.album.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CoverArtwork from '@/components/CoverArtwork.vue'
|
import CoverArtwork from '@/components/CoverArtwork.vue'
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogAlbum',
|
name: 'ModalDialogAlbum',
|
||||||
components: { CoverArtwork },
|
components: { ModalDialog, CoverArtwork },
|
||||||
props: {
|
props: {
|
||||||
item: { required: true, type: Object },
|
item: { required: true, type: Object },
|
||||||
media_kind: { default: '', type: String },
|
media_kind: { default: '', type: String },
|
||||||
@ -184,5 +175,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,90 +1,66 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<div class="title is-4">
|
||||||
<div class="modal-content">
|
<a @click="open" v-text="item.name" />
|
||||||
<div class="card">
|
</div>
|
||||||
<div class="card-content">
|
<cover-artwork
|
||||||
<cover-artwork
|
:url="artwork_url(item)"
|
||||||
:url="artwork_url(item)"
|
:artist="item.artist"
|
||||||
:artist="item.artist"
|
:album="item.name"
|
||||||
:album="item.name"
|
class="fd-has-shadow fd-cover fd-cover-normal-image mb-3"
|
||||||
class="fd-has-shadow fd-cover fd-cover-normal-image mb-5"
|
@load="artwork_loaded"
|
||||||
@load="artwork_loaded"
|
@error="artwork_error"
|
||||||
@error="artwork_error"
|
/>
|
||||||
/>
|
<div class="mb-3">
|
||||||
<p class="title is-4">
|
<div
|
||||||
<a class="has-text-link" @click="open" v-text="item.name" />
|
class="is-size-7 is-uppercase"
|
||||||
</p>
|
v-text="$t('dialog.spotify.album.album-artist')"
|
||||||
<div class="content is-small">
|
/>
|
||||||
<p>
|
<div class="title is-6">
|
||||||
<span
|
<a @click="open_artist" v-text="item.artists[0].name" />
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.album.album-artist')"
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_artist"
|
|
||||||
v-text="item.artists[0].name"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.album.release-date')"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.date(item.release_date)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.album.type')"
|
|
||||||
/>
|
|
||||||
<span class="title is-6" v-text="item.album_type" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.spotify.album.add')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.album.add-next')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.album.play')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.spotify.album.release-date')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div class="title is-6" v-text="$filters.date(item.release_date)" />
|
||||||
</transition>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.spotify.album.type')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.album_type" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.album.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.album.add-next')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.album.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CoverArtwork from '@/components/CoverArtwork.vue'
|
import CoverArtwork from '@/components/CoverArtwork.vue'
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogAlbumSpotify',
|
name: 'ModalDialogAlbumSpotify',
|
||||||
components: { CoverArtwork },
|
components: { ModalDialog, CoverArtwork },
|
||||||
props: { item: { required: true, type: Object }, show: Boolean },
|
props: { item: { required: true, type: Object }, show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -133,5 +109,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,68 +1,59 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<div class="title is-4">
|
||||||
<div class="modal-content">
|
<a @click="open" v-text="item.name" />
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<p class="title is-4">
|
|
||||||
<a class="has-text-link" @click="open" v-text="item.name" />
|
|
||||||
</p>
|
|
||||||
<div class="content is-small">
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.artist.albums')" />
|
|
||||||
<span class="title is-6" v-text="item.album_count" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.artist.tracks')" />
|
|
||||||
<span class="title is-6" v-text="item.track_count" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.artist.type')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$t(`data.kind.${item.data_kind}`)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.artist.added-on')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.datetime(item.time_added)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.artist.add')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.artist.add-next')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.artist.play')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.artist.albums')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div class="title is-6" v-text="item.album_count" />
|
||||||
</transition>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.artist.tracks')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.track_count" />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="is-size-7 is-uppercase" v-text="$t('dialog.artist.type')" />
|
||||||
|
<div class="title is-6" v-text="$t(`data.kind.${item.data_kind}`)" />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.artist.added-on')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="$filters.datetime(item.time_added)" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.artist.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.artist.add-next')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.artist.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogArtist',
|
name: 'ModalDialogArtist',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { item: { required: true, type: Object }, show: Boolean },
|
props: { item: { required: true, type: Object }, show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -89,5 +80,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,72 +1,51 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<div class="title is-4">
|
||||||
<div class="modal-content">
|
<a @click="open" v-text="item.name" />
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<p class="title is-4">
|
|
||||||
<a class="has-text-link" @click="open" v-text="item.name" />
|
|
||||||
</p>
|
|
||||||
<div class="content is-small">
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.artist.popularity')"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="[item.popularity, item.followers.total].join(' / ')"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.artist.genres')"
|
|
||||||
/>
|
|
||||||
<span class="title is-6" v-text="item.genres.join(', ')" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.artist.add')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.artist.add-next')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.artist.play')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.spotify.artist.popularity')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div
|
||||||
</transition>
|
class="title is-6"
|
||||||
|
v-text="[item.popularity, item.followers.total].join(' / ')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.spotify.artist.genres')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.genres.join(', ')" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.artist.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.artist.add-next')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.artist.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogArtistSpotify',
|
name: 'ModalDialogArtistSpotify',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { item: { required: true, type: Object }, show: Boolean },
|
props: { item: { required: true, type: Object }, show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -93,5 +72,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,71 +1,62 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<div class="title is-4">
|
||||||
<div class="modal-content">
|
<a @click="open_albums" v-text="item.name" />
|
||||||
<div class="card">
|
</div>
|
||||||
<div class="card-content">
|
<div class="mb-3">
|
||||||
<p class="title is-4">
|
<div
|
||||||
<a
|
class="is-size-7 is-uppercase"
|
||||||
class="has-text-link"
|
v-text="$t('dialog.composer.albums')"
|
||||||
@click="open_albums"
|
/>
|
||||||
v-text="item.name"
|
<div class="title is-6">
|
||||||
/>
|
<a @click="open_albums" v-text="item.album_count" />
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.composer.albums')" />
|
|
||||||
<a
|
|
||||||
class="has-text-link is-6"
|
|
||||||
@click="open_albums"
|
|
||||||
v-text="item.album_count"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.composer.tracks')" />
|
|
||||||
<a
|
|
||||||
class="has-text-link is-6"
|
|
||||||
@click="open_tracks"
|
|
||||||
v-text="item.track_count"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.composer.duration')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.durationInHours(item.length_ms)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.composer.add')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.composer.add-next')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.composer.play')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.composer.tracks')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div class="title is-6">
|
||||||
</transition>
|
<a @click="open_tracks" v-text="item.track_count" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.composer.duration')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="$filters.durationInHours(item.length_ms)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.composer.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.composer.add-next')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.composer.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogComposer',
|
name: 'ModalDialogComposer',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { item: { required: true, type: Object }, show: Boolean },
|
props: { item: { required: true, type: Object }, show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -105,5 +96,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,45 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<p class="title is-4" v-text="item" />
|
||||||
<div class="modal-content">
|
</template>
|
||||||
<div class="card">
|
<template #footer>
|
||||||
<div class="card-content">
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
<p class="title is-4" v-text="item" />
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
</div>
|
<span class="is-size-7" v-text="$t('dialog.directory.add')" />
|
||||||
<footer class="card-footer">
|
</a>
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
<span class="is-size-7" v-text="$t('dialog.directory.add')" />
|
<span class="is-size-7" v-text="$t('dialog.directory.add-next')" />
|
||||||
</a>
|
</a>
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
<mdicon class="icon" name="play" size="16" />
|
||||||
<span
|
<span class="is-size-7" v-text="$t('dialog.directory.play')" />
|
||||||
class="is-size-7"
|
</a>
|
||||||
v-text="$t('dialog.directory.add-next')"
|
</template>
|
||||||
/>
|
</modal-dialog>
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.directory.play')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="modal-close is-large"
|
|
||||||
aria-label="close"
|
|
||||||
@click="$emit('close')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogDirectory',
|
name: 'ModalDialogDirectory',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { item: { required: true, type: String }, show: Boolean },
|
props: { item: { required: true, type: String }, show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -66,5 +53,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,61 +1,58 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<div class="title is-4">
|
||||||
<div class="modal-content">
|
<a @click="open" v-text="item.name" />
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<p class="title is-4">
|
|
||||||
<a class="has-text-link" @click="open" v-text="item.name" />
|
|
||||||
</p>
|
|
||||||
<div class="content is-small">
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.genre.albums')" />
|
|
||||||
<span class="title is-6" v-text="item.album_count" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.genre.tracks')" />
|
|
||||||
<span class="title is-6" v-text="item.track_count" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.genre.duration')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.durationInHours(item.length_ms)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.genre.add')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.genre.add-next')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.genre.play')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.genre.albums')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div class="title is-6" v-text="item.album_count" />
|
||||||
</transition>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.genre.tracks')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.track_count" />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.genre.duration')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="$filters.durationInHours(item.length_ms)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.genre.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.genre.add-next')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.genre.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogGenre',
|
name: 'ModalDialogGenre',
|
||||||
|
components: { ModalDialog },
|
||||||
props: {
|
props: {
|
||||||
item: { required: true, type: Object },
|
item: { required: true, type: Object },
|
||||||
media_kind: { required: true, type: String },
|
media_kind: { required: true, type: String },
|
||||||
@ -92,5 +89,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,61 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<div class="title is-4">
|
||||||
<div class="modal-content">
|
<a @click="open" v-text="item.name" />
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<p class="title is-4">
|
|
||||||
<a class="has-text-link" @click="open" v-text="item.name" />
|
|
||||||
</p>
|
|
||||||
<div class="content is-small">
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.playlist.path')" />
|
|
||||||
<span class="title is-6" v-text="item.path" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.playlist.type')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$t(`playlist.type.${item.type}`)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="!item.folder">
|
|
||||||
<span class="heading" v-text="$t('dialog.playlist.tracks')" />
|
|
||||||
<span class="title is-6" v-text="item.item_count" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer v-if="!item.folder" class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.playlist.add')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.playlist.add-next')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.playlist.play')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.playlist.path')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div class="title is-6" v-text="item.path" />
|
||||||
</transition>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.playlist.type')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="$t(`playlist.type.${item.type}`)" />
|
||||||
|
</div>
|
||||||
|
<div v-if="!item.folder" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.playlist.tracks')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.item_count" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="!item.folder" #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.playlist.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.playlist.add-next')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.playlist.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogPlaylist',
|
name: 'ModalDialogPlaylist',
|
||||||
|
components: { ModalDialog },
|
||||||
props: {
|
props: {
|
||||||
item: { required: true, type: Object },
|
item: { required: true, type: Object },
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
@ -86,5 +80,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,73 +1,56 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<form @submit.prevent="save">
|
||||||
<div class="modal-content">
|
<p class="title is-4" v-text="$t('dialog.playlist.save.title')" />
|
||||||
<form class="card" @submit.prevent="save">
|
<div class="field">
|
||||||
<div class="card-content">
|
<p class="control has-icons-left">
|
||||||
<p class="title is-4" v-text="$t('dialog.playlist.save.title')" />
|
<input
|
||||||
<div class="field">
|
ref="playlist_name_field"
|
||||||
<p class="control has-icons-left">
|
v-model="playlist_name"
|
||||||
<input
|
class="input"
|
||||||
ref="playlist_name_field"
|
type="text"
|
||||||
v-model="playlist_name"
|
pattern=".+"
|
||||||
class="input is-shadowless"
|
required
|
||||||
type="text"
|
:placeholder="$t('dialog.playlist.save.playlist-name')"
|
||||||
pattern=".+"
|
:disabled="loading"
|
||||||
required
|
@input="check_name"
|
||||||
:placeholder="$t('dialog.playlist.save.playlist-name')"
|
/>
|
||||||
:disabled="loading"
|
<mdicon class="icon is-left" name="file-music" size="16" />
|
||||||
@input="check_name"
|
</p>
|
||||||
/>
|
</div>
|
||||||
<mdicon class="icon is-left" name="file-music" size="16" />
|
</form>
|
||||||
</p>
|
</template>
|
||||||
</div>
|
<template v-if="loading" #footer>
|
||||||
</div>
|
<a class="card-footer-item has-text-dark">
|
||||||
<footer v-if="loading" class="card-footer">
|
<mdicon class="icon" name="web" size="16" />
|
||||||
<a class="card-footer-item has-text-dark">
|
<span class="is-size-7" v-text="$t('dialog.playlist.save.saving')" />
|
||||||
<mdicon class="icon" name="web" size="16" />
|
</a>
|
||||||
<span
|
</template>
|
||||||
class="is-size-7"
|
<template v-else #footer>
|
||||||
v-text="$t('dialog.playlist.save.saving')"
|
<a class="card-footer-item has-text-danger" @click="$emit('close')">
|
||||||
/>
|
<mdicon class="icon" name="cancel" size="16" />
|
||||||
</a>
|
<span class="is-size-7" v-text="$t('dialog.playlist.save.cancel')" />
|
||||||
</footer>
|
</a>
|
||||||
<footer v-else class="card-footer is-clipped">
|
<a
|
||||||
<a class="card-footer-item has-text-danger" @click="$emit('close')">
|
:class="{ 'is-disabled': disabled }"
|
||||||
<mdicon class="icon" name="cancel" size="16" />
|
class="card-footer-item has-text-weight-bold"
|
||||||
<span
|
@click="save"
|
||||||
class="is-size-7"
|
>
|
||||||
v-text="$t('dialog.playlist.save.cancel')"
|
<mdicon class="icon" name="content-save" size="16" />
|
||||||
/>
|
<span class="is-size-7" v-text="$t('dialog.playlist.save.save')" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
</template>
|
||||||
:class="{ 'is-disabled': disabled }"
|
</modal-dialog>
|
||||||
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
|
|
||||||
@click="save"
|
|
||||||
>
|
|
||||||
<mdicon class="icon" name="content-save" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.playlist.save.save')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="modal-close is-large"
|
|
||||||
aria-label="close"
|
|
||||||
@click="$emit('close')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogPlaylistSave',
|
name: 'ModalDialogPlaylistSave',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { show: Boolean },
|
props: { show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -111,5 +94,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,76 +1,58 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<div class="title is-4">
|
||||||
<div class="modal-content">
|
<a @click="open" v-text="item.name" />
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<p class="title is-4">
|
|
||||||
<a class="has-text-link" @click="open" v-text="item.name" />
|
|
||||||
</p>
|
|
||||||
<div class="content is-small">
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.playlist.owner')"
|
|
||||||
/>
|
|
||||||
<span class="title is-6" v-text="item.owner.display_name" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.playlist.tracks')"
|
|
||||||
/>
|
|
||||||
<span class="title is-6" v-text="item.tracks.total" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.playlist.path')"
|
|
||||||
/>
|
|
||||||
<span class="title is-6" v-text="item.uri" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.playlist.add')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.playlist.add-next')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.playlist.play')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.spotify.playlist.owner')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div class="title is-6" v-text="item.owner.display_name" />
|
||||||
</transition>
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.spotify.playlist.tracks')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.tracks.total" />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.spotify.playlist.path')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.uri" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.playlist.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span
|
||||||
|
class="is-size-7"
|
||||||
|
v-text="$t('dialog.spotify.playlist.add-next')"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.playlist.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogPlaylistSpotify',
|
name: 'ModalDialogPlaylistSpotify',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { item: { required: true, type: Object }, show: Boolean },
|
props: { item: { required: true, type: Object }, show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -97,5 +79,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,146 +1,141 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<div class="title is-4" v-text="item.title" />
|
||||||
<div class="modal-content">
|
<div class="subtitle" v-text="item.artist" />
|
||||||
<div class="card">
|
<div v-if="item.album" class="mb-3">
|
||||||
<div class="card-content">
|
<div
|
||||||
<p class="title is-4" v-text="item.title" />
|
class="is-size-7 is-uppercase"
|
||||||
<p class="subtitle" v-text="item.artist" />
|
v-text="$t('dialog.queue-item.album')"
|
||||||
<div class="content is-small">
|
/>
|
||||||
<p v-if="item.album">
|
<div class="title is-6">
|
||||||
<span class="heading" v-text="$t('dialog.queue-item.album')" />
|
<a @click="open_album" v-text="item.album" />
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_album"
|
|
||||||
v-text="item.album"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.album_artist">
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.queue-item.album-artist')"
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_album_artist"
|
|
||||||
v-text="item.album_artist"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.composer">
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.queue-item.composer')"
|
|
||||||
/>
|
|
||||||
<span class="title is-6" v-text="item.composer" />
|
|
||||||
</p>
|
|
||||||
<p v-if="item.year">
|
|
||||||
<span class="heading" v-text="$t('dialog.queue-item.year')" />
|
|
||||||
<span class="title is-6" v-text="item.year" />
|
|
||||||
</p>
|
|
||||||
<p v-if="item.genre">
|
|
||||||
<span class="heading" v-text="$t('dialog.queue-item.genre')" />
|
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_genre"
|
|
||||||
v-text="item.genre"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.disc_number">
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.queue-item.position')"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="[item.disc_number, item.track_number].join(' / ')"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.length_ms">
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.queue-item.duration')"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.durationInHours(item.length_ms)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.queue-item.path')" />
|
|
||||||
<span class="title is-6" v-text="item.path" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.queue-item.type')" />
|
|
||||||
<span class="title is-6">
|
|
||||||
<span
|
|
||||||
v-text="
|
|
||||||
`${$t(`media.kind.${item.media_kind}`)} - ${$t(`data.kind.${item.data_kind}`)}`
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.samplerate">
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.queue-item.quality')"
|
|
||||||
/>
|
|
||||||
<span class="title is-6">
|
|
||||||
<span v-text="item.type" />
|
|
||||||
<span
|
|
||||||
v-if="item.samplerate"
|
|
||||||
v-text="
|
|
||||||
$t('dialog.queue-item.samplerate', {
|
|
||||||
rate: item.samplerate
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
v-if="item.channels"
|
|
||||||
v-text="
|
|
||||||
$t('dialog.queue-item.channels', {
|
|
||||||
channels: $filters.channels(item.channels)
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
v-if="item.bitrate"
|
|
||||||
v-text="
|
|
||||||
$t('dialog.queue-item.bitrate', { rate: item.bitrate })
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="remove">
|
|
||||||
<mdicon class="icon" name="delete" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.queue-item.remove')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.queue-item.play')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div v-if="item.album_artist" class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.queue-item.album-artist')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div class="title is-6">
|
||||||
</transition>
|
<a @click="open_album_artist" v-text="item.album_artist" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.composer" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.queue-item.composer')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.composer" />
|
||||||
|
</div>
|
||||||
|
<div v-if="item.year" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.queue-item.year')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.year" />
|
||||||
|
</div>
|
||||||
|
<div v-if="item.genre" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.queue-item.genre')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6">
|
||||||
|
<a @click="open_genre" v-text="item.genre" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.disc_number" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.queue-item.position')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="[item.disc_number, item.track_number].join(' / ')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.length_ms" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.queue-item.duration')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="$filters.durationInHours(item.length_ms)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.queue-item.path')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.path" />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.queue-item.type')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6">
|
||||||
|
<span
|
||||||
|
v-text="
|
||||||
|
`${$t(`media.kind.${item.media_kind}`)} - ${$t(`data.kind.${item.data_kind}`)}`
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.samplerate" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.queue-item.quality')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6">
|
||||||
|
<span v-text="item.type" />
|
||||||
|
<span
|
||||||
|
v-if="item.samplerate"
|
||||||
|
v-text="
|
||||||
|
$t('dialog.queue-item.samplerate', {
|
||||||
|
rate: item.samplerate
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-if="item.channels"
|
||||||
|
v-text="
|
||||||
|
$t('dialog.queue-item.channels', {
|
||||||
|
channels: $filters.channels(item.channels)
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-if="item.bitrate"
|
||||||
|
v-text="$t('dialog.queue-item.bitrate', { rate: item.bitrate })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="remove">
|
||||||
|
<mdicon class="icon" name="delete" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.queue-item.remove')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.queue-item.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import SpotifyWebApi from 'spotify-web-api-js'
|
import SpotifyWebApi from 'spotify-web-api-js'
|
||||||
import { useServicesStore } from '@/stores/services'
|
import { useServicesStore } from '@/stores/services'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogQueueItem',
|
name: 'ModalDialogQueueItem',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { item: { required: true, type: Object }, show: Boolean },
|
props: { item: { required: true, type: Object }, show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -233,5 +228,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,63 +1,44 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<p class="title is-4" v-text="$t('dialog.remote-pairing.title')" />
|
||||||
<div class="modal-content">
|
<form @submit.prevent="kickoff_pairing">
|
||||||
<div class="card">
|
<label class="label" v-text="pairing.remote" />
|
||||||
<div class="card-content">
|
<div class="field">
|
||||||
<p class="title is-4" v-text="$t('dialog.remote-pairing.title')" />
|
<div class="control">
|
||||||
<form @submit.prevent="kickoff_pairing">
|
<input
|
||||||
<label class="label" v-text="pairing.remote" />
|
ref="pin_field"
|
||||||
<div class="field">
|
v-model="pairing_req.pin"
|
||||||
<div class="control">
|
class="input"
|
||||||
<input
|
inputmode="numeric"
|
||||||
ref="pin_field"
|
pattern="[\d]{4}"
|
||||||
v-model="pairing_req.pin"
|
:placeholder="$t('dialog.remote-pairing.pairing-code')"
|
||||||
class="input"
|
/>
|
||||||
inputmode="numeric"
|
|
||||||
pattern="[\d]{4}"
|
|
||||||
:placeholder="$t('dialog.remote-pairing.pairing-code')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<footer class="card-footer is-clipped">
|
|
||||||
<a class="card-footer-item has-text-danger" @click="$emit('close')">
|
|
||||||
<mdicon class="icon" name="cancel" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.remote-pairing.cancel')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
class="card-footer-item has-background-info has-text-white has-text-weight-bold"
|
|
||||||
@click="kickoff_pairing"
|
|
||||||
>
|
|
||||||
<mdicon class="icon" name="cellphone" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.remote-pairing.pair')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
<button
|
</template>
|
||||||
class="modal-close is-large"
|
<template #footer>
|
||||||
aria-label="close"
|
<a class="card-footer-item has-text-danger" @click="$emit('close')">
|
||||||
@click="$emit('close')"
|
<mdicon class="icon" name="cancel" size="16" />
|
||||||
/>
|
<span class="is-size-7" v-text="$t('dialog.remote-pairing.cancel')" />
|
||||||
</div>
|
</a>
|
||||||
</transition>
|
<a class="card-footer-item" @click="kickoff_pairing">
|
||||||
|
<mdicon class="icon" name="cellphone" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.remote-pairing.pair')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import { useRemotesStore } from '@/stores/remotes'
|
import { useRemotesStore } from '@/stores/remotes'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogRemotePairing',
|
name: 'ModalDialogRemotePairing',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { show: Boolean },
|
props: { show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -98,5 +79,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,182 +1,181 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<p class="title is-4" v-text="item.title" />
|
||||||
<div class="modal-content">
|
<p class="subtitle" v-text="item.artist" />
|
||||||
<div class="card">
|
<div v-if="item.media_kind === 'podcast'" class="buttons">
|
||||||
<div class="card-content">
|
<a
|
||||||
<p class="title is-4" v-text="item.title" />
|
v-if="item.play_count > 0"
|
||||||
<p class="subtitle" v-text="item.artist" />
|
class="button is-small"
|
||||||
<div v-if="item.media_kind === 'podcast'" class="buttons">
|
@click="mark_new"
|
||||||
<a
|
v-text="$t('dialog.track.mark-as-new')"
|
||||||
v-if="item.play_count > 0"
|
/>
|
||||||
class="button is-small"
|
<a
|
||||||
@click="mark_new"
|
v-if="item.play_count === 0"
|
||||||
v-text="$t('dialog.track.mark-as-new')"
|
class="button is-small"
|
||||||
/>
|
@click="mark_played"
|
||||||
<a
|
v-text="$t('dialog.track.mark-as-played')"
|
||||||
v-if="item.play_count === 0"
|
/>
|
||||||
class="button is-small"
|
</div>
|
||||||
@click="mark_played"
|
<div v-if="item.album" class="mb-3">
|
||||||
v-text="$t('dialog.track.mark-as-played')"
|
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.album')" />
|
||||||
/>
|
<div class="title is-6">
|
||||||
</div>
|
<a @click="open_album" v-text="item.album" />
|
||||||
<div class="content is-small">
|
|
||||||
<p v-if="item.album">
|
|
||||||
<span class="heading" v-text="$t('dialog.track.album')" />
|
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_album"
|
|
||||||
v-text="item.album"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.album_artist && item.media_kind !== 'audiobook'">
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.track.album-artist')"
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_album_artist"
|
|
||||||
v-text="item.album_artist"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.composer">
|
|
||||||
<span class="heading" v-text="$t('dialog.track.composer')" />
|
|
||||||
<span class="title is-6" v-text="item.composer" />
|
|
||||||
</p>
|
|
||||||
<p v-if="item.date_released">
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.track.release-date')"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.date(item.date_released)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-else-if="item.year">
|
|
||||||
<span class="heading" v-text="$t('dialog.track.year')" />
|
|
||||||
<span class="title is-6" v-text="item.year" />
|
|
||||||
</p>
|
|
||||||
<p v-if="item.genre">
|
|
||||||
<span class="heading" v-text="$t('dialog.track.genre')" />
|
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_genre"
|
|
||||||
v-text="item.genre"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.disc_number">
|
|
||||||
<span class="heading" v-text="$t('dialog.track.position')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="[item.disc_number, item.track_number].join(' / ')"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.length_ms">
|
|
||||||
<span class="heading" v-text="$t('dialog.track.duration')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.durationInHours(item.length_ms)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.track.path')" />
|
|
||||||
<span class="title is-6" v-text="item.path" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.track.type')" />
|
|
||||||
<span class="title is-6">
|
|
||||||
<span
|
|
||||||
v-text="
|
|
||||||
`${$t(`media.kind.${item.media_kind}`)} - ${$t(`data.kind.${item.data_kind}`)}`
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.samplerate">
|
|
||||||
<span class="heading" v-text="$t('dialog.track.quality')" />
|
|
||||||
<span class="title is-6">
|
|
||||||
<span v-text="item.type" />
|
|
||||||
<span
|
|
||||||
v-if="item.samplerate"
|
|
||||||
v-text="
|
|
||||||
$t('dialog.track.samplerate', {
|
|
||||||
rate: item.samplerate
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
v-if="item.channels"
|
|
||||||
v-text="
|
|
||||||
$t('dialog.track.channels', {
|
|
||||||
channels: $filters.channels(item.channels)
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
v-if="item.bitrate"
|
|
||||||
v-text="$t('dialog.track.bitrate', { rate: item.bitrate })"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.track.added-on')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.datetime(item.time_added)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span class="heading" v-text="$t('dialog.track.rating')" />
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="
|
|
||||||
$t('dialog.track.rating-value', {
|
|
||||||
rating: Math.floor(item.rating / 10)
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p v-if="item.comment">
|
|
||||||
<span class="heading" v-text="$t('dialog.track.comment')" />
|
|
||||||
<span class="title is-6" v-text="item.comment" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.track.add')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.track.add-next')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.track.play')" />
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div
|
||||||
class="modal-close is-large"
|
v-if="item.album_artist && item.media_kind !== 'audiobook'"
|
||||||
aria-label="close"
|
class="mb-3"
|
||||||
@click="$emit('close')"
|
>
|
||||||
/>
|
<div
|
||||||
</div>
|
class="is-size-7 is-uppercase"
|
||||||
</transition>
|
v-text="$t('dialog.track.album-artist')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6">
|
||||||
|
<a @click="open_album_artist" v-text="item.album_artist" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.composer" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.track.composer')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.composer" />
|
||||||
|
</div>
|
||||||
|
<div v-if="item.date_released" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.track.release-date')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="$filters.date(item.date_released)" />
|
||||||
|
</div>
|
||||||
|
<div v-else-if="item.year" class="mb-3">
|
||||||
|
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.year')" />
|
||||||
|
<div class="title is-6" v-text="item.year" />
|
||||||
|
</div>
|
||||||
|
<div v-if="item.genre" class="mb-3">
|
||||||
|
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.genre')" />
|
||||||
|
<div class="title is-6">
|
||||||
|
<a @click="open_genre" v-text="item.genre" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.disc_number" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.track.position')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="[item.disc_number, item.track_number].join(' / ')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.length_ms" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.track.duration')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="$filters.durationInHours(item.length_ms)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.path')" />
|
||||||
|
<div class="title is-6" v-text="item.path" />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="is-size-7 is-uppercase" v-text="$t('dialog.track.type')" />
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="
|
||||||
|
`${$t(`media.kind.${item.media_kind}`)} - ${$t(`data.kind.${item.data_kind}`)}`
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.samplerate" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.track.quality')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6">
|
||||||
|
<span v-text="item.type" />
|
||||||
|
<span
|
||||||
|
v-if="item.samplerate"
|
||||||
|
v-text="
|
||||||
|
$t('dialog.track.samplerate', {
|
||||||
|
rate: item.samplerate
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-if="item.channels"
|
||||||
|
v-text="
|
||||||
|
$t('dialog.track.channels', {
|
||||||
|
channels: $filters.channels(item.channels)
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-if="item.bitrate"
|
||||||
|
v-text="$t('dialog.track.bitrate', { rate: item.bitrate })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.track.added-on')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="$filters.datetime(item.time_added)" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.track.rating')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="
|
||||||
|
$t('dialog.track.rating-value', {
|
||||||
|
rating: Math.floor(item.rating / 10)
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.comment" class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.track.comment')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.comment" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.track.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.track.add-next')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.track.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import SpotifyWebApi from 'spotify-web-api-js'
|
import SpotifyWebApi from 'spotify-web-api-js'
|
||||||
import { useServicesStore } from '@/stores/services'
|
import { useServicesStore } from '@/stores/services'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogTrack',
|
name: 'ModalDialogTrack',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { item: { required: true, type: Object }, show: Boolean },
|
props: { item: { required: true, type: Object }, show: Boolean },
|
||||||
emits: ['close', 'play-count-changed'],
|
emits: ['close', 'play-count-changed'],
|
||||||
|
|
||||||
@ -296,5 +295,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,110 +1,88 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<modal-dialog :show="show" @close="$emit('close')">
|
||||||
<div v-if="show" class="modal is-active">
|
<template #content>
|
||||||
<div class="modal-background" @click="$emit('close')" />
|
<p class="title is-4" v-text="item.name" />
|
||||||
<div class="modal-content">
|
<p class="subtitle" v-text="item.artists[0].name" />
|
||||||
<div class="card">
|
<div class="mb-3">
|
||||||
<div class="card-content">
|
<div
|
||||||
<p class="title is-4" v-text="item.name" />
|
class="is-size-7 is-uppercase"
|
||||||
<p class="subtitle" v-text="item.artists[0].name" />
|
v-text="$t('dialog.spotify.track.album')"
|
||||||
<div class="content is-small">
|
/>
|
||||||
<p>
|
<div class="title is-6">
|
||||||
<span
|
<a @click="open_album" v-text="item.album.name" />
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.track.album')"
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_album"
|
|
||||||
v-text="item.album.name"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.track.album-artist')"
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
class="title is-6 has-text-link"
|
|
||||||
@click="open_artist"
|
|
||||||
v-text="item.artists[0].name"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.track.release-date')"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.date(item.album.release_date)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.track.position')"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="[item.disc_number, item.track_number].join(' / ')"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.track.duration')"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="title is-6"
|
|
||||||
v-text="$filters.durationInHours(item.duration_ms)"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<span
|
|
||||||
class="heading"
|
|
||||||
v-text="$t('dialog.spotify.track.path')"
|
|
||||||
/>
|
|
||||||
<span class="title is-6" v-text="item.uri" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer class="card-footer">
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add">
|
|
||||||
<mdicon class="icon" name="playlist-plus" size="16" />
|
|
||||||
<span class="is-size-7" v-text="$t('dialog.spotify.track.add')" />
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
|
||||||
<mdicon class="icon" name="playlist-play" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.track.add-next')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a class="card-footer-item has-text-dark" @click="play">
|
|
||||||
<mdicon class="icon" name="play" size="16" />
|
|
||||||
<span
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="$t('dialog.spotify.track.play')"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="mb-3">
|
||||||
class="modal-close is-large"
|
<div
|
||||||
aria-label="close"
|
class="is-size-7 is-uppercase"
|
||||||
@click="$emit('close')"
|
v-text="$t('dialog.spotify.track.album-artist')"
|
||||||
/>
|
/>
|
||||||
</div>
|
<div class="title is-6">
|
||||||
</transition>
|
<a @click="open_artist" v-text="item.artists[0].name" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.spotify.track.release-date')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="$filters.date(item.album.release_date)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.spotify.track.position')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="[item.disc_number, item.track_number].join(' / ')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.spotify.track.duration')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="title is-6"
|
||||||
|
v-text="$filters.durationInHours(item.duration_ms)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('dialog.spotify.track.path')"
|
||||||
|
/>
|
||||||
|
<div class="title is-6" v-text="item.uri" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add">
|
||||||
|
<mdicon class="icon" name="playlist-plus" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.track.add')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="queue_add_next">
|
||||||
|
<mdicon class="icon" name="playlist-play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.track.add-next')" />
|
||||||
|
</a>
|
||||||
|
<a class="card-footer-item has-text-dark" @click="play">
|
||||||
|
<mdicon class="icon" name="play" size="16" />
|
||||||
|
<span class="is-size-7" v-text="$t('dialog.spotify.track.play')" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</modal-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModalDialog from '@/components/ModalDialog.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogTrackSpotify',
|
name: 'ModalDialogTrackSpotify',
|
||||||
|
components: { ModalDialog },
|
||||||
props: { item: { required: true, type: Object }, show: Boolean },
|
props: { item: { required: true, type: Object }, show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -138,5 +116,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<modal-dialog
|
<modal-dialog-action
|
||||||
:show="show"
|
:show="show"
|
||||||
:title="$t('dialog.update.title')"
|
:title="$t('dialog.update.title')"
|
||||||
:ok_action="library.updating ? '' : $t('dialog.update.rescan')"
|
:ok_action="libraryStore.updating ? '' : $t('dialog.update.rescan')"
|
||||||
:close_action="$t('dialog.update.cancel')"
|
:close_action="$t('dialog.update.cancel')"
|
||||||
@ok="update_library"
|
@ok="update_library"
|
||||||
@close="close()"
|
@close="close()"
|
||||||
>
|
>
|
||||||
<template #modal-content>
|
<template #modal-content>
|
||||||
<div v-if="!library.updating">
|
<div v-if="!libraryStore.updating">
|
||||||
<p class="mb-3" v-text="$t('dialog.update.info')" />
|
|
||||||
<div v-if="spotify_enabled || rss.tracks > 0" class="field">
|
<div v-if="spotify_enabled || rss.tracks > 0" class="field">
|
||||||
|
<label class="label" v-text="$t('dialog.update.info')" />
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<div class="select is-small">
|
<div class="select is-small">
|
||||||
<select v-model="update_dialog_scan_kind">
|
<select v-model="libraryStore.update_dialog_scan_kind">
|
||||||
<option value="" v-text="$t('dialog.update.all')" />
|
<option value="" v-text="$t('dialog.update.all')" />
|
||||||
<option value="files" v-text="$t('dialog.update.local')" />
|
<option value="files" v-text="$t('dialog.update.local')" />
|
||||||
<option
|
<option
|
||||||
@ -30,32 +30,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<control-switch v-model="rescan_metadata">
|
||||||
<input
|
<template #label>
|
||||||
id="rescan"
|
<span v-text="$t('dialog.update.rescan-metadata')" />
|
||||||
v-model="rescan_metadata"
|
</template>
|
||||||
type="checkbox"
|
</control-switch>
|
||||||
class="switch is-rounded is-small"
|
|
||||||
/>
|
|
||||||
<label for="rescan" v-text="$t('dialog.update.rescan-metadata')" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<p class="mb-3" v-text="$t('dialog.update.progress')" />
|
<p class="mb-3" v-text="$t('dialog.update.progress')" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</modal-dialog>
|
</modal-dialog-action>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ModalDialog from '@/components/ModalDialog.vue'
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
|
import ModalDialogAction from '@/components/ModalDialogAction.vue'
|
||||||
import { useLibraryStore } from '@/stores/library'
|
import { useLibraryStore } from '@/stores/library'
|
||||||
import { useServicesStore } from '@/stores/services'
|
import { useServicesStore } from '@/stores/services'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ModalDialogUpdate',
|
name: 'ModalDialogUpdate',
|
||||||
components: { ModalDialog },
|
components: { ControlSwitch, ModalDialogAction },
|
||||||
props: { show: Boolean },
|
props: { show: Boolean },
|
||||||
emits: ['close'],
|
emits: ['close'],
|
||||||
|
|
||||||
@ -73,42 +70,26 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
library() {
|
|
||||||
return this.libraryStore.$state
|
|
||||||
},
|
|
||||||
|
|
||||||
rss() {
|
rss() {
|
||||||
return this.libraryStore.rss
|
return this.libraryStore.rss
|
||||||
},
|
},
|
||||||
|
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
},
|
|
||||||
|
|
||||||
update_dialog_scan_kind: {
|
|
||||||
get() {
|
|
||||||
return this.library.update_dialog_scan_kind
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.library.update_dialog_scan_kind = value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
close() {
|
close() {
|
||||||
this.update_dialog_scan_kind = ''
|
this.libraryStore.update_dialog_scan_kind = ''
|
||||||
this.$emit('close')
|
this.$emit('close')
|
||||||
},
|
},
|
||||||
update_library() {
|
update_library() {
|
||||||
if (this.rescan_metadata) {
|
if (this.rescan_metadata) {
|
||||||
webapi.library_rescan(this.update_dialog_scan_kind)
|
webapi.library_rescan(this.libraryStore.update_dialog_scan_kind)
|
||||||
} else {
|
} else {
|
||||||
webapi.library_update(this.update_dialog_scan_kind)
|
webapi.library_update(this.libraryStore.update_dialog_scan_kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,250 +1,68 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav
|
<nav
|
||||||
class="navbar is-block is-white is-fixed-bottom fd-bottom-navbar"
|
class="navbar is-fixed-bottom"
|
||||||
:class="{
|
:class="{ 'is-dark': !is_now_playing_page }"
|
||||||
'is-transparent': is_now_playing_page,
|
|
||||||
'is-dark': !is_now_playing_page
|
|
||||||
}"
|
|
||||||
role="navigation"
|
|
||||||
aria-label="player controls"
|
|
||||||
>
|
>
|
||||||
<!-- Player menu for desktop -->
|
|
||||||
<div
|
|
||||||
class="navbar-item has-dropdown has-dropdown-up is-hidden-touch"
|
|
||||||
:class="{ 'is-active': show_player_menu }"
|
|
||||||
>
|
|
||||||
<div class="navbar-dropdown is-right fd-width-auto">
|
|
||||||
<div class="navbar-item">
|
|
||||||
<!-- Outputs: master volume -->
|
|
||||||
<div class="level is-mobile">
|
|
||||||
<div class="level-left is-flex-grow-1">
|
|
||||||
<div class="level-item is-flex-grow-0">
|
|
||||||
<a class="button is-white is-small" @click="toggle_mute_volume">
|
|
||||||
<mdicon
|
|
||||||
class="icon"
|
|
||||||
:name="player.volume > 0 ? 'volume-high' : 'volume-off'"
|
|
||||||
size="18"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="level-item">
|
|
||||||
<div>
|
|
||||||
<p class="heading" v-text="$t('navigation.volume')" />
|
|
||||||
<control-slider
|
|
||||||
v-model:value="player.volume"
|
|
||||||
:max="100"
|
|
||||||
@change="change_volume"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Outputs: master volume -->
|
|
||||||
<hr class="my-3" />
|
|
||||||
<navbar-item-output
|
|
||||||
v-for="output in outputs"
|
|
||||||
:key="output.id"
|
|
||||||
:output="output"
|
|
||||||
/>
|
|
||||||
<!-- Outputs: stream volume -->
|
|
||||||
<hr class="my-3" />
|
|
||||||
<div class="navbar-item">
|
|
||||||
<div class="level is-mobile">
|
|
||||||
<div class="level-left is-flex-grow-1">
|
|
||||||
<div class="level-item is-flex-grow-0">
|
|
||||||
<a
|
|
||||||
class="button is-white is-small"
|
|
||||||
:class="{
|
|
||||||
'has-text-grey-light': !playing && !loading,
|
|
||||||
'is-loading': loading
|
|
||||||
}"
|
|
||||||
@click="togglePlay"
|
|
||||||
>
|
|
||||||
<mdicon class="icon" name="broadcast" size="18" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="level-item">
|
|
||||||
<div class="is-flex-grow-1">
|
|
||||||
<div
|
|
||||||
class="is-flex is-align-content-center"
|
|
||||||
:class="{ 'has-text-grey-light': !playing }"
|
|
||||||
>
|
|
||||||
<p class="heading" v-text="$t('navigation.stream')" />
|
|
||||||
<a href="stream.mp3" class="heading ml-2" target="_blank">
|
|
||||||
<mdicon
|
|
||||||
class="icon is-small"
|
|
||||||
name="open-in-new"
|
|
||||||
size="16"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<control-slider
|
|
||||||
v-model:value="stream_volume"
|
|
||||||
:disabled="!playing"
|
|
||||||
:max="100"
|
|
||||||
:cursor="cursor"
|
|
||||||
@change="change_stream_volume"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="my-3" />
|
|
||||||
<div class="navbar-item is-justify-content-center">
|
|
||||||
<div class="buttons has-addons">
|
|
||||||
<player-button-repeat class="button" />
|
|
||||||
<player-button-shuffle class="button" />
|
|
||||||
<player-button-consume class="button" />
|
|
||||||
<player-button-lyrics class="button" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="navbar-brand is-flex-grow-1">
|
<div class="navbar-brand is-flex-grow-1">
|
||||||
<navbar-item-link :to="{ name: 'queue' }" class="mr-auto">
|
<control-link class="navbar-item" :to="{ name: 'queue' }">
|
||||||
<mdicon class="icon" name="playlist-play" size="24" />
|
<mdicon class="icon" name="playlist-play" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link
|
<template v-if="is_now_playing_page">
|
||||||
v-if="!is_now_playing_page"
|
<control-player-previous class="navbar-item ml-auto" />
|
||||||
:to="{ name: 'now-playing' }"
|
<control-player-back class="navbar-item" :offset="10000" />
|
||||||
exact
|
<control-player-play class="navbar-item" show_disabled_message />
|
||||||
class="is-expanded is-clipped is-size-7"
|
<control-player-forward class="navbar-item" :offset="30000" />
|
||||||
>
|
<control-player-next class="navbar-item mr-auto" />
|
||||||
<div class="fd-is-text-clipped">
|
</template>
|
||||||
<strong v-text="current.title" />
|
<template v-else>
|
||||||
<br />
|
<control-link
|
||||||
<span v-text="current.artist" />
|
:to="{ name: 'now-playing' }"
|
||||||
<span
|
exact
|
||||||
v-if="current.album"
|
class="navbar-item is-justify-content-flex-start is-expanded is-clipped is-size-7"
|
||||||
v-text="$t('navigation.now-playing', { album: current.album })"
|
>
|
||||||
/>
|
<div class="is-text-clipped">
|
||||||
</div>
|
<strong v-text="current.title" />
|
||||||
</navbar-item-link>
|
<br />
|
||||||
<player-button-previous
|
<span v-text="current.artist" />
|
||||||
v-if="is_now_playing_page"
|
<span
|
||||||
class="navbar-item px-2"
|
v-if="current.album"
|
||||||
:icon_size="24"
|
v-text="$t('navigation.now-playing', { album: current.album })"
|
||||||
/>
|
/>
|
||||||
<player-button-seek-back
|
</div>
|
||||||
v-if="is_now_playing_page"
|
</control-link>
|
||||||
:seek_ms="10000"
|
<control-player-play class="navbar-item" show_disabled_message />
|
||||||
class="navbar-item px-2"
|
</template>
|
||||||
:icon_size="24"
|
|
||||||
/>
|
|
||||||
<player-button-play-pause
|
|
||||||
class="navbar-item px-2"
|
|
||||||
:icon_size="36"
|
|
||||||
show_disabled_message
|
|
||||||
/>
|
|
||||||
<player-button-seek-forward
|
|
||||||
v-if="is_now_playing_page"
|
|
||||||
:seek_ms="30000"
|
|
||||||
class="navbar-item px-2"
|
|
||||||
:icon_size="24"
|
|
||||||
/>
|
|
||||||
<player-button-next
|
|
||||||
v-if="is_now_playing_page"
|
|
||||||
class="navbar-item px-2"
|
|
||||||
:icon_size="24"
|
|
||||||
/>
|
|
||||||
<a
|
<a
|
||||||
class="navbar-item ml-auto"
|
class="navbar-item"
|
||||||
@click="show_player_menu = !show_player_menu"
|
@click="uiStore.show_player_menu = !uiStore.show_player_menu"
|
||||||
>
|
>
|
||||||
<mdicon
|
<mdicon
|
||||||
class="icon"
|
class="icon"
|
||||||
:name="show_player_menu ? 'chevron-down' : 'chevron-up'"
|
:name="uiStore.show_player_menu ? 'chevron-down' : 'chevron-up'"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
<div
|
||||||
<!-- Player menu for mobile and tablet -->
|
class="dropdown is-up is-right"
|
||||||
<div
|
:class="{ 'is-active': uiStore.show_player_menu }"
|
||||||
class="navbar-menu is-hidden-desktop"
|
>
|
||||||
:class="{ 'is-active': show_player_menu }"
|
<div class="dropdown-menu">
|
||||||
>
|
<div class="dropdown-content">
|
||||||
<div class="navbar-item">
|
<div class="dropdown-item pt-0">
|
||||||
<div class="buttons has-addons is-centered">
|
<control-main-volume />
|
||||||
<player-button-repeat class="button" />
|
<control-output-volume
|
||||||
<player-button-shuffle class="button" />
|
v-for="output in outputsStore.outputs"
|
||||||
<player-button-consume class="button" />
|
:key="output.id"
|
||||||
<player-button-lyrics class="button" />
|
:output="output"
|
||||||
</div>
|
/>
|
||||||
</div>
|
<control-stream-volume />
|
||||||
<hr class="my-3" />
|
|
||||||
<!-- Outputs: master volume -->
|
|
||||||
<div class="navbar-item">
|
|
||||||
<div class="level is-mobile">
|
|
||||||
<div class="level-left is-flex-grow-1">
|
|
||||||
<div class="level-item is-flex-grow-0">
|
|
||||||
<a class="button is-white is-small" @click="toggle_mute_volume">
|
|
||||||
<mdicon
|
|
||||||
class="icon"
|
|
||||||
:name="player.volume > 0 ? 'volume-high' : 'volume-off'"
|
|
||||||
size="18"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="level-item">
|
<hr class="dropdown-divider" />
|
||||||
<div class="is-flex-grow-1">
|
<div class="dropdown-item is-flex is-justify-content-center">
|
||||||
<p class="heading" v-text="$t('navigation.volume')" />
|
<div class="buttons has-addons">
|
||||||
<control-slider
|
<control-player-repeat class="button" />
|
||||||
v-model:value="player.volume"
|
<control-player-shuffle class="button" />
|
||||||
:max="100"
|
<control-player-consume class="button" />
|
||||||
@change="change_volume"
|
<control-player-lyrics class="button" />
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="my-3" />
|
|
||||||
<!-- Outputs: speaker volumes -->
|
|
||||||
<navbar-item-output
|
|
||||||
v-for="output in outputs"
|
|
||||||
:key="output.id"
|
|
||||||
:output="output"
|
|
||||||
/>
|
|
||||||
<!-- Outputs: stream volume -->
|
|
||||||
<hr class="my-3" />
|
|
||||||
<div class="navbar-item mb-5">
|
|
||||||
<div class="level is-mobile">
|
|
||||||
<div class="level-left is-flex-grow-1">
|
|
||||||
<div class="level-item is-flex-grow-0">
|
|
||||||
<a
|
|
||||||
class="button is-white is-small"
|
|
||||||
:class="{
|
|
||||||
'has-text-grey-light': !playing && !loading,
|
|
||||||
'is-loading': loading
|
|
||||||
}"
|
|
||||||
@click="togglePlay"
|
|
||||||
>
|
|
||||||
<mdicon class="icon" name="radio-tower" size="16" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="level-item">
|
|
||||||
<div class="is-flex-grow-1">
|
|
||||||
<div
|
|
||||||
class="is-flex is-align-content-center"
|
|
||||||
:class="{ 'has-text-grey-light': !playing }"
|
|
||||||
>
|
|
||||||
<p class="heading" v-text="$t('navigation.stream')" />
|
|
||||||
<a href="stream.mp3" class="heading ml-2" target="_blank">
|
|
||||||
<mdicon
|
|
||||||
class="icon is-small"
|
|
||||||
name="open-in-new"
|
|
||||||
size="16"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<control-slider
|
|
||||||
v-model:value="stream_volume"
|
|
||||||
:disabled="!playing"
|
|
||||||
:max="100"
|
|
||||||
:cursor="cursor"
|
|
||||||
@change="change_stream_volume"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -255,168 +73,66 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ControlSlider from '@/components/ControlSlider.vue'
|
import ControlLink from '@/components/ControlLink.vue'
|
||||||
import NavbarItemLink from '@/components/NavbarItemLink.vue'
|
import ControlMainVolume from '@/components/ControlMainVolume.vue'
|
||||||
import NavbarItemOutput from '@/components/NavbarItemOutput.vue'
|
import ControlOutputVolume from '@/components/ControlOutputVolume.vue'
|
||||||
import PlayerButtonConsume from '@/components/PlayerButtonConsume.vue'
|
import ControlPlayerBack from '@/components/ControlPlayerBack.vue'
|
||||||
import PlayerButtonLyrics from '@/components/PlayerButtonLyrics.vue'
|
import ControlPlayerConsume from '@/components/ControlPlayerConsume.vue'
|
||||||
import PlayerButtonNext from '@/components/PlayerButtonNext.vue'
|
import ControlPlayerForward from '@/components/ControlPlayerForward.vue'
|
||||||
import PlayerButtonPlayPause from '@/components/PlayerButtonPlayPause.vue'
|
import ControlPlayerLyrics from '@/components/ControlPlayerLyrics.vue'
|
||||||
import PlayerButtonPrevious from '@/components/PlayerButtonPrevious.vue'
|
import ControlPlayerNext from '@/components/ControlPlayerNext.vue'
|
||||||
import PlayerButtonRepeat from '@/components/PlayerButtonRepeat.vue'
|
import ControlPlayerPlay from '@/components/ControlPlayerPlay.vue'
|
||||||
import PlayerButtonSeekBack from '@/components/PlayerButtonSeekBack.vue'
|
import ControlPlayerPrevious from '@/components/ControlPlayerPrevious.vue'
|
||||||
import PlayerButtonSeekForward from '@/components/PlayerButtonSeekForward.vue'
|
import ControlPlayerRepeat from '@/components/ControlPlayerRepeat.vue'
|
||||||
import PlayerButtonShuffle from '@/components/PlayerButtonShuffle.vue'
|
import ControlPlayerShuffle from '@/components/ControlPlayerShuffle.vue'
|
||||||
import audio from '@/lib/Audio'
|
import ControlStreamVolume from '@/components/ControlStreamVolume.vue'
|
||||||
import { mdiCancel } from '@mdi/js'
|
|
||||||
import { useNotificationsStore } from '@/stores/notifications'
|
import { useNotificationsStore } from '@/stores/notifications'
|
||||||
import { useOutputsStore } from '@/stores/outputs'
|
import { useOutputsStore } from '@/stores/outputs'
|
||||||
import { usePlayerStore } from '@/stores/player'
|
|
||||||
import { useQueueStore } from '@/stores/queue'
|
import { useQueueStore } from '@/stores/queue'
|
||||||
import { useUIStore } from '@/stores/ui'
|
import { useUIStore } from '@/stores/ui'
|
||||||
import webapi from '@/webapi'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NavbarBottom',
|
name: 'NavbarBottom',
|
||||||
components: {
|
components: {
|
||||||
ControlSlider,
|
ControlLink,
|
||||||
NavbarItemLink,
|
ControlOutputVolume,
|
||||||
NavbarItemOutput,
|
ControlMainVolume,
|
||||||
PlayerButtonConsume,
|
ControlPlayerBack,
|
||||||
PlayerButtonLyrics,
|
ControlPlayerConsume,
|
||||||
PlayerButtonNext,
|
ControlPlayerForward,
|
||||||
PlayerButtonPlayPause,
|
ControlPlayerLyrics,
|
||||||
PlayerButtonPrevious,
|
ControlPlayerNext,
|
||||||
PlayerButtonRepeat,
|
ControlPlayerPlay,
|
||||||
PlayerButtonSeekBack,
|
ControlPlayerPrevious,
|
||||||
PlayerButtonSeekForward,
|
ControlPlayerRepeat,
|
||||||
PlayerButtonShuffle
|
ControlPlayerShuffle,
|
||||||
|
ControlStreamVolume
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
notificationsStore: useNotificationsStore(),
|
notificationsStore: useNotificationsStore(),
|
||||||
outputsStore: useOutputsStore(),
|
outputsStore: useOutputsStore(),
|
||||||
playerStore: usePlayerStore(),
|
|
||||||
queueStore: useQueueStore(),
|
queueStore: useQueueStore(),
|
||||||
uiStore: useUIStore()
|
uiStore: useUIStore()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
cursor: mdiCancel,
|
|
||||||
loading: false,
|
|
||||||
old_volume: 0,
|
|
||||||
playing: false,
|
|
||||||
show_desktop_outputs_menu: false,
|
|
||||||
show_outputs_menu: false,
|
|
||||||
stream_volume: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
is_now_playing_page() {
|
is_now_playing_page() {
|
||||||
return this.$route.name === 'now-playing'
|
return this.$route.name === 'now-playing'
|
||||||
},
|
},
|
||||||
current() {
|
current() {
|
||||||
return this.queueStore.current
|
return this.queueStore.current
|
||||||
},
|
|
||||||
outputs() {
|
|
||||||
return this.outputsStore.outputs
|
|
||||||
},
|
|
||||||
player() {
|
|
||||||
return this.playerStore
|
|
||||||
},
|
|
||||||
show_player_menu: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.show_player_menu
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.show_player_menu = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
'playerStore.volume'() {
|
|
||||||
if (this.player.volume > 0) {
|
|
||||||
this.old_volume = this.player.volume
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// On app mounted
|
|
||||||
mounted() {
|
|
||||||
this.setupAudio()
|
|
||||||
},
|
|
||||||
|
|
||||||
// On app destroyed
|
|
||||||
unmounted() {
|
|
||||||
this.closeAudio()
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
change_stream_volume() {
|
|
||||||
audio.setVolume(this.stream_volume / 100)
|
|
||||||
},
|
|
||||||
change_volume() {
|
|
||||||
webapi.player_volume(this.player.volume)
|
|
||||||
},
|
|
||||||
closeAudio() {
|
|
||||||
audio.stop()
|
|
||||||
this.playing = false
|
|
||||||
},
|
|
||||||
on_click_outside_outputs() {
|
|
||||||
this.show_outputs_menu = false
|
|
||||||
},
|
|
||||||
playChannel() {
|
|
||||||
if (this.playing) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.loading = true
|
|
||||||
audio.play('/stream.mp3')
|
|
||||||
audio.setVolume(this.stream_volume / 100)
|
|
||||||
},
|
|
||||||
setupAudio() {
|
|
||||||
const a = audio.setup()
|
|
||||||
a.addEventListener('waiting', () => {
|
|
||||||
this.playing = false
|
|
||||||
this.loading = true
|
|
||||||
})
|
|
||||||
a.addEventListener('playing', () => {
|
|
||||||
this.playing = true
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
a.addEventListener('ended', () => {
|
|
||||||
this.playing = false
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
a.addEventListener('error', () => {
|
|
||||||
this.closeAudio()
|
|
||||||
this.notificationsStore.add({
|
|
||||||
text: this.$t('navigation.stream-error'),
|
|
||||||
type: 'danger'
|
|
||||||
})
|
|
||||||
this.playing = false
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
togglePlay() {
|
|
||||||
if (this.loading) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.playing) {
|
|
||||||
this.closeAudio()
|
|
||||||
}
|
|
||||||
this.playChannel()
|
|
||||||
},
|
|
||||||
toggle_mute_volume() {
|
|
||||||
this.player.volume = this.player.volume > 0 ? 0 : this.old_volume
|
|
||||||
this.change_volume()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style scoped>
|
||||||
|
.is-text-clipped {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="navbar-item">
|
|
||||||
<div class="level is-mobile">
|
|
||||||
<div class="level-left is-flex-grow-1">
|
|
||||||
<div class="level-item is-flex-grow-0">
|
|
||||||
<a
|
|
||||||
class="button is-white is-small"
|
|
||||||
:class="{ 'has-text-grey-light': !output.selected }"
|
|
||||||
@click="set_enabled"
|
|
||||||
>
|
|
||||||
<mdicon
|
|
||||||
class="icon"
|
|
||||||
:name="type_class"
|
|
||||||
size="18"
|
|
||||||
:title="output.type"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="level-item">
|
|
||||||
<div class="is-flex-grow-1">
|
|
||||||
<p
|
|
||||||
class="heading"
|
|
||||||
:class="{ 'has-text-grey-light': !output.selected }"
|
|
||||||
v-text="output.name"
|
|
||||||
/>
|
|
||||||
<control-slider
|
|
||||||
v-model:value="volume"
|
|
||||||
:disabled="!output.selected"
|
|
||||||
:max="100"
|
|
||||||
:cursor="cursor"
|
|
||||||
@change="change_volume"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import ControlSlider from '@/components/ControlSlider.vue'
|
|
||||||
import { mdiCancel } from '@mdi/js'
|
|
||||||
import webapi from '@/webapi'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'NavbarItemOutput',
|
|
||||||
components: {
|
|
||||||
ControlSlider
|
|
||||||
},
|
|
||||||
props: { output: { required: true, type: Object } },
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
cursor: mdiCancel,
|
|
||||||
volume: this.output.selected ? this.output.volume : 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
type_class() {
|
|
||||||
if (this.output.type.startsWith('AirPlay')) {
|
|
||||||
return 'cast-variant'
|
|
||||||
} else if (this.output.type === 'Chromecast') {
|
|
||||||
return 'cast'
|
|
||||||
} else if (this.output.type === 'fifo') {
|
|
||||||
return 'pipe'
|
|
||||||
}
|
|
||||||
return 'server'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
output() {
|
|
||||||
this.volume = this.output.volume
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
change_volume() {
|
|
||||||
webapi.player_output_volume(this.output.id, this.volume)
|
|
||||||
},
|
|
||||||
|
|
||||||
set_enabled() {
|
|
||||||
const values = {
|
|
||||||
selected: !this.output.selected
|
|
||||||
}
|
|
||||||
webapi.output_update(this.output.id, values)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,135 +1,151 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav
|
<nav class="navbar is-light is-fixed-top" :style="zindex">
|
||||||
class="navbar is-light is-fixed-top"
|
<div class="navbar-brand is-flex-grow-1">
|
||||||
:style="zindex"
|
<control-link
|
||||||
role="navigation"
|
|
||||||
aria-label="main navigation"
|
|
||||||
>
|
|
||||||
<div class="navbar-brand">
|
|
||||||
<navbar-item-link
|
|
||||||
v-if="settingsStore.show_menu_item_playlists"
|
v-if="settingsStore.show_menu_item_playlists"
|
||||||
|
class="navbar-item"
|
||||||
:to="{ name: 'playlists' }"
|
:to="{ name: 'playlists' }"
|
||||||
>
|
>
|
||||||
<mdicon class="icon" name="music-box-multiple" size="16" />
|
<mdicon class="icon" name="music-box-multiple" size="16" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link
|
<control-link
|
||||||
v-if="settingsStore.show_menu_item_music"
|
v-if="settingsStore.show_menu_item_music"
|
||||||
|
class="navbar-item"
|
||||||
:to="{ name: 'music' }"
|
:to="{ name: 'music' }"
|
||||||
>
|
>
|
||||||
<mdicon class="icon" name="music" size="16" />
|
<mdicon class="icon" name="music" size="16" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link
|
<control-link
|
||||||
v-if="settingsStore.show_menu_item_podcasts"
|
v-if="settingsStore.show_menu_item_podcasts"
|
||||||
|
class="navbar-item"
|
||||||
:to="{ name: 'podcasts' }"
|
:to="{ name: 'podcasts' }"
|
||||||
>
|
>
|
||||||
<mdicon class="icon" name="microphone" size="16" />
|
<mdicon class="icon" name="microphone" size="16" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link
|
<control-link
|
||||||
v-if="settingsStore.show_menu_item_audiobooks"
|
v-if="settingsStore.show_menu_item_audiobooks"
|
||||||
|
class="navbar-item"
|
||||||
:to="{ name: 'audiobooks' }"
|
:to="{ name: 'audiobooks' }"
|
||||||
>
|
>
|
||||||
<mdicon class="icon" name="book-open-variant" size="16" />
|
<mdicon class="icon" name="book-open-variant" size="16" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link
|
<control-link
|
||||||
v-if="settingsStore.show_menu_item_radio"
|
v-if="settingsStore.show_menu_item_radio"
|
||||||
|
class="navbar-item"
|
||||||
:to="{ name: 'radio' }"
|
:to="{ name: 'radio' }"
|
||||||
>
|
>
|
||||||
<mdicon class="icon" name="radio" size="16" />
|
<mdicon class="icon" name="radio" size="16" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link
|
<control-link
|
||||||
v-if="settingsStore.show_menu_item_files"
|
v-if="settingsStore.show_menu_item_files"
|
||||||
|
class="navbar-item"
|
||||||
:to="{ name: 'files' }"
|
:to="{ name: 'files' }"
|
||||||
>
|
>
|
||||||
<mdicon class="icon" name="folder-open" size="16" />
|
<mdicon class="icon" name="folder-open" size="16" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link
|
<control-link
|
||||||
v-if="settingsStore.show_menu_item_search"
|
v-if="settingsStore.show_menu_item_search"
|
||||||
|
class="navbar-item"
|
||||||
:to="{ name: searchStore.search_source }"
|
:to="{ name: searchStore.search_source }"
|
||||||
>
|
>
|
||||||
<mdicon class="icon" name="magnify" size="16" />
|
<mdicon class="icon" name="magnify" size="16" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<div
|
<a
|
||||||
class="navbar-burger"
|
class="navbar-item ml-auto"
|
||||||
:class="{ 'is-active': show_burger_menu }"
|
@click="uiStore.show_burger_menu = !uiStore.show_burger_menu"
|
||||||
@click="show_burger_menu = !show_burger_menu"
|
|
||||||
>
|
>
|
||||||
<span />
|
<mdicon
|
||||||
<span />
|
class="icon"
|
||||||
<span />
|
:name="uiStore.show_burger_menu ? 'close' : 'menu'"
|
||||||
</div>
|
/>
|
||||||
</div>
|
</a>
|
||||||
<div class="navbar-menu" :class="{ 'is-active': show_burger_menu }">
|
<div
|
||||||
<div class="navbar-start" />
|
class="dropdown is-right"
|
||||||
<div class="navbar-end">
|
:class="{ 'is-active': uiStore.show_burger_menu }"
|
||||||
<!-- Burger menu entries -->
|
>
|
||||||
<div
|
<div class="dropdown-menu">
|
||||||
class="navbar-item has-dropdown is-hoverable"
|
<div class="dropdown-content">
|
||||||
:class="{ 'is-active': show_settings_menu }"
|
<control-link class="dropdown-item" :to="{ name: 'playlists' }">
|
||||||
@click="on_click_outside_settings"
|
<span class="icon-text">
|
||||||
>
|
<mdicon class="icon" name="music-box-multiple" size="16" />
|
||||||
<a class="navbar-item is-arrowless is-hidden-touch">
|
</span>
|
||||||
<mdicon class="icon" name="menu" size="24" />
|
|
||||||
</a>
|
|
||||||
<div class="navbar-dropdown is-right">
|
|
||||||
<navbar-item-link :to="{ name: 'playlists' }">
|
|
||||||
<mdicon class="icon" name="music-box-multiple" size="16" />
|
|
||||||
<b v-text="$t('navigation.playlists')" />
|
<b v-text="$t('navigation.playlists')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link :to="{ name: 'music' }">
|
<control-link class="dropdown-item" :to="{ name: 'music' }">
|
||||||
<mdicon class="icon" name="music" size="16" />
|
<span class="icon-text">
|
||||||
|
<mdicon class="icon" name="music" size="16" />
|
||||||
|
</span>
|
||||||
<b v-text="$t('navigation.music')" />
|
<b v-text="$t('navigation.music')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link :to="{ name: 'music-artists' }">
|
<control-link class="dropdown-item" :to="{ name: 'music-artists' }">
|
||||||
<span class="pl-5" v-text="$t('navigation.artists')" />
|
<span class="pl-5" v-text="$t('navigation.artists')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link :to="{ name: 'music-albums' }">
|
<control-link class="dropdown-item" :to="{ name: 'music-albums' }">
|
||||||
<span class="pl-5" v-text="$t('navigation.albums')" />
|
<span class="pl-5" v-text="$t('navigation.albums')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link :to="{ name: 'music-genres' }">
|
<control-link class="dropdown-item" :to="{ name: 'music-genres' }">
|
||||||
<span class="pl-5" v-text="$t('navigation.genres')" />
|
<span class="pl-5" v-text="$t('navigation.genres')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link
|
<control-link
|
||||||
v-if="spotify_enabled"
|
v-if="spotify_enabled"
|
||||||
|
class="dropdown-item"
|
||||||
:to="{ name: 'music-spotify' }"
|
:to="{ name: 'music-spotify' }"
|
||||||
>
|
>
|
||||||
<span class="pl-5" v-text="$t('navigation.spotify')" />
|
<span class="pl-5" v-text="$t('navigation.spotify')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link :to="{ name: 'podcasts' }">
|
<control-link class="dropdown-item" :to="{ name: 'podcasts' }">
|
||||||
<mdicon class="icon" name="microphone" size="16" />
|
<span class="icon-text">
|
||||||
|
<mdicon class="icon" name="microphone" size="16" />
|
||||||
|
</span>
|
||||||
<b v-text="$t('navigation.podcasts')" />
|
<b v-text="$t('navigation.podcasts')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link :to="{ name: 'audiobooks' }">
|
<control-link class="dropdown-item" :to="{ name: 'audiobooks' }">
|
||||||
<mdicon class="icon" name="book-open-variant" size="16" />
|
<span class="icon-text">
|
||||||
|
<mdicon class="icon" name="book-open-variant" size="16" />
|
||||||
|
</span>
|
||||||
<b v-text="$t('navigation.audiobooks')" />
|
<b v-text="$t('navigation.audiobooks')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link :to="{ name: 'radio' }">
|
<control-link class="dropdown-item" :to="{ name: 'radio' }">
|
||||||
<mdicon class="icon" name="radio" size="16" />
|
<span class="icon-text">
|
||||||
|
<mdicon class="icon" name="radio" size="16" />
|
||||||
|
</span>
|
||||||
<b v-text="$t('navigation.radio')" />
|
<b v-text="$t('navigation.radio')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link :to="{ name: 'files' }">
|
<control-link class="dropdown-item" :to="{ name: 'files' }">
|
||||||
<mdicon class="icon" name="folder-open" size="16" />
|
<span class="icon-text">
|
||||||
|
<mdicon class="icon" name="folder-open" size="16" />
|
||||||
|
</span>
|
||||||
<b v-text="$t('navigation.files')" />
|
<b v-text="$t('navigation.files')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<navbar-item-link :to="{ name: searchStore.search_source }">
|
<control-link
|
||||||
<mdicon class="icon" name="magnify" size="16" />
|
class="dropdown-item"
|
||||||
|
:to="{ name: searchStore.search_source }"
|
||||||
|
>
|
||||||
|
<span class="icon-text">
|
||||||
|
<mdicon class="icon" name="magnify" size="16" />
|
||||||
|
</span>
|
||||||
<b v-text="$t('navigation.search')" />
|
<b v-text="$t('navigation.search')" />
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<hr class="my-3" />
|
<hr class="my-3" />
|
||||||
<navbar-item-link :to="{ name: 'settings-webinterface' }">
|
<control-link
|
||||||
|
class="dropdown-item"
|
||||||
|
:to="{ name: 'settings-webinterface' }"
|
||||||
|
>
|
||||||
{{ $t('navigation.settings') }}
|
{{ $t('navigation.settings') }}
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
<a
|
<a
|
||||||
class="navbar-item"
|
class="dropdown-item"
|
||||||
@click.stop.prevent="open_update_dialog()"
|
@click.stop.prevent="open_update_dialog()"
|
||||||
v-text="$t('navigation.update-library')"
|
v-text="$t('navigation.update-library')"
|
||||||
/>
|
/>
|
||||||
<navbar-item-link :to="{ name: 'about' }">
|
<control-link class="dropdown-item" :to="{ name: 'about' }">
|
||||||
{{ $t('navigation.about') }}
|
{{ $t('navigation.about') }}
|
||||||
</navbar-item-link>
|
</control-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-show="show_settings_menu"
|
v-show="show_settings_menu"
|
||||||
class="is-overlay"
|
class="is-overlay"
|
||||||
@ -139,7 +155,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import NavbarItemLink from '@/components/NavbarItemLink.vue'
|
import ControlLink from '@/components/ControlLink.vue'
|
||||||
import { useSearchStore } from '@/stores/search'
|
import { useSearchStore } from '@/stores/search'
|
||||||
import { useServicesStore } from '@/stores/services'
|
import { useServicesStore } from '@/stores/services'
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
import { useSettingsStore } from '@/stores/settings'
|
||||||
@ -147,7 +163,7 @@ import { useUIStore } from '@/stores/ui'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NavbarTop',
|
name: 'NavbarTop',
|
||||||
components: { NavbarItemLink },
|
components: { ControlLink },
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
@ -165,22 +181,6 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
show_burger_menu: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.show_burger_menu
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.show_burger_menu = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
show_update_dialog: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.show_update_dialog
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.show_update_dialog = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
},
|
},
|
||||||
@ -203,12 +203,10 @@ export default {
|
|||||||
this.show_settings_menu = !this.show_settings_menu
|
this.show_settings_menu = !this.show_settings_menu
|
||||||
},
|
},
|
||||||
open_update_dialog() {
|
open_update_dialog() {
|
||||||
this.show_update_dialog = true
|
this.uiStore.show_update_dialog = true
|
||||||
this.show_settings_menu = false
|
this.show_settings_menu = false
|
||||||
this.show_burger_menu = false
|
this.uiStore.show_burger_menu = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="field">
|
|
||||||
<input
|
|
||||||
:id="setting.name"
|
|
||||||
v-model="setting.value"
|
|
||||||
type="checkbox"
|
|
||||||
class="switch is-rounded mr-2"
|
|
||||||
@change="update_setting"
|
|
||||||
/>
|
|
||||||
<label class="pt-0" :for="setting.name">
|
|
||||||
<slot name="label" />
|
|
||||||
</label>
|
|
||||||
<i
|
|
||||||
class="is-size-7"
|
|
||||||
:class="{ 'has-text-info': is_success, 'has-text-danger': is_error }"
|
|
||||||
v-text="info"
|
|
||||||
/>
|
|
||||||
<p v-if="$slots['info']" class="help">
|
|
||||||
<slot name="info" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
|
||||||
import webapi from '@/webapi'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'SettingsCheckbox',
|
|
||||||
props: {
|
|
||||||
category: { required: true, type: String },
|
|
||||||
name: { required: true, type: String }
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
|
||||||
return {
|
|
||||||
settingsStore: useSettingsStore()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
statusUpdate: '',
|
|
||||||
timerDelay: 2000,
|
|
||||||
timerId: -1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
info() {
|
|
||||||
if (this.is_success) {
|
|
||||||
return this.$t('setting.saved')
|
|
||||||
} else if (this.is_error) {
|
|
||||||
return this.$t('setting.not-saved')
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
},
|
|
||||||
is_error() {
|
|
||||||
return this.statusUpdate === 'error'
|
|
||||||
},
|
|
||||||
is_success() {
|
|
||||||
return this.statusUpdate === 'success'
|
|
||||||
},
|
|
||||||
setting() {
|
|
||||||
const setting = this.settingsStore.setting(this.category, this.name)
|
|
||||||
if (!setting) {
|
|
||||||
return {
|
|
||||||
category: this.category,
|
|
||||||
name: this.name,
|
|
||||||
value: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return setting
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
clear_status() {
|
|
||||||
if (this.is_error) {
|
|
||||||
this.setting.value = !this.setting.value
|
|
||||||
}
|
|
||||||
this.statusUpdate = ''
|
|
||||||
},
|
|
||||||
update_setting() {
|
|
||||||
this.timerId = -1
|
|
||||||
const setting = {
|
|
||||||
category: this.category,
|
|
||||||
name: this.name,
|
|
||||||
value: this.setting.value
|
|
||||||
}
|
|
||||||
webapi
|
|
||||||
.settings_update(this.category, setting)
|
|
||||||
.then(() => {
|
|
||||||
this.settingsStore.update(setting)
|
|
||||||
this.statusUpdate = 'success'
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.statusUpdate = 'error'
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.timerId = window.setTimeout(this.clear_status, this.timerDelay)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,120 +0,0 @@
|
|||||||
<template>
|
|
||||||
<fieldset :disabled="disabled">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label has-text-weight-normal">
|
|
||||||
<slot name="label" />
|
|
||||||
<i
|
|
||||||
class="is-size-7"
|
|
||||||
:class="{ 'has-text-info': is_success, 'has-text-danger': is_error }"
|
|
||||||
v-text="info"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<div class="control">
|
|
||||||
<input
|
|
||||||
ref="setting"
|
|
||||||
class="column input is-one-fifth"
|
|
||||||
inputmode="numeric"
|
|
||||||
min="0"
|
|
||||||
:placeholder="placeholder"
|
|
||||||
:value="setting.value"
|
|
||||||
@input="set_update_timer"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p v-if="$slots['info']" class="help">
|
|
||||||
<slot name="info" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
|
||||||
import webapi from '@/webapi'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'SettingsIntfield',
|
|
||||||
props: {
|
|
||||||
category: { required: true, type: String },
|
|
||||||
disabled: Boolean,
|
|
||||||
name: { required: true, type: String },
|
|
||||||
placeholder: { default: '', type: String }
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
|
||||||
return {
|
|
||||||
settingsStore: useSettingsStore()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
statusUpdate: '',
|
|
||||||
timerDelay: 2000,
|
|
||||||
timerId: -1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
info() {
|
|
||||||
if (this.statusUpdate === 'success') {
|
|
||||||
return this.$t('setting.saved')
|
|
||||||
} else if (this.statusUpdate === 'error') {
|
|
||||||
return this.$t('setting.not-saved')
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
},
|
|
||||||
is_error() {
|
|
||||||
return this.statusUpdate === 'error'
|
|
||||||
},
|
|
||||||
is_success() {
|
|
||||||
return this.statusUpdate === 'success'
|
|
||||||
},
|
|
||||||
setting() {
|
|
||||||
return this.settingsStore.setting(this.category, this.name)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
clear_status() {
|
|
||||||
this.statusUpdate = ''
|
|
||||||
},
|
|
||||||
set_update_timer(event) {
|
|
||||||
event.target.value = event.target.value.replace(/[^0-9]/gu, '')
|
|
||||||
if (this.timerId > 0) {
|
|
||||||
window.clearTimeout(this.timerId)
|
|
||||||
this.timerId = -1
|
|
||||||
}
|
|
||||||
this.statusUpdate = ''
|
|
||||||
this.timerId = window.setTimeout(this.update_setting, this.timerDelay)
|
|
||||||
},
|
|
||||||
update_setting() {
|
|
||||||
this.timerId = -1
|
|
||||||
const newValue = parseInt(this.$refs.setting.value, 10)
|
|
||||||
if (isNaN(newValue) || newValue === this.value) {
|
|
||||||
this.statusUpdate = ''
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const setting = {
|
|
||||||
category: this.category,
|
|
||||||
name: this.name,
|
|
||||||
value: newValue
|
|
||||||
}
|
|
||||||
webapi
|
|
||||||
.settings_update(this.category, setting)
|
|
||||||
.then(() => {
|
|
||||||
this.settingsStore.update(setting)
|
|
||||||
this.statusUpdate = 'success'
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.statusUpdate = 'error'
|
|
||||||
this.$refs.setting.value = this.value
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.timerId = window.setTimeout(this.clear_status, this.timerDelay)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,121 +0,0 @@
|
|||||||
<template>
|
|
||||||
<fieldset :disabled="disabled">
|
|
||||||
<div class="field">
|
|
||||||
<label class="label has-text-weight-normal">
|
|
||||||
<slot name="label" />
|
|
||||||
<i
|
|
||||||
class="is-size-7"
|
|
||||||
:class="{ 'has-text-info': is_success, 'has-text-danger': is_error }"
|
|
||||||
v-text="info"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
<div class="control">
|
|
||||||
<input
|
|
||||||
ref="setting"
|
|
||||||
class="input"
|
|
||||||
type="text"
|
|
||||||
:placeholder="placeholder"
|
|
||||||
:value="setting.value"
|
|
||||||
@input="set_update_timer"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p v-if="$slots['info']" class="help">
|
|
||||||
<slot name="info" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
|
||||||
import webapi from '@/webapi'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'SettingsTextfield',
|
|
||||||
props: {
|
|
||||||
category: { required: true, type: String },
|
|
||||||
disabled: Boolean,
|
|
||||||
name: { required: true, type: String },
|
|
||||||
placeholder: { default: '', type: String }
|
|
||||||
},
|
|
||||||
|
|
||||||
setup() {
|
|
||||||
return {
|
|
||||||
settingsStore: useSettingsStore()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
statusUpdate: '',
|
|
||||||
timerDelay: 2000,
|
|
||||||
timerId: -1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
info() {
|
|
||||||
if (this.statusUpdate === 'success') {
|
|
||||||
return this.$t('setting.saved')
|
|
||||||
} else if (this.statusUpdate === 'error') {
|
|
||||||
return this.$t('setting.not-saved')
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
},
|
|
||||||
is_error() {
|
|
||||||
return this.statusUpdate === 'error'
|
|
||||||
},
|
|
||||||
is_success() {
|
|
||||||
return this.statusUpdate === 'success'
|
|
||||||
},
|
|
||||||
setting() {
|
|
||||||
return this.settingsStore.setting(this.category, this.name)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
clear_status() {
|
|
||||||
this.statusUpdate = ''
|
|
||||||
},
|
|
||||||
set_update_timer() {
|
|
||||||
if (this.timerId > 0) {
|
|
||||||
window.clearTimeout(this.timerId)
|
|
||||||
this.timerId = -1
|
|
||||||
}
|
|
||||||
this.statusUpdate = ''
|
|
||||||
const newValue = this.$refs.setting.value
|
|
||||||
if (newValue !== this.value) {
|
|
||||||
this.timerId = window.setTimeout(this.update_setting, this.timerDelay)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
update_setting() {
|
|
||||||
this.timerId = -1
|
|
||||||
const newValue = this.$refs.setting.value
|
|
||||||
if (newValue === this.value) {
|
|
||||||
this.statusUpdate = ''
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const setting = {
|
|
||||||
category: this.category,
|
|
||||||
name: this.name,
|
|
||||||
value: newValue
|
|
||||||
}
|
|
||||||
webapi
|
|
||||||
.settings_update(this.category, setting)
|
|
||||||
.then(() => {
|
|
||||||
this.settingsStore.update(setting)
|
|
||||||
this.statusUpdate = 'success'
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.statusUpdate = 'error'
|
|
||||||
this.$refs.setting.value = this.value
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.timerId = window.setTimeout(this.clear_status, this.timerDelay)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style></style>
|
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="section fd-tabs-section">
|
<section class="section tabs-section">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
<div class="column is-four-fifths">
|
<div class="column is-four-fifths">
|
||||||
@ -67,5 +67,3 @@ export default {
|
|||||||
name: 'TabsAudiobooks'
|
name: 'TabsAudiobooks'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="section fd-tabs-section">
|
<section class="section tabs-section">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
<div class="column is-four-fifths">
|
<div class="column is-four-fifths">
|
||||||
@ -129,5 +129,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -53,5 +53,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="section fd-tabs-section">
|
<section class="section tabs-section">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
<div class="column is-four-fifths">
|
<div class="column is-four-fifths">
|
||||||
@ -64,5 +64,3 @@ export default {
|
|||||||
name: 'TabsSettings'
|
name: 'TabsSettings'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -32,7 +32,7 @@ export const filters = {
|
|||||||
.toLocaleString(DateTime.DATETIME_MED)
|
.toLocaleString(DateTime.DATETIME_MED)
|
||||||
},
|
},
|
||||||
durationInDays(value) {
|
durationInDays(value) {
|
||||||
const minutes = Math.floor(value / 60000)
|
const minutes = Math.floor(value / 60)
|
||||||
if (minutes > 1440) {
|
if (minutes > 1440) {
|
||||||
return Duration.fromObject({ minutes })
|
return Duration.fromObject({ minutes })
|
||||||
.shiftTo('days', 'hours', 'minutes')
|
.shiftTo('days', 'hours', 'minutes')
|
||||||
@ -53,6 +53,6 @@ export const filters = {
|
|||||||
},
|
},
|
||||||
timeFromNow(value) {
|
timeFromNow(value) {
|
||||||
const diff = DateTime.now().diff(DateTime.fromISO(value))
|
const diff = DateTime.now().diff(DateTime.fromISO(value))
|
||||||
return this.durationInDays(diff.as('milliseconds'))
|
return this.durationInDays(diff.as('seconds'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,6 +241,7 @@
|
|||||||
"compiled-with": "Compiliert mit Unterstützung von {options}.",
|
"compiled-with": "Compiliert mit Unterstützung von {options}.",
|
||||||
"library": "Bibliothek",
|
"library": "Bibliothek",
|
||||||
"more": "mehr",
|
"more": "mehr",
|
||||||
|
"name": "Name",
|
||||||
"total-playtime": "Gesamte Spielzeit",
|
"total-playtime": "Gesamte Spielzeit",
|
||||||
"tracks": "Tracks",
|
"tracks": "Tracks",
|
||||||
"update": "Neu einlesen",
|
"update": "Neu einlesen",
|
||||||
@ -407,8 +408,8 @@
|
|||||||
"count": "{count} Track|{count} Track|{count} Tracks",
|
"count": "{count} Track|{count} Track|{count} Tracks",
|
||||||
"edit": "Bearbeiten",
|
"edit": "Bearbeiten",
|
||||||
"hide-previous": "Vorherige verbergen",
|
"hide-previous": "Vorherige verbergen",
|
||||||
"title": "Warteschlange",
|
"save": "Speichern",
|
||||||
"save": "Speichern"
|
"title": "Warteschlange"
|
||||||
},
|
},
|
||||||
"radio": {
|
"radio": {
|
||||||
"count": "{count} Station|{count} Station|{count} Stationen",
|
"count": "{count} Station|{count} Station|{count} Stationen",
|
||||||
@ -445,6 +446,7 @@
|
|||||||
"discogs": "Discogs",
|
"discogs": "Discogs",
|
||||||
"explanation-1": "OwnTone verarbeitet PNG- und JPEG-Artwork, welches in einer eigenen Datei in der Bibliothek, in die Dateien eingebettet oder online von Radiostationen bereitgestellt werden kann.",
|
"explanation-1": "OwnTone verarbeitet PNG- und JPEG-Artwork, welches in einer eigenen Datei in der Bibliothek, in die Dateien eingebettet oder online von Radiostationen bereitgestellt werden kann.",
|
||||||
"explanation-2": "Zusätzlich kann auf folgende Artwork-Anbieter zugegriffen werden:",
|
"explanation-2": "Zusätzlich kann auf folgende Artwork-Anbieter zugegriffen werden:",
|
||||||
|
"show-coverart": "Zeige Cover-Artwork in der Albumliste",
|
||||||
"spotify": "Spotify",
|
"spotify": "Spotify",
|
||||||
"streaming": "Bereitgestellte Artwork von Radiostationen ignorieren"
|
"streaming": "Bereitgestellte Artwork von Radiostationen ignorieren"
|
||||||
},
|
},
|
||||||
@ -460,7 +462,6 @@
|
|||||||
"verify": "Verifizieren"
|
"verify": "Verifizieren"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"album-lists": "Album-Listen",
|
|
||||||
"audiobooks": "Hörbücher",
|
"audiobooks": "Hörbücher",
|
||||||
"files": "Dateien",
|
"files": "Dateien",
|
||||||
"genres": "Genres",
|
"genres": "Genres",
|
||||||
@ -473,17 +474,16 @@
|
|||||||
"playlists": "Playlisten",
|
"playlists": "Playlisten",
|
||||||
"podcasts": "Podcasts",
|
"podcasts": "Podcasts",
|
||||||
"radio": "Radio",
|
"radio": "Radio",
|
||||||
"recently-added-page-info": "Beschränkte die Zahl der Alben auf der \"kürzlich hinzugefügt\"-Seite",
|
"recently-added-page-info": "Beschränkte die Zahl der Alben",
|
||||||
"recently-added-page": "Kürzlich hinzugefügt-Seite",
|
"recently-added-page": "Kürzlich hinzugefügt-Seite",
|
||||||
"search": "Suche",
|
"search": "Suche",
|
||||||
"show-composer-genres-info-1": "Komma-separierte Liste der Genres, wo der Komponist auf der \"Aktuell läuft\"-Seite angezeigt werden soll",
|
"show-composer-genres-info-1": "Komma getrennte Liste der Genres, für die der Komponist angezeigt werden soll.",
|
||||||
"show-composer-genres-info-2": "Leer lassen, um ihn immer anzuzeigen.",
|
"show-composer-genres-info-2": "Leer lassen, um den Komponisten immer anzuzeigen.",
|
||||||
"show-composer-genres-info-3": "Der Genre-Tag des aktuellen Tracks wird abgeglichen als Teil-String des Genre-Tags. Z.B. \"classical, soundtrack\" wird den Komponisten beim Genre-Tag \"Contemporary Classical\" anzeigen",
|
"show-composer-genres-info-3": "Der Genre-Tag des aktuellen Tracks wird abgeglichen als Teil-String des Genre-Tags. Z.B. \"classical, soundtrack\" wird den Komponisten beim Genre-Tag \"Contemporary Classical\" anzeigen",
|
||||||
"show-composer-genres": "Zeige den Komponisten für die aufgelisteten Genres an",
|
"show-composer-genres": "Zeige den Komponisten für die aufgelisteten Genres an",
|
||||||
"show-composer-info": "Wenn aktiviert, wird der Komponist auf der \"Aktuell läuft\"-Seite angezeigt.",
|
"show-composer-info": "Wenn aktiviert, wird der Komponist angezeigt.",
|
||||||
"show-composer": "Komponisten anzeigen",
|
"show-composer": "Komponisten anzeigen",
|
||||||
"show-coverart": "Zeige Cover-Artwork in der Albumliste",
|
"show-path": "Dateipfad anzeigen"
|
||||||
"show-path": "Dateipfad auf der \"Aktuell läuft\"-Seite anzeigen"
|
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"lastfm": {
|
"lastfm": {
|
||||||
@ -495,8 +495,7 @@
|
|||||||
"spotify": {
|
"spotify": {
|
||||||
"no-support": "OwnTone wurde entweder ohne Unterstützung für Spotify erstellt oder libspotify ist nicht installiert.",
|
"no-support": "OwnTone wurde entweder ohne Unterstützung für Spotify erstellt oder libspotify ist nicht installiert.",
|
||||||
"logged-as": "Angemeldet als ",
|
"logged-as": "Angemeldet als ",
|
||||||
"requirements": "Spotify Premium Abo erforderlich.",
|
"requirements": "Spotify Premium Abo erforderlich. Zugriff auf die Spotify Web-Api ermöglicht scannen der Spotify-Blibliothek. Erforderliche scopes sind: ",
|
||||||
"scopes": "Zugriff auf die Spotify Web-Api ermöglicht scannen der Spotify-Blibliothek. Erforderliche scopes sind: ",
|
|
||||||
"user": "Zugriff gestattet für ",
|
"user": "Zugriff gestattet für ",
|
||||||
"authorize": "Authorisiere Web-API-Zugriff",
|
"authorize": "Authorisiere Web-API-Zugriff",
|
||||||
"grant-access": "Zugriff auf die Spotify Web-API gestatten",
|
"grant-access": "Zugriff auf die Spotify Web-API gestatten",
|
||||||
@ -572,10 +571,6 @@
|
|||||||
"toggle-lyrics": "Liedtexte anzeigen/verbergen"
|
"toggle-lyrics": "Liedtexte anzeigen/verbergen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"setting": {
|
|
||||||
"not-saved": " (Fehler beim Speichern der Einstellungen)",
|
|
||||||
"saved": " (Einstellungen gesichert)"
|
|
||||||
},
|
|
||||||
"server": {
|
"server": {
|
||||||
"connection-failed": "Fehler bei Verbindung zum OwnTone-Server",
|
"connection-failed": "Fehler bei Verbindung zum OwnTone-Server",
|
||||||
"request-failed": "Anfrage gescheitert (Status: {status} {cause} {url})",
|
"request-failed": "Anfrage gescheitert (Status: {status} {cause} {url})",
|
||||||
|
@ -241,6 +241,7 @@
|
|||||||
"compiled-with": "Compiled with support for {options}.",
|
"compiled-with": "Compiled with support for {options}.",
|
||||||
"library": "Library",
|
"library": "Library",
|
||||||
"more": "more",
|
"more": "more",
|
||||||
|
"name": "Name",
|
||||||
"total-playtime": "Total playtime",
|
"total-playtime": "Total playtime",
|
||||||
"tracks": "Tracks",
|
"tracks": "Tracks",
|
||||||
"update": "Update",
|
"update": "Update",
|
||||||
@ -407,8 +408,8 @@
|
|||||||
"count": "{count} track|{count} track|{count} tracks",
|
"count": "{count} track|{count} track|{count} tracks",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"hide-previous": "Hide previous",
|
"hide-previous": "Hide previous",
|
||||||
"title": "Queue",
|
"save": "Save",
|
||||||
"save": "Save"
|
"title": "Queue"
|
||||||
},
|
},
|
||||||
"radio": {
|
"radio": {
|
||||||
"count": "{count} station|{count} station|{count} stations",
|
"count": "{count} station|{count} station|{count} stations",
|
||||||
@ -473,16 +474,16 @@
|
|||||||
"playlists": "Playlists",
|
"playlists": "Playlists",
|
||||||
"podcasts": "Podcasts",
|
"podcasts": "Podcasts",
|
||||||
"radio": "Radio",
|
"radio": "Radio",
|
||||||
"recently-added-page-info": "Limit the number of albums shown on the \"Recently Added\" page",
|
"recently-added-page-info": "Limit the number of albums displayed",
|
||||||
"recently-added-page": "Recently added page",
|
"recently-added-page": "Recently added page",
|
||||||
"search": "Search",
|
"search": "Search",
|
||||||
"show-composer-genres-info-1": "Comma separated list of genres the composer should be displayed on the \"Now playing page\"",
|
"show-composer-genres-info-1": "Comma-separated list of genres, for which the composer must be displayed",
|
||||||
"show-composer-genres-info-2": "Leave empty to always show the composer.",
|
"show-composer-genres-info-2": "Leave empty to always show the composer",
|
||||||
"show-composer-genres-info-3": "The genre tag of the current track is matched by checking, if one of the defined genres are included. For example setting to \"classical, soundtrack\" will show the composer for tracks with a genre tag of \"Contemporary Classical\"",
|
"show-composer-genres-info-3": "The genre tag of the current track is matched by checking, if one of the defined genres are included. For example setting to \"classical, soundtrack\" will show the composer for tracks with a genre tag of \"Contemporary Classical\"",
|
||||||
"show-composer-genres": "Show composer only for listed genres",
|
"show-composer-genres": "Show composer only for listed genres",
|
||||||
"show-composer-info": "If enabled the composer of the current playing track is shown on the \"Now playing page\"",
|
"show-composer-info": "If enabled, the composer of the current playing track is displayed",
|
||||||
"show-composer": "Show composer",
|
"show-composer": "Show composer",
|
||||||
"show-path": "Show filepath on the \"Now playing\" page"
|
"show-path": "Show filepath"
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"lastfm": {
|
"lastfm": {
|
||||||
@ -494,8 +495,7 @@
|
|||||||
"spotify": {
|
"spotify": {
|
||||||
"no-support": "OwnTone was either built without support for Spotify or libspotify is not installed.",
|
"no-support": "OwnTone was either built without support for Spotify or libspotify is not installed.",
|
||||||
"logged-as": "Logged in as ",
|
"logged-as": "Logged in as ",
|
||||||
"requirements": "You must have a Spotify premium account.",
|
"requirements": "You must have a Spotify premium account. Access to the Spotify Web API enables scanning of your Spotify library. Required scopes are: ",
|
||||||
"scopes": "Access to the Spotify Web API enables scanning of your Spotify library. Required scopes are: ",
|
|
||||||
"user": "Access granted for ",
|
"user": "Access granted for ",
|
||||||
"authorize": "Authorize Web API access",
|
"authorize": "Authorize Web API access",
|
||||||
"grant-access": "Grant access to the Spotify Web API",
|
"grant-access": "Grant access to the Spotify Web API",
|
||||||
@ -571,10 +571,6 @@
|
|||||||
"toggle-lyrics": "Toggle lyrics"
|
"toggle-lyrics": "Toggle lyrics"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"setting": {
|
|
||||||
"not-saved": " (error saving setting)",
|
|
||||||
"saved": " (setting saved)"
|
|
||||||
},
|
|
||||||
"server": {
|
"server": {
|
||||||
"connection-failed": "Failed to connect to OwnTone server",
|
"connection-failed": "Failed to connect to OwnTone server",
|
||||||
"request-failed": "Request failed (status: {status} {cause} {url})",
|
"request-failed": "Request failed (status: {status} {cause} {url})",
|
||||||
|
@ -241,6 +241,7 @@
|
|||||||
"compiled-with": "Compilé avec les options {options}.",
|
"compiled-with": "Compilé avec les options {options}.",
|
||||||
"library": "Bibliothèque",
|
"library": "Bibliothèque",
|
||||||
"more": "plus",
|
"more": "plus",
|
||||||
|
"name": "Nom",
|
||||||
"total-playtime": "Durée totale de lecture",
|
"total-playtime": "Durée totale de lecture",
|
||||||
"tracks": "Pistes",
|
"tracks": "Pistes",
|
||||||
"update": "Actualiser",
|
"update": "Actualiser",
|
||||||
@ -407,8 +408,8 @@
|
|||||||
"count": "{count} piste|{count} piste|{count} pistes",
|
"count": "{count} piste|{count} piste|{count} pistes",
|
||||||
"edit": "Éditer",
|
"edit": "Éditer",
|
||||||
"hide-previous": "Masquer l’historique",
|
"hide-previous": "Masquer l’historique",
|
||||||
"queue": "File d’attente",
|
"save": "Enregistrer",
|
||||||
"save": "Enregistrer"
|
"title": "File d’attente"
|
||||||
},
|
},
|
||||||
"radio": {
|
"radio": {
|
||||||
"count": "{count} station|{count} station|{count} stations",
|
"count": "{count} station|{count} station|{count} stations",
|
||||||
@ -473,16 +474,16 @@
|
|||||||
"playlists": "Listes de lecture",
|
"playlists": "Listes de lecture",
|
||||||
"podcasts": "Podcasts",
|
"podcasts": "Podcasts",
|
||||||
"radio": "Radio",
|
"radio": "Radio",
|
||||||
"recently-added-page-info": "Limiter le nombre d’albums affichés dans la section « Ajouts récents »",
|
"recently-added-page-info": "Limiter le nombre d’albums affichés",
|
||||||
"recently-added-page": "Page « Ajouts récents »",
|
"recently-added-page": "Page « Ajouts récents »",
|
||||||
"search": "Recherche",
|
"search": "Recherche",
|
||||||
"show-composer-genres-info-1": "Liste des genres, séparés par des virgules, que le compositeur doit afficher sur la page « En cours de lecture ».",
|
"show-composer-genres-info-1": "Liste de genres séparés par des virgules pour lesquels le compositeur doit être affiché.",
|
||||||
"show-composer-genres-info-2": "Laissez vide pour toujours afficher le compositeur.",
|
"show-composer-genres-info-2": "Laissez vide pour toujours afficher le compositeur.",
|
||||||
"show-composer-genres-info-3": "L’étiquette de genre de la piste actuelle est comparée en vérifiant si l’un des genres définis est inclus. Par exemple, en choisissant \"classique, bande sonore\", le compositeur pour les pistes dont l’étiquette de genre est \"classique contemporain\" sera affiché.",
|
"show-composer-genres-info-3": "L’étiquette de genre de la piste actuelle est comparée en vérifiant si l’un des genres définis est inclus. Par exemple, en choisissant \"classique, bande sonore\", le compositeur pour les pistes dont l’étiquette de genre est \"classique contemporain\" sera affiché.",
|
||||||
"show-composer-genres": "Afficher le compositeur uniquement pour les genres listés",
|
"show-composer-genres": "Afficher le compositeur uniquement pour les genres listés",
|
||||||
"show-composer-info": "Si actif, le compositeur de la piste en cours de lecture est affiché sur la page « En cours de lecture »",
|
"show-composer-info": "Si actif, le compositeur de la piste en cours de lecture est affiché",
|
||||||
"show-composer": "Afficher le compositeur",
|
"show-composer": "Afficher le compositeur",
|
||||||
"show-path": "Afficher le chemin du fichier sur la page « En cours de lecture »"
|
"show-path": "Afficher le chemin du fichier"
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"lastfm": {
|
"lastfm": {
|
||||||
@ -494,8 +495,7 @@
|
|||||||
"spotify": {
|
"spotify": {
|
||||||
"no-support": "L’option Spotify n’est pas présente.",
|
"no-support": "L’option Spotify n’est pas présente.",
|
||||||
"logged-as": "Connecté en tant que ",
|
"logged-as": "Connecté en tant que ",
|
||||||
"requirements": "Vous devez posséder un compte Spotify Premium.",
|
"requirements": "Vous devez posséder un compte Spotify Premium. L’accès à l’API de Spotify permet l’analyse de votre bibliothèque Spotify. Les champs d’application requis sont les suivants :",
|
||||||
"scopes": "L’accès à l’API de Spotify permet l’analyse de votre bibliothèque Spotify. Les champs d’application requis sont les suivants :",
|
|
||||||
"user": "Accès autorisé pour ",
|
"user": "Accès autorisé pour ",
|
||||||
"authorize": "Autoriser l’accès à l’API",
|
"authorize": "Autoriser l’accès à l’API",
|
||||||
"grant-access": "Accordez l’accès à l’API de Spotify",
|
"grant-access": "Accordez l’accès à l’API de Spotify",
|
||||||
@ -571,10 +571,6 @@
|
|||||||
"toggle-lyrics": "Voir/Cacher les paroles"
|
"toggle-lyrics": "Voir/Cacher les paroles"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"setting": {
|
|
||||||
"not-saved": " (erreur à l’enregistrement du réglage)",
|
|
||||||
"saved": " (réglage enregistré)"
|
|
||||||
},
|
|
||||||
"server": {
|
"server": {
|
||||||
"connection-failed": "Échec de connexion au serveur",
|
"connection-failed": "Échec de connexion au serveur",
|
||||||
"request-failed": "La requête a échoué (status: {status} {cause} {url})",
|
"request-failed": "La requête a échoué (status: {status} {cause} {url})",
|
||||||
|
@ -241,6 +241,7 @@
|
|||||||
"compiled-with": "编译支持来自于 {options}",
|
"compiled-with": "编译支持来自于 {options}",
|
||||||
"library": "资料库",
|
"library": "资料库",
|
||||||
"more": "更多",
|
"more": "更多",
|
||||||
|
"name": "名称",
|
||||||
"total-playtime": "总播放时长",
|
"total-playtime": "总播放时长",
|
||||||
"tracks": "曲目总数",
|
"tracks": "曲目总数",
|
||||||
"update": "更新",
|
"update": "更新",
|
||||||
@ -407,8 +408,8 @@
|
|||||||
"count": "{count} 只曲目|{count} 只曲目",
|
"count": "{count} 只曲目|{count} 只曲目",
|
||||||
"edit": "编辑",
|
"edit": "编辑",
|
||||||
"hide-previous": "隐藏历史",
|
"hide-previous": "隐藏历史",
|
||||||
"title": "清单",
|
"save": "保存",
|
||||||
"save": "保存"
|
"title": "清单"
|
||||||
},
|
},
|
||||||
"radio": {
|
"radio": {
|
||||||
"count": "{count} 个电台|{count} 个电台",
|
"count": "{count} 个电台|{count} 个电台",
|
||||||
@ -473,16 +474,16 @@
|
|||||||
"playlists": "播放列表",
|
"playlists": "播放列表",
|
||||||
"podcasts": "播客",
|
"podcasts": "播客",
|
||||||
"radio": "广播电台",
|
"radio": "广播电台",
|
||||||
"recently-added-page-info": "限制“最近添加”页面上显示的专辑数量",
|
"recently-added-page-info": "限制显示的相册数量",
|
||||||
"recently-added-page": "“最近添加”页面",
|
"recently-added-page": "“最近添加”页面",
|
||||||
"search": "搜索",
|
"search": "搜索",
|
||||||
"show-composer-genres-info-1": "以逗号分隔流派,作曲家会在“正在播放的页面”上显示",
|
"show-composer-genres-info-1": "以逗号分隔的流派列表,必须显示作曲家所属的流派",
|
||||||
"show-composer-genres-info-2": "留空以始终显示作曲家",
|
"show-composer-genres-info-2": "留空以始终显示作曲家",
|
||||||
"show-composer-genres-info-3": "通过检查是否包含定义的流派之一来匹配当前曲目的流派标签。例如,设置为“古典、原声带”将显示流派标签为“当代古典”的曲目的作曲家",
|
"show-composer-genres-info-3": "通过检查是否包含定义的流派之一来匹配当前曲目的流派标签。例如,设置为“古典、原声带”将显示流派标签为“当代古典”的曲目的作曲家",
|
||||||
"show-composer-genres": "仅显示列出的流派的作曲家",
|
"show-composer-genres": "仅显示列出的流派的作曲家",
|
||||||
"show-composer-info": "如果启用,当前播放曲目的作曲家将显示在“正在播放页面”上",
|
"show-composer-info": "如果启用,则会显示当前播放曲目的作曲家",
|
||||||
"show-composer": "显示作曲家",
|
"show-composer": "显示作曲家",
|
||||||
"show-path": "在“正在播放”页面显示文件路径"
|
"show-path": "显示文件路径"
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"lastfm": {
|
"lastfm": {
|
||||||
@ -494,8 +495,7 @@
|
|||||||
"spotify": {
|
"spotify": {
|
||||||
"no-support": "OwnTone的构建没有来自 Spotify 官方的支持,也未安装 libspotify",
|
"no-support": "OwnTone的构建没有来自 Spotify 官方的支持,也未安装 libspotify",
|
||||||
"logged-as": "登录为 ",
|
"logged-as": "登录为 ",
|
||||||
"requirements": "您必须拥有 Spotify付费帐户",
|
"requirements": "您必须拥有 Spotify付费帐户。访问 Spotify Web API 可以扫描您的 Spotify库。所需范围是:",
|
||||||
"scopes": "访问 Spotify Web API 可以扫描您的 Spotify库。所需范围是:",
|
|
||||||
"user": "授予访问权限",
|
"user": "授予访问权限",
|
||||||
"authorize": "授权 Web API 访问",
|
"authorize": "授权 Web API 访问",
|
||||||
"grant-access": "授予对 Spotify Web API 的访问权限",
|
"grant-access": "授予对 Spotify Web API 的访问权限",
|
||||||
@ -571,10 +571,6 @@
|
|||||||
"toggle-lyrics": "显示/隐藏歌词"
|
"toggle-lyrics": "显示/隐藏歌词"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"setting": {
|
|
||||||
"not-saved": " (设置保存错误)",
|
|
||||||
"saved": " (设置已保存)"
|
|
||||||
},
|
|
||||||
"server": {
|
"server": {
|
||||||
"connection-failed": "无法连接到 OwnTone 服务器",
|
"connection-failed": "无法连接到 OwnTone 服务器",
|
||||||
"request-failed": "请求失败 (状态:{status} {cause} {url})",
|
"request-failed": "请求失败 (状态:{status} {cause} {url})",
|
||||||
|
@ -241,6 +241,7 @@
|
|||||||
"compiled-with": "編譯支持來自於 {options}",
|
"compiled-with": "編譯支持來自於 {options}",
|
||||||
"library": "資料庫",
|
"library": "資料庫",
|
||||||
"more": "更多",
|
"more": "更多",
|
||||||
|
"name": "名稱",
|
||||||
"total-playtime": "總播放時長",
|
"total-playtime": "總播放時長",
|
||||||
"tracks": "曲目總數",
|
"tracks": "曲目總數",
|
||||||
"update": "更新",
|
"update": "更新",
|
||||||
@ -407,8 +408,8 @@
|
|||||||
"count": "{count} 首曲目|{count} 首曲目",
|
"count": "{count} 首曲目|{count} 首曲目",
|
||||||
"edit": "編輯",
|
"edit": "編輯",
|
||||||
"hide-previous": "隱藏歷史",
|
"hide-previous": "隱藏歷史",
|
||||||
"title": "清單",
|
"save": "儲存",
|
||||||
"save": "儲存"
|
"title": "清單"
|
||||||
},
|
},
|
||||||
"radio": {
|
"radio": {
|
||||||
"count": "{count} 個電台|{count} 個電台",
|
"count": "{count} 個電台|{count} 個電台",
|
||||||
@ -473,16 +474,16 @@
|
|||||||
"playlists": "播放列表",
|
"playlists": "播放列表",
|
||||||
"podcasts": "Podcast",
|
"podcasts": "Podcast",
|
||||||
"radio": "電台",
|
"radio": "電台",
|
||||||
"recently-added-page-info": "限制“最近新增”頁面上顯示的專輯數量",
|
"recently-added-page-info": "限制顯示的相簿數量",
|
||||||
"recently-added-page": "“最近新增”頁面",
|
"recently-added-page": "“最近新增”頁面",
|
||||||
"search": "搜尋",
|
"search": "搜尋",
|
||||||
"show-composer-genres-info-1": "以逗號分隔音樂類型,作曲家會在“正在播放的頁面”上顯示",
|
"show-composer-genres-info-1": "以逗號分隔的音樂類型清單,將顯示作曲家的音樂類型",
|
||||||
"show-composer-genres-info-2": "留空以始終顯示作曲家",
|
"show-composer-genres-info-2": "留空以始終顯示作曲家",
|
||||||
"show-composer-genres-info-3": "通過檢查是否包含定義的音樂類型之一來匹配當前曲目的音樂類型標籤。例如,設定為“古典、原聲帶”將顯示音樂類型標籤為“當代古典”的曲目的作曲家",
|
"show-composer-genres-info-3": "通過檢查是否包含定義的音樂類型之一來匹配當前曲目的音樂類型標籤。例如,設定為“古典、原聲帶”將顯示音樂類型標籤為“當代古典”的曲目的作曲家",
|
||||||
"show-composer-genres": "僅顯示列出的音樂類型的作曲家",
|
"show-composer-genres": "僅顯示列出的音樂類型的作曲家",
|
||||||
"show-composer-info": "如果啓用,當前播放曲目的作曲家將顯示在“正在播放頁面”上",
|
"show-composer-info": "如果啟用,則會顯示目前播放曲目的作曲家",
|
||||||
"show-composer": "顯示作曲家",
|
"show-composer": "顯示作曲家",
|
||||||
"show-path": "在“正在播放”頁面顯示文件路徑"
|
"show-path": "顯示檔案路徑"
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"lastfm": {
|
"lastfm": {
|
||||||
@ -494,8 +495,7 @@
|
|||||||
"spotify": {
|
"spotify": {
|
||||||
"no-support": "OwnTone並無 Spotify 官方的支持,也未安裝 libspotify",
|
"no-support": "OwnTone並無 Spotify 官方的支持,也未安裝 libspotify",
|
||||||
"logged-as": "登入為 ",
|
"logged-as": "登入為 ",
|
||||||
"requirements": "您必須擁有 Spotify付費帳戶",
|
"requirements": "您必須擁有 Spotify付費帳戶。訪問 Spotify Web API 可以掃描您的 Spotify庫。所需範圍是:",
|
||||||
"scopes": "訪問 Spotify Web API 可以掃描您的 Spotify庫。所需範圍是:",
|
|
||||||
"user": "授予訪問權限",
|
"user": "授予訪問權限",
|
||||||
"authorize": "授權 Web API 訪問",
|
"authorize": "授權 Web API 訪問",
|
||||||
"grant-access": "授予對 Spotify Web API 的訪問權限",
|
"grant-access": "授予對 Spotify Web API 的訪問權限",
|
||||||
@ -571,10 +571,6 @@
|
|||||||
"toggle-lyrics": "顯示/隱藏歌詞"
|
"toggle-lyrics": "顯示/隱藏歌詞"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"setting": {
|
|
||||||
"not-saved": " (設定儲存錯誤)",
|
|
||||||
"saved": " (設定已儲存)"
|
|
||||||
},
|
|
||||||
"server": {
|
"server": {
|
||||||
"connection-failed": "無法連接到 OwnTone 伺服器",
|
"connection-failed": "無法連接到 OwnTone 伺服器",
|
||||||
"request-failed": "請求失敗 (狀態:{status} {cause} {url})",
|
"request-failed": "請求失敗 (狀態:{status} {cause} {url})",
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
mdiChevronDown,
|
mdiChevronDown,
|
||||||
mdiChevronLeft,
|
mdiChevronLeft,
|
||||||
mdiChevronUp,
|
mdiChevronUp,
|
||||||
|
mdiClose,
|
||||||
mdiContentSave,
|
mdiContentSave,
|
||||||
mdiDelete,
|
mdiDelete,
|
||||||
mdiDeleteEmpty,
|
mdiDeleteEmpty,
|
||||||
@ -79,6 +80,7 @@ export const icons = {
|
|||||||
mdiChevronDown,
|
mdiChevronDown,
|
||||||
mdiChevronLeft,
|
mdiChevronLeft,
|
||||||
mdiChevronUp,
|
mdiChevronUp,
|
||||||
|
mdiClose,
|
||||||
mdiContentSave,
|
mdiContentSave,
|
||||||
mdiDelete,
|
mdiDelete,
|
||||||
mdiDeleteEmpty,
|
mdiDeleteEmpty,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
@use 'bulma/bulma';
|
@use 'bulma/bulma';
|
||||||
@use 'bulma/sass/utilities/mixins';
|
@use 'bulma/sass/utilities/mixins';
|
||||||
|
|
||||||
.fd-tabs-section {
|
.tabs-section {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
background: var(--bulma-body-background-color);
|
background: var(--bulma-body-background-color);
|
||||||
|
@ -1,180 +1,166 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<section class="section">
|
||||||
<section class="section">
|
<div class="container">
|
||||||
<div class="container">
|
<div class="columns is-centered">
|
||||||
<div class="columns is-centered">
|
<div class="column is-four-fifths">
|
||||||
<div class="column is-four-fifths has-text-centered-mobile">
|
<div class="content">
|
||||||
<h1 class="title is-4" v-text="configuration.library_name" />
|
<nav class="level">
|
||||||
</div>
|
<div class="level-left">
|
||||||
</div>
|
<div class="level-item">
|
||||||
</div>
|
<p class="title is-4" v-text="$t('page.about.library')" />
|
||||||
</section>
|
|
||||||
<section class="section">
|
|
||||||
<div class="container">
|
|
||||||
<div class="columns is-centered">
|
|
||||||
<div class="column is-four-fifths">
|
|
||||||
<div class="content">
|
|
||||||
<nav class="level is-mobile">
|
|
||||||
<!-- Left side -->
|
|
||||||
<div class="level-left">
|
|
||||||
<div class="level-item">
|
|
||||||
<p class="title is-5" v-text="$t('page.about.library')" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Right side -->
|
</div>
|
||||||
<div class="level-right">
|
<div class="level-right">
|
||||||
<div v-if="library.updating">
|
<div v-if="library.updating">
|
||||||
<a
|
|
||||||
class="button is-small is-loading"
|
|
||||||
v-text="$t('page.about.update')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<a
|
|
||||||
class="button is-small"
|
|
||||||
@click="showUpdateDialog()"
|
|
||||||
v-text="$t('page.about.update')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
class="has-text-left"
|
|
||||||
v-text="$t('page.about.artists')"
|
|
||||||
/>
|
|
||||||
<td
|
|
||||||
class="has-text-right"
|
|
||||||
v-text="$filters.number(library.artists)"
|
|
||||||
/>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
class="has-text-left"
|
|
||||||
v-text="$t('page.about.albums')"
|
|
||||||
/>
|
|
||||||
<td
|
|
||||||
class="has-text-right"
|
|
||||||
v-text="$filters.number(library.albums)"
|
|
||||||
/>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
class="has-text-left"
|
|
||||||
v-text="$t('page.about.tracks')"
|
|
||||||
/>
|
|
||||||
<td
|
|
||||||
class="has-text-right"
|
|
||||||
v-text="$filters.number(library.songs)"
|
|
||||||
/>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
class="has-text-left"
|
|
||||||
v-text="$t('page.about.total-playtime')"
|
|
||||||
/>
|
|
||||||
<td
|
|
||||||
class="has-text-right"
|
|
||||||
v-text="
|
|
||||||
$filters.durationInDays(library.db_playtime * 1000)
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
class="has-text-left"
|
|
||||||
v-text="$t('page.about.updated')"
|
|
||||||
/>
|
|
||||||
<td class="has-text-right">
|
|
||||||
<span
|
|
||||||
v-text="
|
|
||||||
$t('page.about.updated-on', {
|
|
||||||
time: $filters.timeFromNow(library.updated_at)
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
(<span
|
|
||||||
class="has-text-grey"
|
|
||||||
v-text="$filters.datetime(library.updated_at)"
|
|
||||||
/>)
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
class="has-text-left"
|
|
||||||
v-text="$t('page.about.uptime')"
|
|
||||||
/>
|
|
||||||
<td class="has-text-right">
|
|
||||||
<span
|
|
||||||
v-text="$filters.timeFromNow(library.started_at, true)"
|
|
||||||
/>
|
|
||||||
(<span
|
|
||||||
class="has-text-grey"
|
|
||||||
v-text="$filters.datetime(library.started_at)"
|
|
||||||
/>)
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="section">
|
|
||||||
<div class="container">
|
|
||||||
<div class="columns is-centered">
|
|
||||||
<div class="column is-four-fifths">
|
|
||||||
<div class="content has-text-centered-mobile">
|
|
||||||
<p
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="
|
|
||||||
$t('page.about.version', { version: configuration.version })
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<p
|
|
||||||
class="is-size-7"
|
|
||||||
v-text="
|
|
||||||
$t('page.about.compiled-with', {
|
|
||||||
options: configuration.buildoptions.join(', ')
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<i18n-t
|
|
||||||
tag="p"
|
|
||||||
class="is-size-7"
|
|
||||||
keypath="page.about.built-with"
|
|
||||||
scope="global"
|
|
||||||
>
|
|
||||||
<template #bulma>
|
|
||||||
<a href="https://bulma.io">Bulma</a>
|
|
||||||
</template>
|
|
||||||
<template #mdi>
|
|
||||||
<a href="https://pictogrammers.com/library/mdi/">
|
|
||||||
Material Design Icons
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
<template #vuejs>
|
|
||||||
<a href="https://vuejs.org/">Vue.js</a>
|
|
||||||
</template>
|
|
||||||
<template #axios>
|
|
||||||
<a href="https://github.com/axios/axios">axios</a>
|
|
||||||
</template>
|
|
||||||
<template #others>
|
|
||||||
<a
|
<a
|
||||||
href="https://github.com/owntone/owntone-server/network/dependencies"
|
class="button is-small is-loading"
|
||||||
v-text="$t('page.about.more')"
|
v-text="$t('page.about.update')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</div>
|
||||||
</i18n-t>
|
<div v-else>
|
||||||
|
<a
|
||||||
|
class="button is-small"
|
||||||
|
@click="showUpdateDialog()"
|
||||||
|
v-text="$t('page.about.update')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="media">
|
||||||
|
<div
|
||||||
|
class="media-content has-text-weight-bold"
|
||||||
|
v-text="$t('page.about.name')"
|
||||||
|
/>
|
||||||
|
<div class="media-right" v-text="configuration.library_name" />
|
||||||
|
</div>
|
||||||
|
<div class="media">
|
||||||
|
<div
|
||||||
|
class="media-content has-text-weight-bold"
|
||||||
|
v-text="$t('page.about.artists')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="media-right"
|
||||||
|
v-text="$filters.number(library.artists)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="media">
|
||||||
|
<div
|
||||||
|
class="media-content has-text-weight-bold"
|
||||||
|
v-text="$t('page.about.albums')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
media="media-right"
|
||||||
|
v-text="$filters.number(library.albums)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="media">
|
||||||
|
<div
|
||||||
|
class="media-content has-text-weight-bold"
|
||||||
|
v-text="$t('page.about.tracks')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="media-right"
|
||||||
|
v-text="$filters.number(library.songs)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="media">
|
||||||
|
<div
|
||||||
|
class="media-content has-text-weight-bold"
|
||||||
|
v-text="$t('page.about.total-playtime')"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="media-right"
|
||||||
|
v-text="$filters.durationInDays(library.db_playtime)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="media">
|
||||||
|
<div
|
||||||
|
class="media-content has-text-weight-bold"
|
||||||
|
v-text="$t('page.about.updated')"
|
||||||
|
/>
|
||||||
|
<div class="media-right">
|
||||||
|
<span
|
||||||
|
v-text="
|
||||||
|
$t('page.about.updated-on', {
|
||||||
|
time: $filters.timeFromNow(library.updated_at)
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
(<span
|
||||||
|
class="has-text-grey"
|
||||||
|
v-text="$filters.datetime(library.updated_at)"
|
||||||
|
/>)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="media">
|
||||||
|
<div
|
||||||
|
class="media-content has-text-weight-bold"
|
||||||
|
v-text="$t('page.about.uptime')"
|
||||||
|
/>
|
||||||
|
<div class="media-right">
|
||||||
|
<span v-text="$filters.timeFromNow(library.started_at, true)" />
|
||||||
|
(<span
|
||||||
|
class="has-text-grey"
|
||||||
|
v-text="$filters.datetime(library.started_at)"
|
||||||
|
/>)
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<div class="columns is-centered">
|
||||||
|
<div class="column is-four-fifths">
|
||||||
|
<div class="content has-text-centered-mobile">
|
||||||
|
<p
|
||||||
|
class="is-size-7"
|
||||||
|
v-text="
|
||||||
|
$t('page.about.version', { version: configuration.version })
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
class="is-size-7"
|
||||||
|
v-text="
|
||||||
|
$t('page.about.compiled-with', {
|
||||||
|
options: configuration.buildoptions.join(', ')
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<i18n-t
|
||||||
|
tag="p"
|
||||||
|
class="is-size-7"
|
||||||
|
keypath="page.about.built-with"
|
||||||
|
scope="global"
|
||||||
|
>
|
||||||
|
<template #bulma>
|
||||||
|
<a href="https://bulma.io">Bulma</a>
|
||||||
|
</template>
|
||||||
|
<template #mdi>
|
||||||
|
<a href="https://pictogrammers.com/library/mdi/">
|
||||||
|
Material Design Icons
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
<template #vuejs>
|
||||||
|
<a href="https://vuejs.org/">Vue.js</a>
|
||||||
|
</template>
|
||||||
|
<template #axios>
|
||||||
|
<a href="https://github.com/axios/axios">axios</a>
|
||||||
|
</template>
|
||||||
|
<template #others>
|
||||||
|
<a
|
||||||
|
href="https://github.com/owntone/owntone-server/network/dependencies"
|
||||||
|
v-text="$t('page.about.more')"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -209,5 +195,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -2,17 +2,20 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-hero>
|
<content-with-hero>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<h1 class="title is-5" v-text="album.name" />
|
<div class="title is-5" v-text="album.name" />
|
||||||
<h2 class="subtitle is-6 has-text-link">
|
<div class="subtitle is-6">
|
||||||
<a class="has-text-link" @click="open_artist" v-text="album.artist" />
|
<a @click="open_artist" v-text="album.artist" />
|
||||||
</h2>
|
</div>
|
||||||
<div class="buttons fd-is-centered-mobile mt-5">
|
<div class="buttons is-centered-mobile mt-5">
|
||||||
<a class="button is-small is-dark is-rounded" @click="play">
|
<a
|
||||||
|
class="button has-background-light is-small is-rounded"
|
||||||
|
@click="play"
|
||||||
|
>
|
||||||
<mdicon class="icon" name="shuffle" size="16" />
|
<mdicon class="icon" name="shuffle" size="16" />
|
||||||
<span v-text="$t('page.album.shuffle')" />
|
<span v-text="$t('page.album.shuffle')" />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="button is-small is-light is-rounded"
|
class="button is-small has-background-light is-rounded"
|
||||||
@click="show_details_modal = true"
|
@click="show_details_modal = true"
|
||||||
>
|
>
|
||||||
<mdicon class="icon" name="dots-horizontal" size="16" />
|
<mdicon class="icon" name="dots-horizontal" size="16" />
|
||||||
@ -29,8 +32,8 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p
|
<div
|
||||||
class="heading has-text-centered-mobile mt-5"
|
class="is-size-7 is-uppercase has-text-centered-mobile my-5"
|
||||||
v-text="$t('page.album.track-count', { count: album.track_count })"
|
v-text="$t('page.album.track-count', { count: album.track_count })"
|
||||||
/>
|
/>
|
||||||
<list-tracks :items="tracks" :uris="album.uri" />
|
<list-tracks :items="tracks" :uris="album.uri" />
|
||||||
@ -104,5 +107,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -2,15 +2,11 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-hero>
|
<content-with-hero>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<h1 class="title is-5" v-text="album.name" />
|
<div class="title is-5" v-text="album.name" />
|
||||||
<h2 class="subtitle is-6 has-text-link">
|
<div class="subtitle is-6">
|
||||||
<a
|
<a @click="open_artist" v-text="album.artists[0].name" />
|
||||||
class="has-text-link"
|
</div>
|
||||||
@click="open_artist"
|
<div class="buttons is-centered-mobile mt-5">
|
||||||
v-text="album.artists[0].name"
|
|
||||||
/>
|
|
||||||
</h2>
|
|
||||||
<div class="buttons fd-is-centered-mobile mt-5">
|
|
||||||
<a class="button is-small is-dark is-rounded" @click="play">
|
<a class="button is-small is-dark is-rounded" @click="play">
|
||||||
<mdicon class="icon" name="shuffle" size="16" />
|
<mdicon class="icon" name="shuffle" size="16" />
|
||||||
<span v-text="$t('page.spotify.album.shuffle')" />
|
<span v-text="$t('page.spotify.album.shuffle')" />
|
||||||
@ -33,8 +29,8 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p
|
<div
|
||||||
class="heading has-text-centered-mobile mt-5"
|
class="is-size-7 is-uppercase has-text-centered-mobile mt-5"
|
||||||
v-text="
|
v-text="
|
||||||
$t('page.spotify.album.track-count', { count: album.tracks.total })
|
$t('page.spotify.album.track-count', { count: album.tracks.total })
|
||||||
"
|
"
|
||||||
@ -127,5 +123,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,60 +1,54 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #options>
|
<template #options>
|
||||||
<index-button-list :indices="albums.indices" />
|
<index-button-list :indices="albums.indices" />
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.albums.filter')" />
|
<div
|
||||||
<div class="field">
|
class="is-size-7 is-uppercase"
|
||||||
<div class="control">
|
v-text="$t('page.albums.filter')"
|
||||||
<input
|
/>
|
||||||
id="switchHideSingles"
|
<control-switch v-model="uiStore.hide_singles">
|
||||||
v-model="hide_singles"
|
<template #label>
|
||||||
type="checkbox"
|
<span v-text="$t('page.albums.hide-singles')" />
|
||||||
class="switch is-rounded"
|
</template>
|
||||||
/>
|
<template #help>
|
||||||
<label
|
<span v-text="$t('page.albums.hide-singles-help')" />
|
||||||
for="switchHideSingles"
|
</template>
|
||||||
v-text="$t('page.albums.hide-singles')"
|
</control-switch>
|
||||||
/>
|
<control-switch
|
||||||
</div>
|
v-if="spotify_enabled"
|
||||||
<p class="help" v-text="$t('page.albums.hide-singles-help')" />
|
v-model="uiStore.hide_spotify"
|
||||||
</div>
|
>
|
||||||
<div v-if="spotify_enabled" class="field">
|
<template #label>
|
||||||
<div class="control">
|
<span v-text="$t('page.albums.hide-spotify')" />
|
||||||
<input
|
</template>
|
||||||
id="switchHideSpotify"
|
<template #help>
|
||||||
v-model="hide_spotify"
|
<span v-text="$t('page.albums.hide-spotify-help')" />
|
||||||
type="checkbox"
|
</template>
|
||||||
class="switch is-rounded"
|
</control-switch>
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="switchHideSpotify"
|
|
||||||
v-text="$t('page.albums.hide-spotify')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p class="help" v-text="$t('page.albums.hide-spotify-help')" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.albums.sort.title')" />
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('page.albums.sort.title')"
|
||||||
|
/>
|
||||||
<control-dropdown
|
<control-dropdown
|
||||||
v-model:value="selected_grouping_id"
|
v-model:value="uiStore.albums_sort"
|
||||||
:options="groupings"
|
:options="groupings"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.albums.title')" />
|
<div class="title is-4" v-text="$t('page.albums.title')" />
|
||||||
<p
|
<div
|
||||||
class="heading"
|
class="is-size-7 is-uppercase"
|
||||||
v-text="$t('page.albums.count', { count: albums.count })"
|
v-text="$t('page.albums.count', { count: albums.count })"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right />
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
</template>
|
</template>
|
||||||
@ -65,6 +59,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
@ -88,6 +83,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
|
ControlSwitch,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
TabsMusic
|
TabsMusic
|
||||||
@ -157,43 +153,17 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
albums() {
|
albums() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
(grouping) => grouping.id === this.selected_grouping_id
|
(grouping) => grouping.id === this.uiStore.albums_sort
|
||||||
)
|
)
|
||||||
options.filters = [
|
options.filters = [
|
||||||
(album) => !this.hide_singles || album.track_count > 2,
|
(album) => !this.uiStore.hide_singles || album.track_count > 2,
|
||||||
(album) => !this.hide_spotify || album.data_kind !== 'spotify'
|
(album) => !this.uiStore.hide_spotify || album.data_kind !== 'spotify'
|
||||||
]
|
]
|
||||||
return this.albums_list.group(options)
|
return this.albums_list.group(options)
|
||||||
},
|
},
|
||||||
hide_singles: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.hide_singles
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.hide_singles = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hide_spotify: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.hide_spotify
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.hide_spotify = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selected_grouping_id: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.albums_sort
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.albums_sort = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -4,34 +4,46 @@
|
|||||||
<template #options>
|
<template #options>
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.artist.filter')" />
|
<div
|
||||||
<div v-if="spotify_enabled" class="field">
|
class="is-size-7 is-uppercase"
|
||||||
<div class="control">
|
v-text="$t('page.artist.filter')"
|
||||||
<input
|
/>
|
||||||
id="switchHideSpotify"
|
<control-switch
|
||||||
v-model="hide_spotify"
|
v-if="spotify_enabled"
|
||||||
type="checkbox"
|
v-model="uiStore.hide_spotify"
|
||||||
class="switch is-rounded"
|
>
|
||||||
/>
|
<template #label>
|
||||||
<label
|
<span v-text="$t('page.artist.hide-spotify')" />
|
||||||
for="switchHideSpotify"
|
</template>
|
||||||
v-text="$t('page.artist.hide-spotify')"
|
<template #help>
|
||||||
/>
|
<span v-text="$t('page.artist.hide-spotify-help')" />
|
||||||
</div>
|
</template>
|
||||||
<p class="help" v-text="$t('page.artist.hide-spotify-help')" />
|
</control-switch>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.artist.sort.title')" />
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('page.artist.sort.title')"
|
||||||
|
/>
|
||||||
<control-dropdown
|
<control-dropdown
|
||||||
v-model:value="selected_grouping_id"
|
v-model:value="uiStore.artist_albums_sort"
|
||||||
:options="groupings"
|
:options="groupings"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="artist.name" />
|
<div class="title is-4" v-text="artist.name" />
|
||||||
|
<div class="is-size-7 is-uppercase">
|
||||||
|
<span
|
||||||
|
v-text="$t('page.artist.album-count', { count: albums.count })"
|
||||||
|
/>
|
||||||
|
<span> | </span>
|
||||||
|
<a
|
||||||
|
@click="open_tracks"
|
||||||
|
v-text="$t('page.artist.track-count', { count: track_count })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<div class="buttons is-centered">
|
||||||
@ -48,17 +60,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p class="heading has-text-centered-mobile">
|
|
||||||
<span
|
|
||||||
v-text="$t('page.artist.album-count', { count: albums.count })"
|
|
||||||
/>
|
|
||||||
<span> | </span>
|
|
||||||
<a
|
|
||||||
class="has-text-link"
|
|
||||||
@click="open_tracks"
|
|
||||||
v-text="$t('page.artist.track-count', { count: track_count })"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
<modal-dialog-artist
|
<modal-dialog-artist
|
||||||
:item="artist"
|
:item="artist"
|
||||||
@ -73,6 +74,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
import ListAlbums from '@/components/ListAlbums.vue'
|
import ListAlbums from '@/components/ListAlbums.vue'
|
||||||
import ModalDialogArtist from '@/components/ModalDialogArtist.vue'
|
import ModalDialogArtist from '@/components/ModalDialogArtist.vue'
|
||||||
@ -99,6 +101,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
|
ControlSwitch,
|
||||||
ListAlbums,
|
ListAlbums,
|
||||||
ModalDialogArtist
|
ModalDialogArtist
|
||||||
},
|
},
|
||||||
@ -136,29 +139,13 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
albums() {
|
albums() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
(grouping) => grouping.id === this.selected_grouping_id
|
(grouping) => grouping.id === this.uiStore.artist_albums_sort
|
||||||
)
|
)
|
||||||
options.filters = [
|
options.filters = [
|
||||||
(album) => !this.hide_spotify || album.data_kind !== 'spotify'
|
(album) => !this.uiStore.hide_spotify || album.data_kind !== 'spotify'
|
||||||
]
|
]
|
||||||
return this.albums_list.group(options)
|
return this.albums_list.group(options)
|
||||||
},
|
},
|
||||||
hide_spotify: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.hide_spotify
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.hide_spotify = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selected_grouping_id: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.artist_albums_sort
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.artist_albums_sort = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
},
|
},
|
||||||
@ -187,5 +174,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="artist.name" />
|
<div class="title is-4" v-text="artist.name" />
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('page.spotify.artist.album-count', { count: total })"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<div class="buttons is-centered">
|
||||||
@ -19,10 +23,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p
|
|
||||||
class="heading has-text-centered-mobile"
|
|
||||||
v-text="$t('page.spotify.artist.album-count', { count: total })"
|
|
||||||
/>
|
|
||||||
<list-albums-spotify :items="albums" />
|
<list-albums-spotify :items="albums" />
|
||||||
<VueEternalLoading v-if="offset < total" :load="load_next">
|
<VueEternalLoading v-if="offset < total" :load="load_next">
|
||||||
<template #loading>
|
<template #loading>
|
||||||
@ -140,5 +140,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -5,27 +5,29 @@
|
|||||||
<index-button-list :indices="tracks.indices" />
|
<index-button-list :indices="tracks.indices" />
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.artist.filter')" />
|
<p
|
||||||
<div v-if="spotify_enabled" class="field">
|
class="is-size-7 is-uppercase"
|
||||||
<div class="control">
|
v-text="$t('page.artist.filter')"
|
||||||
<input
|
/>
|
||||||
id="switchHideSpotify"
|
<control-switch
|
||||||
v-model="hide_spotify"
|
v-if="spotify_enabled"
|
||||||
type="checkbox"
|
v-model="uiStore.hide_spotify"
|
||||||
class="switch is-rounded"
|
>
|
||||||
/>
|
<template #label>
|
||||||
<label
|
<span v-text="$t('page.artist.hide-spotify')" />
|
||||||
for="switchHideSpotify"
|
</template>
|
||||||
v-text="$t('page.artist.hide-spotify')"
|
<template #help>
|
||||||
/>
|
<span v-text="$t('page.artist.hide-spotify-help')" />
|
||||||
</div>
|
</template>
|
||||||
<p class="help" v-text="$t('page.artist.hide-spotify-help')" />
|
</control-switch>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.artist.sort.title')" />
|
<p
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('page.artist.sort.title')"
|
||||||
|
/>
|
||||||
<control-dropdown
|
<control-dropdown
|
||||||
v-model:value="selected_grouping_id"
|
v-model:value="uiStore.artist_tracks_sort"
|
||||||
:options="groupings"
|
:options="groupings"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -33,6 +35,16 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="artist.name" />
|
<p class="title is-4" v-text="artist.name" />
|
||||||
|
<div class="is-size-7 is-uppercase">
|
||||||
|
<a
|
||||||
|
@click="open_artist"
|
||||||
|
v-text="$t('page.artist.album-count', { count: album_count })"
|
||||||
|
/>
|
||||||
|
<span> | </span>
|
||||||
|
<span
|
||||||
|
v-text="$t('page.artist.track-count', { count: tracks.count })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<div class="buttons is-centered">
|
||||||
@ -49,17 +61,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p class="heading has-text-centered-mobile">
|
|
||||||
<a
|
|
||||||
class="has-text-link"
|
|
||||||
@click="open_artist"
|
|
||||||
v-text="$t('page.artist.album-count', { count: album_count })"
|
|
||||||
/>
|
|
||||||
<span> | </span>
|
|
||||||
<span
|
|
||||||
v-text="$t('page.artist.track-count', { count: tracks.count })"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<list-tracks :items="tracks" :uris="track_uris" />
|
<list-tracks :items="tracks" :uris="track_uris" />
|
||||||
<modal-dialog-artist
|
<modal-dialog-artist
|
||||||
:item="artist"
|
:item="artist"
|
||||||
@ -74,6 +75,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListTracks from '@/components/ListTracks.vue'
|
import ListTracks from '@/components/ListTracks.vue'
|
||||||
@ -101,6 +103,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
|
ControlSwitch,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListTracks,
|
ListTracks,
|
||||||
ModalDialogArtist
|
ModalDialogArtist
|
||||||
@ -147,22 +150,6 @@ export default {
|
|||||||
.map((track) => track.item.album_id)
|
.map((track) => track.item.album_id)
|
||||||
).size
|
).size
|
||||||
},
|
},
|
||||||
hide_spotify: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.hide_spotify
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.hide_spotify = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selected_grouping_id: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.artist_tracks_sort
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.artist_tracks_sort = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
},
|
},
|
||||||
@ -171,10 +158,10 @@ export default {
|
|||||||
},
|
},
|
||||||
tracks() {
|
tracks() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
(grouping) => grouping.id === this.selected_grouping_id
|
(grouping) => grouping.id === this.uiStore.artist_tracks_sort
|
||||||
)
|
)
|
||||||
options.filters = [
|
options.filters = [
|
||||||
(track) => !this.hide_spotify || track.data_kind !== 'spotify'
|
(track) => !this.uiStore.hide_spotify || track.data_kind !== 'spotify'
|
||||||
]
|
]
|
||||||
return this.tracks_list.group(options)
|
return this.tracks_list.group(options)
|
||||||
}
|
}
|
||||||
@ -197,5 +184,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,60 +1,53 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #options>
|
<template #options>
|
||||||
<index-button-list :indices="artists.indices" />
|
<index-button-list :indices="artists.indices" />
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.artists.filter')" />
|
<div
|
||||||
<div class="field">
|
class="is-size-7 is-uppercase"
|
||||||
<div class="control">
|
v-text="$t('page.artists.filter')"
|
||||||
<input
|
/>
|
||||||
id="switchHideSingles"
|
<control-switch v-model="uiStore.hide_singles">
|
||||||
v-model="hide_singles"
|
<template #label>
|
||||||
type="checkbox"
|
<span v-text="$t('page.artists.hide-singles')" />
|
||||||
class="switch is-rounded"
|
</template>
|
||||||
/>
|
<template #help>
|
||||||
<label
|
<span v-text="$t('page.artists.hide-singles-help')" />
|
||||||
for="switchHideSingles"
|
</template>
|
||||||
v-text="$t('page.artists.hide-singles')"
|
</control-switch>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p class="help" v-text="$t('page.artists.hide-singles-help')" />
|
|
||||||
</div>
|
|
||||||
<div v-if="spotify_enabled" class="field">
|
<div v-if="spotify_enabled" class="field">
|
||||||
<div class="control">
|
<control-switch v-model="uiStore.hide_spotify">
|
||||||
<input
|
<template #label>
|
||||||
id="switchHideSpotify"
|
<span v-text="$t('page.artists.hide-spotify')" />
|
||||||
v-model="hide_spotify"
|
</template>
|
||||||
type="checkbox"
|
<template #help>
|
||||||
class="switch is-rounded"
|
<span v-text="$t('page.artists.hide-spotify-help')" />
|
||||||
/>
|
</template>
|
||||||
<label
|
</control-switch>
|
||||||
for="switchHideSpotify"
|
|
||||||
v-text="$t('page.artists.hide-spotify')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p class="help" v-text="$t('page.artists.hide-spotify-help')" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.artists.sort.title')" />
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('page.artists.sort.title')"
|
||||||
|
/>
|
||||||
<control-dropdown
|
<control-dropdown
|
||||||
v-model:value="selected_grouping_id"
|
v-model:value="uiStore.artists_sort"
|
||||||
:options="groupings"
|
:options="groupings"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.artists.title')" />
|
<div class="title is-4" v-text="$t('page.artists.title')" />
|
||||||
<p
|
<div
|
||||||
class="heading"
|
class="is-size-7 is-uppercase"
|
||||||
v-text="$t('page.artists.count', { count: artists.count })"
|
v-text="$t('page.artists.count', { count: artists.count })"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right />
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-artists :items="artists" />
|
<list-artists :items="artists" />
|
||||||
</template>
|
</template>
|
||||||
@ -65,6 +58,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
||||||
import ControlDropdown from '@/components/ControlDropdown.vue'
|
import ControlDropdown from '@/components/ControlDropdown.vue'
|
||||||
|
import ControlSwitch from '@/components/ControlSwitch.vue'
|
||||||
import { GroupedList } from '@/lib/GroupedList'
|
import { GroupedList } from '@/lib/GroupedList'
|
||||||
import IndexButtonList from '@/components/IndexButtonList.vue'
|
import IndexButtonList from '@/components/IndexButtonList.vue'
|
||||||
import ListArtists from '@/components/ListArtists.vue'
|
import ListArtists from '@/components/ListArtists.vue'
|
||||||
@ -88,6 +82,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
ContentWithHeading,
|
ContentWithHeading,
|
||||||
ControlDropdown,
|
ControlDropdown,
|
||||||
|
ControlSwitch,
|
||||||
IndexButtonList,
|
IndexButtonList,
|
||||||
ListArtists,
|
ListArtists,
|
||||||
TabsMusic
|
TabsMusic
|
||||||
@ -125,47 +120,21 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
// Wraps GroupedList and updates it if filter or sort changes
|
|
||||||
artists() {
|
artists() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
(grouping) => grouping.id === this.selected_grouping_id
|
(grouping) => grouping.id === this.uiStore.artists_sort
|
||||||
)
|
)
|
||||||
options.filters = [
|
options.filters = [
|
||||||
(artist) =>
|
(artist) =>
|
||||||
!this.hide_singles || artist.track_count > artist.album_count * 2,
|
!this.uiStore.hide_singles ||
|
||||||
(artist) => !this.hide_spotify || artist.data_kind !== 'spotify'
|
artist.track_count > artist.album_count * 2,
|
||||||
|
(artist) => !this.uiStore.hide_spotify || artist.data_kind !== 'spotify'
|
||||||
]
|
]
|
||||||
return this.artists_list.group(options)
|
return this.artists_list.group(options)
|
||||||
},
|
},
|
||||||
hide_singles: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.hide_singles
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.hide_singles = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hide_spotify: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.hide_spotify
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.hide_spotify = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selected_grouping_id: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.artists_sort
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.artists_sort = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.servicesStore.spotify.webapi_token_valid
|
return this.servicesStore.spotify.webapi_token_valid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-hero>
|
<content-with-hero>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<h1 class="title is-5" v-text="album.name" />
|
<div class="title is-5" v-text="album.name" />
|
||||||
<h2 class="subtitle is-6 has-text-link">
|
<div class="subtitle is-6">
|
||||||
<a class="has-text-link" @click="open_artist" v-text="album.artist" />
|
<a @click="open_artist" v-text="album.artist" />
|
||||||
</h2>
|
</div>
|
||||||
<div class="buttons fd-is-centered-mobile mt-5">
|
<div class="buttons is-centered-mobile mt-5">
|
||||||
<a class="button is-small is-dark is-rounded" @click="play">
|
<a class="button is-small is-dark is-rounded" @click="play">
|
||||||
<mdicon class="icon" name="play" size="16" />
|
<mdicon class="icon" name="play" size="16" />
|
||||||
<span v-text="$t('page.audiobooks.album.play')" />
|
<span v-text="$t('page.audiobooks.album.play')" />
|
||||||
@ -29,8 +29,8 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p
|
<div
|
||||||
class="heading has-text-centered-mobile mt-5"
|
class="is-size-7 is-uppercase has-text-centered-mobile mt-5"
|
||||||
v-text="
|
v-text="
|
||||||
$t('page.audiobooks.album.track-count', {
|
$t('page.audiobooks.album.track-count', {
|
||||||
count: album.track_count
|
count: album.track_count
|
||||||
@ -103,5 +103,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-audiobooks />
|
<tabs-audiobooks />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #options>
|
<template #options>
|
||||||
@ -8,7 +8,7 @@
|
|||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.audiobooks.albums.title')" />
|
<p class="title is-4" v-text="$t('page.audiobooks.albums.title')" />
|
||||||
<p
|
<p
|
||||||
class="heading"
|
class="is-size-7 is-uppercase"
|
||||||
v-text="$t('page.audiobooks.albums.count', { count: albums.count })"
|
v-text="$t('page.audiobooks.albums.count', { count: albums.count })"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -61,5 +61,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -2,7 +2,15 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="artist.name" />
|
<div class="title is-4" v-text="artist.name" />
|
||||||
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="
|
||||||
|
$t('page.audiobooks.artist.album-count', {
|
||||||
|
count: artist.album_count
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<div class="buttons is-centered">
|
||||||
@ -19,14 +27,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p
|
|
||||||
class="heading has-text-centered-mobile"
|
|
||||||
v-text="
|
|
||||||
$t('page.audiobooks.artist.album-count', {
|
|
||||||
count: artist.album_count
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
<modal-dialog-artist
|
<modal-dialog-artist
|
||||||
:item="artist"
|
:item="artist"
|
||||||
@ -87,5 +87,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-audiobooks />
|
<tabs-audiobooks />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #options>
|
<template #options>
|
||||||
<index-button-list :indices="artists.indices" />
|
<index-button-list :indices="artists.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.audiobooks.artists.title')" />
|
<div class="title is-4" v-text="$t('page.audiobooks.artists.title')" />
|
||||||
<p
|
<div
|
||||||
class="heading"
|
class="is-size-7 is-uppercase"
|
||||||
v-text="$t('page.audiobooks.artists.count', { count: artists.count })"
|
v-text="$t('page.audiobooks.artists.count', { count: artists.count })"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right />
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<list-artists :items="artists" />
|
<list-artists :items="artists" />
|
||||||
</template>
|
</template>
|
||||||
@ -62,5 +61,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-audiobooks />
|
<tabs-audiobooks />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #options>
|
<template #options>
|
||||||
<index-button-list :indices="genres.indices" />
|
<index-button-list :indices="genres.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.genres.title')" />
|
<div class="title is-4" v-text="$t('page.genres.title')" />
|
||||||
<p
|
<div
|
||||||
class="heading"
|
class="is-size-7 is-uppercase"
|
||||||
v-text="$t('page.genres.count', { count: genres.total })"
|
v-text="$t('page.genres.count', { count: genres.total })"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -61,5 +61,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -2,7 +2,21 @@
|
|||||||
<div>
|
<div>
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="composer.name" />
|
<div class="title is-4" v-text="composer.name" />
|
||||||
|
<div class="is-size-7 is-uppercase">
|
||||||
|
<span
|
||||||
|
v-text="
|
||||||
|
$t('page.composer.album-count', { count: composer.album_count })
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<span> | </span>
|
||||||
|
<a
|
||||||
|
@click="open_tracks"
|
||||||
|
v-text="
|
||||||
|
$t('page.composer.track-count', { count: composer.track_count })
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<div class="buttons is-centered">
|
||||||
@ -19,21 +33,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p class="heading has-text-centered-mobile">
|
|
||||||
<span
|
|
||||||
v-text="
|
|
||||||
$t('page.composer.album-count', { count: composer.album_count })
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<span> | </span>
|
|
||||||
<a
|
|
||||||
class="has-text-link"
|
|
||||||
@click="open_tracks"
|
|
||||||
v-text="
|
|
||||||
$t('page.composer.track-count', { count: composer.track_count })
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
<modal-dialog-composer
|
<modal-dialog-composer
|
||||||
:item="composer"
|
:item="composer"
|
||||||
@ -104,5 +103,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -5,16 +5,35 @@
|
|||||||
<index-button-list :indices="tracks.indices" />
|
<index-button-list :indices="tracks.indices" />
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.artist.sort.title')" />
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('page.artist.sort.title')"
|
||||||
|
/>
|
||||||
<control-dropdown
|
<control-dropdown
|
||||||
v-model:value="selected_grouping_id"
|
v-model:value="uiStore.composer_tracks_sort"
|
||||||
:options="groupings"
|
:options="groupings"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="composer.name" />
|
<div class="title is-4" v-text="composer.name" />
|
||||||
|
<div class="is-size-7 is-uppercase">
|
||||||
|
<a
|
||||||
|
@click="open_albums"
|
||||||
|
v-text="
|
||||||
|
$t('page.composer.album-count', {
|
||||||
|
count: composer.album_count
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<span> | </span>
|
||||||
|
<span
|
||||||
|
v-text="
|
||||||
|
$t('page.composer.track-count', { count: composer.track_count })
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<div class="buttons is-centered">
|
||||||
@ -31,23 +50,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p class="heading has-text-centered-mobile">
|
|
||||||
<a
|
|
||||||
class="has-text-link"
|
|
||||||
@click="open_albums"
|
|
||||||
v-text="
|
|
||||||
$t('page.composer.album-count', {
|
|
||||||
count: composer.album_count
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<span> | </span>
|
|
||||||
<span
|
|
||||||
v-text="
|
|
||||||
$t('page.composer.track-count', { count: composer.track_count })
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<list-tracks :items="tracks" :expression="expression" />
|
<list-tracks :items="tracks" :expression="expression" />
|
||||||
<modal-dialog-composer
|
<modal-dialog-composer
|
||||||
:item="composer"
|
:item="composer"
|
||||||
@ -130,17 +132,9 @@ export default {
|
|||||||
expression() {
|
expression() {
|
||||||
return `composer is "${this.composer.name}" and media_kind is music`
|
return `composer is "${this.composer.name}" and media_kind is music`
|
||||||
},
|
},
|
||||||
selected_grouping_id: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.composer_tracks_sort
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.composer_tracks_sort = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tracks() {
|
tracks() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
(grouping) => grouping.id === this.selected_grouping_id
|
(grouping) => grouping.id === this.uiStore.composer_tracks_sort
|
||||||
)
|
)
|
||||||
return this.tracks_list.group(options)
|
return this.tracks_list.group(options)
|
||||||
}
|
}
|
||||||
@ -160,5 +154,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #options>
|
<template #options>
|
||||||
<index-button-list :indices="composers.indices" />
|
<index-button-list :indices="composers.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.composers.title')" />
|
<div class="title is-4" v-text="$t('page.composers.title')" />
|
||||||
<p
|
<div
|
||||||
class="heading"
|
class="is-size-7 is-uppercase"
|
||||||
v-text="$t('page.composers.count', { count: composers.total })"
|
v-text="$t('page.composers.count', { count: composers.total })"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -56,5 +56,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -137,5 +137,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -5,7 +5,17 @@
|
|||||||
<index-button-list :indices="albums.indices" />
|
<index-button-list :indices="albums.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="genre.name" />
|
<div class="title is-4" v-text="genre.name" />
|
||||||
|
<div class="is-size-7 is-uppercase">
|
||||||
|
<span
|
||||||
|
v-text="$t('page.genre.album-count', { count: genre.album_count })"
|
||||||
|
/>
|
||||||
|
<span> | </span>
|
||||||
|
<a
|
||||||
|
@click="open_tracks"
|
||||||
|
v-text="$t('page.genre.track-count', { count: genre.track_count })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<div class="buttons is-centered">
|
||||||
@ -22,17 +32,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p class="heading has-text-centered-mobile">
|
|
||||||
<span
|
|
||||||
v-text="$t('page.genre.album-count', { count: genre.album_count })"
|
|
||||||
/>
|
|
||||||
<span> | </span>
|
|
||||||
<a
|
|
||||||
class="has-text-link"
|
|
||||||
@click="open_tracks"
|
|
||||||
v-text="$t('page.genre.track-count', { count: genre.track_count })"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<list-albums :items="albums" />
|
<list-albums :items="albums" />
|
||||||
<modal-dialog-genre
|
<modal-dialog-genre
|
||||||
:item="genre"
|
:item="genre"
|
||||||
@ -109,5 +108,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -5,16 +5,29 @@
|
|||||||
<index-button-list :indices="tracks.indices" />
|
<index-button-list :indices="tracks.indices" />
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<p class="heading mb-5" v-text="$t('page.genre.sort.title')" />
|
<div
|
||||||
|
class="is-size-7 is-uppercase"
|
||||||
|
v-text="$t('page.genre.sort.title')"
|
||||||
|
/>
|
||||||
<control-dropdown
|
<control-dropdown
|
||||||
v-model:value="selected_grouping_id"
|
v-model:value="uiStore.genre_tracks_sort"
|
||||||
:options="groupings"
|
:options="groupings"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="genre.name" />
|
<div class="title is-4" v-text="genre.name" />
|
||||||
|
<div class="is-size-7 is-uppercase">
|
||||||
|
<a
|
||||||
|
@click="open_genre"
|
||||||
|
v-text="$t('page.genre.album-count', { count: genre.album_count })"
|
||||||
|
/>
|
||||||
|
<span> | </span>
|
||||||
|
<span
|
||||||
|
v-text="$t('page.genre.track-count', { count: genre.track_count })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #heading-right>
|
<template #heading-right>
|
||||||
<div class="buttons is-centered">
|
<div class="buttons is-centered">
|
||||||
@ -31,17 +44,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<p class="heading has-text-centered-mobile">
|
|
||||||
<a
|
|
||||||
class="has-text-link"
|
|
||||||
@click="open_genre"
|
|
||||||
v-text="$t('page.genre.album-count', { count: genre.album_count })"
|
|
||||||
/>
|
|
||||||
<span> | </span>
|
|
||||||
<span
|
|
||||||
v-text="$t('page.genre.track-count', { count: genre.track_count })"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<list-tracks :items="tracks" :expression="expression" />
|
<list-tracks :items="tracks" :expression="expression" />
|
||||||
<modal-dialog-genre
|
<modal-dialog-genre
|
||||||
:item="genre"
|
:item="genre"
|
||||||
@ -126,17 +128,9 @@ export default {
|
|||||||
expression() {
|
expression() {
|
||||||
return `genre is "${this.genre.name}" and media_kind is ${this.media_kind}`
|
return `genre is "${this.genre.name}" and media_kind is ${this.media_kind}`
|
||||||
},
|
},
|
||||||
selected_grouping_id: {
|
|
||||||
get() {
|
|
||||||
return this.uiStore.genre_tracks_sort
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
this.uiStore.genre_tracks_sort = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tracks() {
|
tracks() {
|
||||||
const { options } = this.groupings.find(
|
const { options } = this.groupings.find(
|
||||||
(grouping) => grouping.id === this.selected_grouping_id
|
(grouping) => grouping.id === this.uiStore.genre_tracks_sort
|
||||||
)
|
)
|
||||||
return this.tracks_list.group(options)
|
return this.tracks_list.group(options)
|
||||||
}
|
}
|
||||||
@ -157,5 +151,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #options>
|
<template #options>
|
||||||
<index-button-list :indices="genres.indices" />
|
<index-button-list :indices="genres.indices" />
|
||||||
</template>
|
</template>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t('page.genres.title')" />
|
<div class="title is-4" v-text="$t('page.genres.title')" />
|
||||||
<p
|
<div
|
||||||
class="heading"
|
class="is-size-7 is-uppercase"
|
||||||
v-text="$t('page.genres.count', { count: genres.total })"
|
v-text="$t('page.genres.count', { count: genres.total })"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -61,5 +61,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<nav class="level">
|
<nav class="level">
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<router-link
|
<router-link
|
||||||
class="button is-light is-small is-rounded"
|
class="button is-small is-rounded"
|
||||||
:to="{ name: 'music-recently-added' }"
|
:to="{ name: 'music-recently-added' }"
|
||||||
>
|
>
|
||||||
{{ $t('page.music.show-more') }}
|
{{ $t('page.music.show-more') }}
|
||||||
@ -32,7 +32,7 @@
|
|||||||
<nav class="level">
|
<nav class="level">
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<router-link
|
<router-link
|
||||||
class="button is-light is-small is-rounded"
|
class="button is-small is-rounded"
|
||||||
:to="{ name: 'music-recently-played' }"
|
:to="{ name: 'music-recently-played' }"
|
||||||
>
|
>
|
||||||
{{ $t('page.music.show-more') }}
|
{{ $t('page.music.show-more') }}
|
||||||
@ -95,5 +95,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
@ -62,5 +62,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
@ -51,5 +51,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'music-spotify-new-releases' }"
|
:to="{ name: 'music-spotify-new-releases' }"
|
||||||
class="button is-light is-small is-rounded"
|
class="button is-small is-rounded"
|
||||||
>
|
>
|
||||||
{{ $t('page.spotify.music.show-more') }}
|
{{ $t('page.spotify.music.show-more') }}
|
||||||
</router-link>
|
</router-link>
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'music-spotify-featured-playlists' }"
|
:to="{ name: 'music-spotify-featured-playlists' }"
|
||||||
class="button is-light is-small is-rounded"
|
class="button is-small is-rounded"
|
||||||
>
|
>
|
||||||
{{ $t('page.spotify.music.show-more') }}
|
{{ $t('page.spotify.music.show-more') }}
|
||||||
</router-link>
|
</router-link>
|
||||||
@ -102,5 +102,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
@ -60,5 +60,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fd-page-with-tabs">
|
<div>
|
||||||
<tabs-music />
|
<tabs-music />
|
||||||
<content-with-heading>
|
<content-with-heading>
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
@ -57,5 +57,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
@ -1,56 +1,56 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="hero is-full-height">
|
<div class="hero is-full-height">
|
||||||
<div v-if="track.id > 0" class="hero-body is-flex is-align-items-center">
|
<div class="hero-body is-flex is-align-items-center">
|
||||||
<div class="container has-text-centered" style="max-width: 500px">
|
|
||||||
<cover-artwork
|
|
||||||
:url="track.artwork_url"
|
|
||||||
:artist="track.artist"
|
|
||||||
:album="track.album"
|
|
||||||
class="is-clickable fd-has-shadow fd-cover-big-image"
|
|
||||||
:class="{ 'is-masked': lyricsStore.pane }"
|
|
||||||
@click="open_dialog(track)"
|
|
||||||
/>
|
|
||||||
<lyrics-pane v-if="lyricsStore.pane" />
|
|
||||||
<control-slider
|
|
||||||
v-model:value="track_progress"
|
|
||||||
class="mt-5"
|
|
||||||
:disabled="is_live"
|
|
||||||
:max="track_progress_max"
|
|
||||||
:cursor="cursor"
|
|
||||||
@change="seek"
|
|
||||||
@mousedown="start_dragging"
|
|
||||||
@mouseup="end_dragging"
|
|
||||||
/>
|
|
||||||
<div class="is-flex is-justify-content-space-between">
|
|
||||||
<p class="subtitle is-7" v-text="track_elapsed_time" />
|
|
||||||
<p class="subtitle is-7" v-text="track_total_time" />
|
|
||||||
</div>
|
|
||||||
<p class="title is-5" v-text="track.title" />
|
|
||||||
<p class="title is-6" v-text="track.artist" />
|
|
||||||
<p
|
|
||||||
v-if="composer"
|
|
||||||
class="subtitle is-6 has-text-grey has-text-weight-bold"
|
|
||||||
v-text="composer"
|
|
||||||
/>
|
|
||||||
<p v-if="track.album" class="subtitle is-6" v-text="track.album" />
|
|
||||||
<p
|
|
||||||
v-if="settingsStore.show_filepath_now_playing"
|
|
||||||
class="subtitle is-6 has-text-grey"
|
|
||||||
v-text="track.path"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="hero-body is-flex is-align-items-center">
|
|
||||||
<div class="container has-text-centered">
|
<div class="container has-text-centered">
|
||||||
<p class="title is-5" v-text="$t('page.now-playing.title')" />
|
<div v-if="track.id" class="mx-auto" style="max-width: 32rem">
|
||||||
<p class="subtitle" v-text="$t('page.now-playing.info')" />
|
<cover-artwork
|
||||||
|
:url="track.artwork_url"
|
||||||
|
:artist="track.artist"
|
||||||
|
:album="track.album"
|
||||||
|
class="is-clickable fd-has-shadow fd-cover-big-image"
|
||||||
|
:class="{ 'is-masked': lyricsStore.pane }"
|
||||||
|
@click="open_dialog(track)"
|
||||||
|
/>
|
||||||
|
<lyrics-pane v-if="lyricsStore.pane" />
|
||||||
|
<control-slider
|
||||||
|
v-model:value="track_progress"
|
||||||
|
class="mt-5"
|
||||||
|
:disabled="is_live"
|
||||||
|
:max="track_progress_max"
|
||||||
|
:cursor="cursor"
|
||||||
|
@change="seek"
|
||||||
|
@mousedown="start_dragging"
|
||||||
|
@mouseup="end_dragging"
|
||||||
|
/>
|
||||||
|
<div class="is-flex is-justify-content-space-between">
|
||||||
|
<p class="subtitle is-7" v-text="track_elapsed_time" />
|
||||||
|
<p class="subtitle is-7" v-text="track_total_time" />
|
||||||
|
</div>
|
||||||
|
<p class="title is-5" v-text="track.title" />
|
||||||
|
<p class="title is-6" v-text="track.artist" />
|
||||||
|
<p
|
||||||
|
v-if="composer"
|
||||||
|
class="subtitle is-6 has-text-grey has-text-weight-bold"
|
||||||
|
v-text="composer"
|
||||||
|
/>
|
||||||
|
<p v-if="track.album" class="subtitle is-6" v-text="track.album" />
|
||||||
|
<p
|
||||||
|
v-if="settingsStore.show_filepath_now_playing"
|
||||||
|
class="subtitle is-6 has-text-grey"
|
||||||
|
v-text="track.path"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<p class="title is-5" v-text="$t('page.now-playing.title')" />
|
||||||
|
<p class="subtitle" v-text="$t('page.now-playing.info')" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<modal-dialog-queue-item
|
||||||
|
:show="show_details_modal"
|
||||||
|
:item="selected_item"
|
||||||
|
@close="show_details_modal = false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<modal-dialog-queue-item
|
|
||||||
:show="show_details_modal"
|
|
||||||
:item="selected_item"
|
|
||||||
@close="show_details_modal = false"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -196,5 +196,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user