diff --git a/frontend/package-lock.json b/frontend/package-lock.json index df79999..faaaffb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "core-js": "^3.8.3", "cors": "^2.8.5", + "music-metadata": "^7.13.0", "vue": "^3.2.13", "vue-router": "^4.0.3" }, @@ -2261,6 +2262,11 @@ "node": ">=6" } }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.0.tgz", @@ -5215,7 +5221,6 @@ "version": "1.0.5", "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -5666,7 +5671,6 @@ "version": "4.3.4", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -6997,6 +7001,22 @@ "node": ">=4" } }, + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "dependencies": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/filelist/-/filelist-1.0.4.tgz", @@ -8000,8 +8020,7 @@ "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "node_modules/ignore": { "version": "5.2.4", @@ -8077,8 +8096,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { "version": "2.0.0", @@ -9444,8 +9462,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -9460,6 +9477,35 @@ "multicast-dns": "cli.js" } }, + "node_modules/music-metadata": { + "version": "7.13.4", + "resolved": "https://registry.npmjs.org/music-metadata/-/music-metadata-7.13.4.tgz", + "integrity": "sha512-eRRoEMhhYdth2Ws24FmkvIqrtkIBE9sqjHbrRNpkg2Iux3zc37PQKRv2/r/mTtELb7XlB1uWC2UcKKX7BzNMGA==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "content-type": "^1.0.5", + "debug": "^4.3.4", + "file-type": "^16.5.4", + "media-typer": "^1.1.0", + "strtok3": "^6.3.0", + "token-types": "^4.2.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/music-metadata/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", @@ -10072,6 +10118,18 @@ "node": ">=8" } }, + "node_modules/peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", @@ -11008,7 +11066,6 @@ "version": "3.6.2", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -11018,6 +11075,21 @@ "node": ">= 6" } }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", @@ -11348,8 +11420,7 @@ "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -11964,7 +12035,6 @@ "version": "1.3.0", "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -12022,6 +12092,22 @@ "node": ">=0.10.0" } }, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz", @@ -12446,6 +12532,22 @@ "node": ">=0.6" } }, + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/totalist": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/totalist/-/totalist-1.1.0.tgz", @@ -12850,8 +12952,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utila": { "version": "0.4.0", @@ -15934,6 +16035,11 @@ "defer-to-connect": "^1.0.1" } }, + "@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.0.tgz", @@ -18414,8 +18520,7 @@ "content-type": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "convert-source-map": { "version": "1.9.0", @@ -18762,7 +18867,6 @@ "version": "4.3.4", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -19844,6 +19948,16 @@ "escape-string-regexp": "^1.0.5" } }, + "file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "requires": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + } + }, "filelist": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/filelist/-/filelist-1.0.4.tgz", @@ -20639,8 +20753,7 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "5.2.4", @@ -20701,8 +20814,7 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "2.0.0", @@ -21809,8 +21921,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { "version": "7.2.5", @@ -21822,6 +21933,27 @@ "thunky": "^1.0.2" } }, + "music-metadata": { + "version": "7.13.4", + "resolved": "https://registry.npmjs.org/music-metadata/-/music-metadata-7.13.4.tgz", + "integrity": "sha512-eRRoEMhhYdth2Ws24FmkvIqrtkIBE9sqjHbrRNpkg2Iux3zc37PQKRv2/r/mTtELb7XlB1uWC2UcKKX7BzNMGA==", + "requires": { + "@tokenizer/token": "^0.3.0", + "content-type": "^1.0.5", + "debug": "^4.3.4", + "file-type": "^16.5.4", + "media-typer": "^1.1.0", + "strtok3": "^6.3.0", + "token-types": "^4.2.1" + }, + "dependencies": { + "media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==" + } + } + }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", @@ -22308,6 +22440,11 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==" + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", @@ -22973,13 +23110,20 @@ "version": "3.6.2", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, + "readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "requires": { + "readable-stream": "^3.6.0" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", @@ -23248,8 +23392,7 @@ "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", @@ -23783,7 +23926,6 @@ "version": "1.3.0", "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "requires": { "safe-buffer": "~5.2.0" } @@ -23826,6 +23968,15 @@ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true }, + "strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "requires": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + } + }, "stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz", @@ -24166,6 +24317,15 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, + "token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "requires": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + } + }, "totalist": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/totalist/-/totalist-1.1.0.tgz", @@ -24494,8 +24654,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utila": { "version": "0.4.0", diff --git a/frontend/package.json b/frontend/package.json index ab03099..684ccd3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,6 +14,7 @@ "dependencies": { "core-js": "^3.8.3", "cors": "^2.8.5", + "music-metadata": "^7.13.0", "vue": "^3.2.13", "vue-router": "^4.0.3" }, diff --git a/frontend/public/icon-font.css b/frontend/public/icon-font.css new file mode 100644 index 0000000..c221497 --- /dev/null +++ b/frontend/public/icon-font.css @@ -0,0 +1,24 @@ +/* fallback */ +@font-face { + font-family: 'Material Symbols Outlined'; + font-style: normal; + font-weight: 100 700; + src: url(/iconFont.woff2) format('woff2'); + } + + .material-symbols-outlined { + font-family: 'Material Symbols Outlined'; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + white-space: nowrap; + word-wrap: normal; + direction: ltr; + -moz-font-feature-settings: 'liga'; + -moz-osx-font-smoothing: grayscale; + } + \ No newline at end of file diff --git a/frontend/public/iconFont.woff2 b/frontend/public/iconFont.woff2 new file mode 100644 index 0000000..3ac032b Binary files /dev/null and b/frontend/public/iconFont.woff2 differ diff --git a/frontend/public/index.html b/frontend/public/index.html index 3e5a139..bf26c93 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -5,6 +5,7 @@ + <%= htmlWebpackPlugin.options.title %> diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 3f6b7f4..aeeabbb 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -17,7 +17,7 @@ --hover-color: rgb(165, 165, 165); --accent-background-hover: rgb(124, 140, 236); --overlay-color: rgba(0, 0, 0, 0.7); - --inactive-color: rgb(100, 100, 100); + --border-color: rgb(100, 100, 100); --highlight-backdrop: rgb(143, 134, 192); --hint-color: rgb(174, 210, 221); --PI: 3.14159265358979; @@ -33,7 +33,7 @@ --hover-color: rgb(83, 83, 83); --accent-background-hover: #4380a8; --overlay-color: rgba(104, 104, 104, 0.575); - --inactive-color: rgb(190, 190, 190); + --border-color: rgb(190, 190, 190); --highlight-backdrop: rgb(85, 63, 207); --hint-color: rgb(88, 91, 110); } @@ -49,7 +49,7 @@ --hover-color: rgb(83, 83, 83); --accent-background-hover: #4380a8; --overlay-color: rgba(104, 104, 104, 0.575); - --inactive-color: rgb(190, 190, 190); + --border-color: rgb(190, 190, 190); --highlight-backdrop: rgb(85, 63, 207); --hint-color: rgb(88, 91, 110); } @@ -76,6 +76,8 @@ height: 100%; margin: 0; padding: 0; + background-color: var( --background-color ); + color: var( --primary-color ); } #app { diff --git a/frontend/src/app.js b/frontend/src/app.js index 947675e..1528fdd 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -4,43 +4,105 @@ const path = require( 'path' ); const cors = require( 'cors' ); const fs = require( 'fs' ); const bodyParser = require( 'body-parser' ); +const musicMetadata = require( 'music-metadata' ); const dialog = require( 'electron' ).dialog; app.use( bodyParser.urlencoded( { extended: false } ) ); app.use( bodyParser.json() ); app.use( cors() ); +let indexedData = {}; +let coverArtIndex = {}; +const allowedFileTypes = [ '.mp3', '.wav', '.flac' ] + app.get( '/', ( request, response ) => { response.send( 'Hello world' ); } ); app.get( '/openSongs', ( req, res ) => { - res.send( '{ "data": [ "/home/janis/Music/KB2022" ] }' ) + // res.send( '{ "data": [ "/home/janis/Music/KB2022" ] }' ); + res.send( '{ "data": [ "/mnt/storage/SORTED/Music/audio/KB2022" ] }' ); // res.send( { 'data': dialog.showOpenDialogSync( { properties: [ 'openDirectory' ], title: 'Open music library folder' } ) } ); } ); app.get( '/indexDirs', ( req, res ) => { if ( req.query.dir ) { - fs.readdir( req.query.dir, { encoding: 'utf-8' }, ( err, dat ) => { - if ( err ) res.status( 500 ).send( 'err' ); - res.send( dat ); - } ); + if ( indexedData[ req.query.dir ] ) { + console.log( 'using cache' ); + res.send( indexedData[ req.query.dir ] ); + } else { + fs.readdir( req.query.dir, { encoding: 'utf-8' }, ( err, dat ) => { + if ( err ) res.status( 500 ).send( err ); + ( async() => { + // TODO: Check for songlist.csv or songlist.json file and use the data provided there for each song to override + // what was found automatically. If no song title was found in songlist or metadata, use filename + let files = {}; + for ( let file in dat ) { + if ( allowedFileTypes.includes( dat[ file ].slice( dat[ file ].indexOf( '.' ), dat[ file ].length ) ) ) { + try { + let metadata = await musicMetadata.parseFile( req.query.dir + '/' + dat[ file ] ); + files[ req.query.dir + '/' + dat[ file ] ] = { + 'artist': metadata[ 'common' ][ 'artist' ], + 'title': metadata[ 'common' ][ 'title' ], + 'year': metadata[ 'common' ][ 'year' ], + 'bpm': metadata[ 'common' ][ 'bpm' ], + 'genre': metadata[ 'common' ][ 'genre' ], + 'duration': metadata[ 'format' ][ 'duration' ], + 'isLossless': metadata[ 'format' ][ 'lossless' ], + 'sampleRate': metadata[ 'format' ][ 'sampleRate' ], + 'bitrate': metadata[ 'format' ][ 'bitrate' ], + 'numberOfChannels': metadata[ 'format' ][ 'numberOfChannels' ], + 'container': metadata[ 'format' ][ 'container' ], + 'filename': req.query.dir + '/' + dat[ file ], + } + if ( metadata[ 'common' ][ 'picture' ] ) { + files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = true; + if ( req.query.coverart == 'true' ) { + coverArtIndex[ req.query.dir + '/' + dat[ file ] ] = metadata[ 'common' ][ 'picture' ] ? metadata[ 'common' ][ 'picture' ][ 0 ][ 'data' ] : undefined; + } + } else { + files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; + } + } catch ( err ) { + files[ req.query.dir + '/' + dat[ file ] ] = 'ERROR'; + } + } + } + indexedData[ req.query.dir ] = files; + res.send( files ); + } )(); + } ); + } } else { res.status( 400 ).send( 'ERR_REQ_INCOMPLETE' ); } } ); -app.get( '/getSongDetails', ( req, res ) => { +app.get( '/getSongCover', ( req, res ) => { if ( req.query.filename ) { - fs.readFile( req.query.filename, ( err, data ) => { - res.send( '' + data ); - } ); + if ( coverArtIndex[ req.query.filename ] ) { + res.send( coverArtIndex[ req.query.filename ] ); + } else { + res.status( 404 ).send( 'No cover image for this file' ); + } + } else { res.status( 400 ).send( 'ERR_REQ_INCOMPLETE' ); } } ); +app.get( '/getSongFile', ( req, res ) => { + if ( req.query.filename ) { + res.sendFile( req.query.filename ); + } else { + res.status( 400 ).send( 'ERR_REQ_INCOMPLETE' ); + } +} ); + +// TODO: Add get lyrics route later +// 'lyrics': metadata[ 'common' ][ 'lyrics' ], + app.use( ( request, response, next ) => { response.sendFile( path.join( __dirname + '' ) ) diff --git a/frontend/src/assets/loadingSymbol.svg b/frontend/src/assets/loadingSymbol.svg new file mode 100644 index 0000000..60646d6 --- /dev/null +++ b/frontend/src/assets/loadingSymbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/components/mediaPool.vue b/frontend/src/components/mediaPool.vue index 3c481ee..5fc52d6 100644 --- a/frontend/src/components/mediaPool.vue +++ b/frontend/src/components/mediaPool.vue @@ -1,7 +1,17 @@ \ No newline at end of file diff --git a/frontend/src/views/HomeView.vue b/frontend/src/views/HomeView.vue index 3c4d9c7..6a610de 100644 --- a/frontend/src/views/HomeView.vue +++ b/frontend/src/views/HomeView.vue @@ -3,11 +3,11 @@
- +
- +
@@ -51,11 +51,13 @@