diff --git a/package.json b/package.json index 132175e..eaf0f61 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,10 @@ }, "type": "module", "dependencies": { + "jotai": "^2.8.0", + "jotai-svelte": "^0.0.2", "localforage": "^1.10.0", + "music-metadata-browser": "^2.5.10", "uuid": "^9.0.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8b4e164..5c02264 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,9 +5,18 @@ settings: excludeLinksFromLockfile: false dependencies: + jotai: + specifier: ^2.8.0 + version: 2.8.0 + jotai-svelte: + specifier: ^0.0.2 + version: 0.0.2(jotai@2.8.0) localforage: specifier: ^1.10.0 version: 1.10.0 + music-metadata-browser: + specifier: ^2.5.10 + version: 2.5.10 uuid: specifier: ^9.0.1 version: 9.0.1 @@ -645,6 +654,10 @@ packages: - supports-color dev: true + /@tokenizer/token@0.3.0: + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + dev: false + /@types/cookie@0.6.0: resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} dev: true @@ -711,6 +724,13 @@ packages: pretty-format: 29.7.0 dev: true + /abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + dependencies: + event-target-shim: 5.0.1 + dev: false + /acorn-jsx@5.3.2(acorn@8.11.3): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -822,6 +842,10 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + /binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -862,6 +886,13 @@ packages: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} dev: true + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -957,6 +988,11 @@ packages: resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} dev: true + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + /cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} @@ -995,7 +1031,6 @@ packages: optional: true dependencies: ms: 2.1.2 - dev: true /deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} @@ -1259,6 +1294,16 @@ packages: engines: {node: '>=0.10.0'} dev: true + /event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + dev: false + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: false + /execa@8.0.1: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} @@ -1310,6 +1355,15 @@ packages: flat-cache: 3.2.0 dev: true + /file-type@16.5.4: + resolution: {integrity: sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==} + engines: {node: '>=10'} + dependencies: + readable-web-to-node-stream: 3.0.2 + strtok3: 6.3.0 + token-types: 4.2.1 + dev: false + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -1452,6 +1506,10 @@ packages: engines: {node: '>=16.17.0'} dev: true + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -1487,7 +1545,6 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} @@ -1558,6 +1615,27 @@ packages: hasBin: true dev: true + /jotai-svelte@0.0.2(jotai@2.8.0): + resolution: {integrity: sha512-dPxBEIIMNkfgtXvvyiiCW5ds1VeAyeyxfIu5qeXb7VSgvNgqU/lCKld3ue7yRLdcRJUx2ddocI49WTzzNp/uGQ==} + peerDependencies: + jotai: '>=1.12.0' + dependencies: + jotai: 2.8.0 + dev: false + + /jotai@2.8.0: + resolution: {integrity: sha512-yZNMC36FdLOksOr8qga0yLf14miCJlEThlp5DeFJNnqzm2+ZG7wLcJzoOyij5K6U6Xlc5ljQqPDlJRgqW0Y18g==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=17.0.0' + react: '>=17.0.0' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + dev: false + /js-tokens@9.0.0: resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} dev: true @@ -1681,6 +1759,11 @@ packages: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} dev: true + /media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + dev: false + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -1758,7 +1841,33 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true + + /music-metadata-browser@2.5.10: + resolution: {integrity: sha512-03UnAmsSJoZZ5kK2BnEnd2zpH8LXRWQ6xlc7akKudhc2d9FT+yAiqapnmOzjW3g4cxxvIsSK5MVBO2Gi+Ymjfw==} + dependencies: + buffer: 6.0.3 + debug: 4.3.4 + music-metadata: 7.14.0 + readable-stream: 4.5.2 + readable-web-to-node-stream: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: false + + /music-metadata@7.14.0: + resolution: {integrity: sha512-xrm3w7SV0Wk+OythZcSbaI8mcr/KHd0knJieu8bVpaPfMv/Agz5EooCAPz3OR5hbYMiUG6dgAPKZKnMzV+3amA==} + engines: {node: '>=10'} + 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 + transitivePeerDependencies: + - supports-color + dev: false /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -1902,6 +2011,11 @@ packages: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} dev: true + /peek-readable@4.1.0: + resolution: {integrity: sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==} + engines: {node: '>=8'} + dev: false + /periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} dependencies: @@ -2072,6 +2186,11 @@ packages: react-is: 18.3.1 dev: true + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: false + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2091,6 +2210,33 @@ packages: pify: 2.3.0 dev: true + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /readable-stream@4.5.2: + resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + dev: false + + /readable-web-to-node-stream@3.0.2: + resolution: {integrity: sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==} + engines: {node: '>=8'} + dependencies: + readable-stream: 3.6.2 + dev: false + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2170,6 +2316,10 @@ packages: mri: 1.2.0 dev: true + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + /sander@0.5.1: resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} dependencies: @@ -2262,6 +2412,12 @@ packages: strip-ansi: 7.1.0 dev: true + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2299,6 +2455,14 @@ packages: js-tokens: 9.0.0 dev: true + /strtok3@6.3.0: + resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==} + engines: {node: '>=10'} + dependencies: + '@tokenizer/token': 0.3.0 + peek-readable: 4.1.0 + dev: false + /sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -2522,6 +2686,14 @@ packages: is-number: 7.0.0 dev: true + /token-types@4.2.1: + resolution: {integrity: sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==} + engines: {node: '>=10'} + dependencies: + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + dev: false + /totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -2577,7 +2749,6 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true /uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} diff --git a/src/app.css b/src/app.css index 93ca9c9..f30d034 100644 --- a/src/app.css +++ b/src/app.css @@ -4,4 +4,8 @@ h1 { @apply text-4xl font-bold leading-[4rem]; +} + +h2 { + @apply text-3xl font-medium leading-[3rem]; } \ No newline at end of file diff --git a/src/app.html b/src/app.html index 77a5ff5..3b52a7f 100644 --- a/src/app.html +++ b/src/app.html @@ -1,12 +1,18 @@ - - - - - %sveltekit.head% - - -
%sveltekit.body%
- + + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ diff --git a/src/components/import/addIcon.svelte b/src/components/import/addIcon.svelte new file mode 100644 index 0000000..ffa4aad --- /dev/null +++ b/src/components/import/addIcon.svelte @@ -0,0 +1,17 @@ +
+ + + +
diff --git a/src/components/import/fileList.d.ts b/src/components/import/fileList.d.ts new file mode 100644 index 0000000..555018b --- /dev/null +++ b/src/components/import/fileList.d.ts @@ -0,0 +1,7 @@ +interface FileItem { + name: string; + size?: number; + type: string; + lastModified?: number; + lastModifiedDate?: Date; +} \ No newline at end of file diff --git a/src/components/import/fileList.state.ts b/src/components/import/fileList.state.ts new file mode 100644 index 0000000..dd9609f --- /dev/null +++ b/src/components/import/fileList.state.ts @@ -0,0 +1,4 @@ +import { atom } from 'jotai-svelte' + +export const fileListState = atom([] as any[]); +export const finalFileListState = atom([] as any[]); \ No newline at end of file diff --git a/src/components/import/fileList.svelte b/src/components/import/fileList.svelte new file mode 100644 index 0000000..ca03a3d --- /dev/null +++ b/src/components/import/fileList.svelte @@ -0,0 +1,57 @@ + + + diff --git a/src/components/import/fileSelector.svelte b/src/components/import/fileSelector.svelte new file mode 100644 index 0000000..34434b3 --- /dev/null +++ b/src/components/import/fileSelector.svelte @@ -0,0 +1,41 @@ + + + +
+ +
diff --git a/src/components/import/importIcon.svelte b/src/components/import/importIcon.svelte new file mode 100644 index 0000000..cf982d5 --- /dev/null +++ b/src/components/import/importIcon.svelte @@ -0,0 +1,15 @@ +
+ +
diff --git a/src/index.test.js b/src/index.test.js index e07cbbd..f5e2ff9 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -1,7 +1,20 @@ import { describe, it, expect } from 'vitest'; +import formatDuration from '$lib/formatDuration'; -describe('sum test', () => { - it('adds 1 + 2 to equal 3', () => { - expect(1 + 2).toBe(3); - }); -}); +describe('formatDuration test', () => { + it('converts 120 seconds to "2:00"', () => { + expect(formatDuration(120)).toBe('2:00'); + }); + + it('converts 185 seconds to "3:05"', () => { + expect(formatDuration(185)).toBe('3:05'); + }); + + it('converts 601 seconds to "10:01"', () => { + expect(formatDuration(601)).toBe('10:01'); + }); + + it('converts 3601 seconds to "1:00:01"', () => { + expect(formatDuration(3601)).toBe('1:00:01'); + }); +}); \ No newline at end of file diff --git a/src/lib/audioFormatText.ts b/src/lib/audioFormatText.ts new file mode 100644 index 0000000..08612ed --- /dev/null +++ b/src/lib/audioFormatText.ts @@ -0,0 +1,10 @@ +export default function(key: string){ + const dict = { + "audio/mpeg": "MP3 音频", + "audio/ogg": "OGG 容器", + "audio/flac": "FLAC 无损音频", + "audio/aac": "AAC 音频" + } + if (!key) return "未知格式"; + else return dict[key as keyof typeof dict]; +} \ No newline at end of file diff --git a/src/lib/convertCoverData.ts b/src/lib/convertCoverData.ts new file mode 100644 index 0000000..f1d49d5 --- /dev/null +++ b/src/lib/convertCoverData.ts @@ -0,0 +1,13 @@ +export default function(dataObject: any) { + // Create a blob from the UInt8Array data + const blob = new Blob([dataObject.data], { type: dataObject.format }); + + // Create a URL for the blob + const imageUrl = URL.createObjectURL(blob); + + // Create an Image object + const image = new Image(); + image.src = imageUrl; + + return imageUrl; // return the URL of the image +} \ No newline at end of file diff --git a/src/lib/extractFileName.ts b/src/lib/extractFileName.ts new file mode 100644 index 0000000..ce739d1 --- /dev/null +++ b/src/lib/extractFileName.ts @@ -0,0 +1,4 @@ +export default function(fullname: string){ + if (!fullname) return ''; + return fullname.split('.').slice(0, -1).join('.') +} \ No newline at end of file diff --git a/src/lib/formatDuration.ts b/src/lib/formatDuration.ts new file mode 100644 index 0000000..1c4324f --- /dev/null +++ b/src/lib/formatDuration.ts @@ -0,0 +1,19 @@ +export default function(durationInSeconds: number): string { + // Calculate hours, minutes, and seconds + const hours = Math.floor(durationInSeconds / 3600); + const minutes = Math.floor((durationInSeconds % 3600) / 60); + const seconds = Math.round(durationInSeconds) % 60; + + // Format hours, minutes, and seconds into string + let formattedTime = ''; + if (hours > 0) { + formattedTime += hours + ':'; + } + if (minutes < 10 && hours > 0) { + formattedTime += '0'; + } + formattedTime += minutes + ':'; + formattedTime += (seconds < 10 ? '0' : '') + seconds; + + return formattedTime; +} diff --git a/src/lib/getAudioCoverURL.ts b/src/lib/getAudioCoverURL.ts new file mode 100644 index 0000000..6fae09f --- /dev/null +++ b/src/lib/getAudioCoverURL.ts @@ -0,0 +1,11 @@ +import * as musicMetadata from 'music-metadata-browser'; +import convertCoverData from './convertCoverData'; + +export default function getAudioMeta(audio: File, callback: Function) { + musicMetadata.parseBlob(audio).then((metadata) => { + if (metadata) + callback(metadata); + else + callback(null); + }) +} diff --git a/src/lib/humanSize.ts b/src/lib/humanSize.ts new file mode 100644 index 0000000..171f64a --- /dev/null +++ b/src/lib/humanSize.ts @@ -0,0 +1,10 @@ +export default function toHumanSize(size: number | undefined){ + if (!size) return '0 B' + const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + let unitIndex = 0; + while (size >= 1000 && unitIndex < units.length - 1) { + size /= 1000; + unitIndex++; + } + return `${size.toFixed(2)} ${units[unitIndex]}` +} \ No newline at end of file diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index df2ffde..6e3f91b 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -4,7 +4,7 @@
\ No newline at end of file diff --git a/src/routes/import/local/+page.server.js b/src/routes/import/local/+page.server.js new file mode 100644 index 0000000..5829b7e --- /dev/null +++ b/src/routes/import/local/+page.server.js @@ -0,0 +1 @@ +export const ssr = false; \ No newline at end of file diff --git a/src/routes/import/local/+page.svelte b/src/routes/import/local/+page.svelte new file mode 100644 index 0000000..3c210ed --- /dev/null +++ b/src/routes/import/local/+page.svelte @@ -0,0 +1,17 @@ + + +

本地导入向导

+

欢迎使用本地导入向导!

+

+ 你可以选择从本地导入你喜欢的音乐文件,并同时将封面、歌词、歌手与制作者等其他信息一并囊括其中。 +

+ +
+

音频

+ +
+ + diff --git a/vite.config.js b/vite.config.js index 37b6a84..df0e579 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,9 +1,22 @@ import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vitest/config'; +import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill' export default defineConfig({ - plugins: [sveltekit()], - test: { - include: ['src/**/*.{test,spec}.{js,ts}'] - } + plugins: [sveltekit()], + test: { + include: ['src/**/*.{test,spec}.{js,ts}'] + }, + optimizeDeps: { + esbuildOptions: { + define: { + global: 'globalThis' + }, + plugins: [ + NodeGlobalsPolyfillPlugin({ + buffer: true + }) + ] + } + } });