From 5d5ba4007c49147ec2f2071e1cca02932824b5d7 Mon Sep 17 00:00:00 2001
From: Aresn
Date: Fri, 10 May 2024 18:09:00 +0800
Subject: [PATCH] Fri May 10 18:09:00 CST 2024 inscode
---
.dockerignore | 16 +
.editorconfig | 8 +
.env.example | 7 +
.gitattributes | 7 +
.github/ISSUE_TEMPLATE/----------.md | 21 +
.github/workflows/build.yaml | 116 +
.github/workflows/sync.yml | 48 +
.gitignore | 17 +-
.inscode | 8 +-
.nvmrc | 1 +
.prettierignore | 3 +
.prettierrc | 12 +
Dockerfile | 25 +
LICENSE | 21 +
README.md | 260 +
babel.config.js | 11 +
build/icons/1024x1024.png | Bin 0 -> 535997 bytes
build/icons/128x128.png | Bin 0 -> 6564 bytes
build/icons/16x16.png | Bin 0 -> 474 bytes
build/icons/24x24.png | Bin 0 -> 750 bytes
build/icons/256x256.png | Bin 0 -> 22892 bytes
build/icons/32x32.png | Bin 0 -> 965 bytes
build/icons/48x48.png | Bin 0 -> 1631 bytes
build/icons/512x512.png | Bin 0 -> 107173 bytes
build/icons/64x64.png | Bin 0 -> 2282 bytes
build/icons/icon.icns | Bin 0 -> 809011 bytes
build/icons/icon.ico | Bin 0 -> 361102 bytes
build/icons/icon.png | Bin 0 -> 282449 bytes
build/icons/menu@88.png | Bin 0 -> 1084 bytes
docker-compose.yml | 39 +
docker/nginx.conf.example | 28 +
images/album.png | Bin 0 -> 258656 bytes
images/artist.png | Bin 0 -> 233300 bytes
images/explore.png | Bin 0 -> 362723 bytes
images/home-2.png | Bin 0 -> 319717 bytes
images/home.png | Bin 0 -> 398056 bytes
images/library-dark.png | Bin 0 -> 343483 bytes
images/library.png | Bin 0 -> 332219 bytes
images/logo.png | Bin 0 -> 178986 bytes
images/lyrics.png | Bin 0 -> 347434 bytes
images/search.png | Bin 0 -> 282425 bytes
index.js | 1 -
install-replit.sh | 28 +
jsconfig.json | 15 +
package-lock.json | 24316 ++++++++++++++++
package.json | 145 +-
public/favicon.ico | Bin 0 -> 15086 bytes
public/img/icons/1024x1024.png | Bin 0 -> 390383 bytes
public/img/icons/128x128.png | Bin 0 -> 9650 bytes
public/img/icons/16x16.png | Bin 0 -> 523 bytes
public/img/icons/24x24.png | Bin 0 -> 913 bytes
public/img/icons/256x256.png | Bin 0 -> 35687 bytes
public/img/icons/32x32.png | Bin 0 -> 1180 bytes
public/img/icons/48x48.png | Bin 0 -> 1981 bytes
public/img/icons/512x512.png | Bin 0 -> 152336 bytes
public/img/icons/64x64.png | Bin 0 -> 2925 bytes
public/img/icons/android-chrome-192x192.png | Bin 0 -> 16395 bytes
public/img/icons/android-chrome-512x512.png | Bin 0 -> 129147 bytes
public/img/icons/apple-touch-icon-120x120.png | Bin 0 -> 3369 bytes
public/img/icons/apple-touch-icon-152x152.png | Bin 0 -> 4046 bytes
public/img/icons/apple-touch-icon-180x180.png | Bin 0 -> 4678 bytes
public/img/icons/apple-touch-icon-60x60.png | Bin 0 -> 1491 bytes
public/img/icons/apple-touch-icon-76x76.png | Bin 0 -> 1823 bytes
public/img/icons/apple-touch-icon.png | Bin 0 -> 14744 bytes
public/img/icons/exit.png | Bin 0 -> 223 bytes
public/img/icons/favicon-16x16.png | Bin 0 -> 1166 bytes
public/img/icons/favicon-32x32.png | Bin 0 -> 1562 bytes
public/img/icons/favicon.ico | Bin 0 -> 15086 bytes
public/img/icons/icon.icns | Bin 0 -> 783497 bytes
public/img/icons/icon.ico | Bin 0 -> 361102 bytes
public/img/icons/left.png | Bin 0 -> 191 bytes
public/img/icons/like.png | Bin 0 -> 308 bytes
public/img/icons/menu-dark@88.png | Bin 0 -> 1096 bytes
public/img/icons/menu-light@88.png | Bin 0 -> 1084 bytes
public/img/icons/menu.png | Bin 0 -> 311 bytes
.../img/icons/msapplication-icon-144x144.png | Bin 0 -> 1169 bytes
public/img/icons/mstile-150x150.png | Bin 0 -> 10295 bytes
public/img/icons/pause.png | Bin 0 -> 953 bytes
public/img/icons/play.png | Bin 0 -> 396 bytes
public/img/icons/repeat.png | Bin 0 -> 344 bytes
public/img/icons/right.png | Bin 0 -> 218 bytes
public/img/icons/safari-pinned-tab.svg | 3 +
public/img/icons/unlike.png | Bin 0 -> 932 bytes
public/img/logos/lastfm.png | Bin 0 -> 9135 bytes
public/img/logos/netease-music.png | Bin 0 -> 11223 bytes
public/img/logos/nyancat-stop.png | Bin 0 -> 816 bytes
public/img/logos/nyancat.gif | Bin 0 -> 29361 bytes
public/img/logos/yesplaymusic-white24x24.png | Bin 0 -> 750 bytes
public/img/logos/yesplaymusic.png | Bin 0 -> 49099 bytes
public/img/touchbar/backward.png | Bin 0 -> 801 bytes
public/img/touchbar/forward.png | Bin 0 -> 779 bytes
public/img/touchbar/like.png | Bin 0 -> 1150 bytes
public/img/touchbar/like_fill.png | Bin 0 -> 871 bytes
public/img/touchbar/next_up.png | Bin 0 -> 855 bytes
public/img/touchbar/page_next.png | Bin 0 -> 656 bytes
public/img/touchbar/page_prev.png | Bin 0 -> 610 bytes
public/img/touchbar/pause.png | Bin 0 -> 499 bytes
public/img/touchbar/play.png | Bin 0 -> 746 bytes
public/img/touchbar/search.png | Bin 0 -> 1084 bytes
public/index.html | 25 +
public/robots.txt | 2 +
restyled.yml | 7 +
src/App.vue | 148 +
src/api/album.js | 79 +
src/api/artist.js | 107 +
src/api/auth.js | 110 +
src/api/lastfm.js | 80 +
src/api/mv.js | 69 +
src/api/others.js | 50 +
src/api/playlist.js | 229 +
src/api/track.js | 148 +
src/api/user.js | 221 +
src/assets/css/global.scss | 135 +
src/assets/css/nprogress.css | 40 +
src/assets/css/plyr.css | 1811 ++
src/assets/css/slider.css | 144 +
src/assets/fonts/Barlow-Black.ttf | Bin 0 -> 105403 bytes
src/assets/fonts/Barlow-Black.woff2 | Bin 0 -> 38196 bytes
src/assets/fonts/Barlow-Bold.ttf | Bin 0 -> 102460 bytes
src/assets/fonts/Barlow-Bold.woff2 | Bin 0 -> 38284 bytes
src/assets/fonts/Barlow-ExtraBold.ttf | Bin 0 -> 104370 bytes
src/assets/fonts/Barlow-ExtraBold.woff2 | Bin 0 -> 38680 bytes
src/assets/fonts/Barlow-Medium.ttf | Bin 0 -> 97763 bytes
src/assets/fonts/Barlow-Medium.woff2 | Bin 0 -> 37076 bytes
src/assets/fonts/Barlow-Regular.ttf | Bin 0 -> 98327 bytes
src/assets/fonts/Barlow-Regular.woff2 | Bin 0 -> 37168 bytes
src/assets/fonts/Barlow-SemiBold.ttf | Bin 0 -> 102537 bytes
src/assets/fonts/Barlow-SemiBold.woff2 | Bin 0 -> 38324 bytes
src/assets/icons/arrow-down.svg | 1 +
src/assets/icons/arrow-left.svg | 1 +
src/assets/icons/arrow-right.svg | 1 +
src/assets/icons/arrow-up-alt.svg | 1 +
src/assets/icons/arrow-up.svg | 1 +
src/assets/icons/dropdown.svg | 1 +
src/assets/icons/explicit.svg | 1 +
src/assets/icons/fm.svg | 1 +
src/assets/icons/github.svg | 1 +
src/assets/icons/heart-solid.svg | 2 +
src/assets/icons/heart.svg | 2 +
src/assets/icons/index.js | 7 +
src/assets/icons/list.svg | 1 +
src/assets/icons/lock.svg | 1 +
src/assets/icons/login.svg | 1 +
src/assets/icons/logout.svg | 1 +
src/assets/icons/mail.svg | 1 +
src/assets/icons/mobile.svg | 1 +
src/assets/icons/more.svg | 1 +
src/assets/icons/next.svg | 1 +
src/assets/icons/pause.svg | 1 +
src/assets/icons/play.svg | 1 +
src/assets/icons/plus.svg | 1 +
src/assets/icons/previous.svg | 1 +
src/assets/icons/repeat-1.svg | 1 +
src/assets/icons/repeat.svg | 1 +
src/assets/icons/search.svg | 1 +
src/assets/icons/settings.svg | 1 +
src/assets/icons/shuffle.svg | 1 +
src/assets/icons/sort-up.svg | 2 +
src/assets/icons/thumbs-down.svg | 1 +
src/assets/icons/volume-half.svg | 1 +
src/assets/icons/volume-mute.svg | 1 +
src/assets/icons/volume.svg | 1 +
src/assets/icons/x.svg | 1 +
src/background.js | 489 +
src/components/ArtistsInLine.vue | 53 +
src/components/ButtonIcon.vue | 36 +
src/components/ButtonTwoTone.vue | 96 +
src/components/ContextMenu.vue | 181 +
src/components/Cover.vue | 171 +
src/components/CoverRow.vue | 201 +
src/components/DailyTracksCard.vue | 172 +
src/components/ExplicitSymbol.vue | 35 +
src/components/FMCard.vue | 193 +
src/components/LinuxTitlebar.vue | 130 +
src/components/Modal.vue | 193 +
src/components/ModalAddTrackToPlaylist.vue | 174 +
src/components/ModalNewPlaylist.vue | 154 +
src/components/MvRow.vue | 177 +
src/components/Navbar.vue | 349 +
src/components/Player.vue | 447 +
src/components/Scrollbar.vue | 198 +
src/components/SvgIcon.vue | 39 +
src/components/Toast.vue | 51 +
src/components/TrackList.vue | 312 +
src/components/TrackListItem.vue | 446 +
src/components/Win32Titlebar.vue | 121 +
src/electron/dockMenu.js | 25 +
src/electron/globalShortcut.js | 58 +
src/electron/ipcMain.js | 323 +
src/electron/ipcRenderer.js | 94 +
src/electron/menu.js | 220 +
src/electron/mpris.js | 94 +
src/electron/services.js | 14 +
src/electron/touchBar.js | 97 +
src/electron/tray.js | 216 +
src/locale/index.js | 25 +
src/locale/lang/en.js | 257 +
src/locale/lang/tr.js | 238 +
src/locale/lang/zh-CN.js | 256 +
src/locale/lang/zh-TW.js | 253 +
src/main.js | 48 +
src/ncmModDef.js | 617 +
src/registerServiceWorker.js | 34 +
src/router/index.js | 171 +
src/store/actions.js | 201 +
src/store/index.js | 67 +
src/store/initLocalStorage.js | 53 +
src/store/mutations.js | 78 +
src/store/plugins/localStorage.js | 7 +
src/store/plugins/sendSettings.js | 11 +
src/store/state.js | 54 +
src/utils/Player.js | 998 +
src/utils/auth.js | 56 +
src/utils/base64.js | 67 +
src/utils/checkAuthToken.js | 8 +
src/utils/common.js | 227 +
src/utils/db.js | 183 +
src/utils/filters.js | 113 +
src/utils/lyrics.js | 86 +
src/utils/nativeAlert.js | 30 +
src/utils/platform.js | 7 +
src/utils/playList.js | 61 +
src/utils/request.js | 92 +
src/utils/shortcuts.js | 47 +
src/utils/staticData.js | 420 +
src/utils/updateApp.js | 62 +
src/views/album.vue | 438 +
src/views/artist.vue | 547 +
src/views/artistMV.vue | 100 +
src/views/dailyTracks.vue | 132 +
src/views/explore.vue | 300 +
src/views/home.vue | 205 +
src/views/lastfmCallback.vue | 96 +
src/views/library.vue | 624 +
src/views/login.vue | 151 +
src/views/loginAccount.vue | 491 +
src/views/loginUsername.vue | 205 +
src/views/lyrics.vue | 1028 +
src/views/mv.vue | 225 +
src/views/newAlbum.vue | 49 +
src/views/next.vue | 142 +
src/views/playlist.vue | 948 +
src/views/search.vue | 288 +
src/views/searchType.vue | 161 +
src/views/settings.vue | 1714 ++
vercel.example.json | 8 +
vue.config.js | 208 +
yarn.lock | 13767 +++++++++
248 files changed, 60797 insertions(+), 21 deletions(-)
create mode 100644 .dockerignore
create mode 100644 .editorconfig
create mode 100644 .env.example
create mode 100644 .gitattributes
create mode 100644 .github/ISSUE_TEMPLATE/----------.md
create mode 100644 .github/workflows/build.yaml
create mode 100644 .github/workflows/sync.yml
create mode 100644 .nvmrc
create mode 100644 .prettierignore
create mode 100644 .prettierrc
create mode 100644 Dockerfile
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 babel.config.js
create mode 100644 build/icons/1024x1024.png
create mode 100644 build/icons/128x128.png
create mode 100644 build/icons/16x16.png
create mode 100644 build/icons/24x24.png
create mode 100644 build/icons/256x256.png
create mode 100644 build/icons/32x32.png
create mode 100644 build/icons/48x48.png
create mode 100644 build/icons/512x512.png
create mode 100644 build/icons/64x64.png
create mode 100644 build/icons/icon.icns
create mode 100644 build/icons/icon.ico
create mode 100644 build/icons/icon.png
create mode 100644 build/icons/menu@88.png
create mode 100644 docker-compose.yml
create mode 100644 docker/nginx.conf.example
create mode 100644 images/album.png
create mode 100644 images/artist.png
create mode 100644 images/explore.png
create mode 100644 images/home-2.png
create mode 100644 images/home.png
create mode 100644 images/library-dark.png
create mode 100644 images/library.png
create mode 100644 images/logo.png
create mode 100644 images/lyrics.png
create mode 100644 images/search.png
delete mode 100644 index.js
create mode 100644 install-replit.sh
create mode 100644 jsconfig.json
create mode 100644 package-lock.json
create mode 100644 public/favicon.ico
create mode 100644 public/img/icons/1024x1024.png
create mode 100644 public/img/icons/128x128.png
create mode 100644 public/img/icons/16x16.png
create mode 100644 public/img/icons/24x24.png
create mode 100644 public/img/icons/256x256.png
create mode 100644 public/img/icons/32x32.png
create mode 100644 public/img/icons/48x48.png
create mode 100644 public/img/icons/512x512.png
create mode 100644 public/img/icons/64x64.png
create mode 100644 public/img/icons/android-chrome-192x192.png
create mode 100644 public/img/icons/android-chrome-512x512.png
create mode 100644 public/img/icons/apple-touch-icon-120x120.png
create mode 100644 public/img/icons/apple-touch-icon-152x152.png
create mode 100644 public/img/icons/apple-touch-icon-180x180.png
create mode 100644 public/img/icons/apple-touch-icon-60x60.png
create mode 100644 public/img/icons/apple-touch-icon-76x76.png
create mode 100644 public/img/icons/apple-touch-icon.png
create mode 100644 public/img/icons/exit.png
create mode 100644 public/img/icons/favicon-16x16.png
create mode 100644 public/img/icons/favicon-32x32.png
create mode 100644 public/img/icons/favicon.ico
create mode 100644 public/img/icons/icon.icns
create mode 100644 public/img/icons/icon.ico
create mode 100644 public/img/icons/left.png
create mode 100644 public/img/icons/like.png
create mode 100644 public/img/icons/menu-dark@88.png
create mode 100644 public/img/icons/menu-light@88.png
create mode 100644 public/img/icons/menu.png
create mode 100644 public/img/icons/msapplication-icon-144x144.png
create mode 100644 public/img/icons/mstile-150x150.png
create mode 100644 public/img/icons/pause.png
create mode 100644 public/img/icons/play.png
create mode 100644 public/img/icons/repeat.png
create mode 100644 public/img/icons/right.png
create mode 100644 public/img/icons/safari-pinned-tab.svg
create mode 100644 public/img/icons/unlike.png
create mode 100644 public/img/logos/lastfm.png
create mode 100644 public/img/logos/netease-music.png
create mode 100644 public/img/logos/nyancat-stop.png
create mode 100644 public/img/logos/nyancat.gif
create mode 100644 public/img/logos/yesplaymusic-white24x24.png
create mode 100644 public/img/logos/yesplaymusic.png
create mode 100644 public/img/touchbar/backward.png
create mode 100644 public/img/touchbar/forward.png
create mode 100644 public/img/touchbar/like.png
create mode 100644 public/img/touchbar/like_fill.png
create mode 100644 public/img/touchbar/next_up.png
create mode 100644 public/img/touchbar/page_next.png
create mode 100644 public/img/touchbar/page_prev.png
create mode 100644 public/img/touchbar/pause.png
create mode 100644 public/img/touchbar/play.png
create mode 100644 public/img/touchbar/search.png
create mode 100644 public/index.html
create mode 100644 public/robots.txt
create mode 100644 restyled.yml
create mode 100644 src/App.vue
create mode 100644 src/api/album.js
create mode 100644 src/api/artist.js
create mode 100644 src/api/auth.js
create mode 100644 src/api/lastfm.js
create mode 100644 src/api/mv.js
create mode 100644 src/api/others.js
create mode 100644 src/api/playlist.js
create mode 100644 src/api/track.js
create mode 100644 src/api/user.js
create mode 100644 src/assets/css/global.scss
create mode 100644 src/assets/css/nprogress.css
create mode 100644 src/assets/css/plyr.css
create mode 100644 src/assets/css/slider.css
create mode 100644 src/assets/fonts/Barlow-Black.ttf
create mode 100644 src/assets/fonts/Barlow-Black.woff2
create mode 100644 src/assets/fonts/Barlow-Bold.ttf
create mode 100644 src/assets/fonts/Barlow-Bold.woff2
create mode 100644 src/assets/fonts/Barlow-ExtraBold.ttf
create mode 100644 src/assets/fonts/Barlow-ExtraBold.woff2
create mode 100644 src/assets/fonts/Barlow-Medium.ttf
create mode 100644 src/assets/fonts/Barlow-Medium.woff2
create mode 100644 src/assets/fonts/Barlow-Regular.ttf
create mode 100644 src/assets/fonts/Barlow-Regular.woff2
create mode 100644 src/assets/fonts/Barlow-SemiBold.ttf
create mode 100644 src/assets/fonts/Barlow-SemiBold.woff2
create mode 100644 src/assets/icons/arrow-down.svg
create mode 100644 src/assets/icons/arrow-left.svg
create mode 100644 src/assets/icons/arrow-right.svg
create mode 100644 src/assets/icons/arrow-up-alt.svg
create mode 100644 src/assets/icons/arrow-up.svg
create mode 100644 src/assets/icons/dropdown.svg
create mode 100644 src/assets/icons/explicit.svg
create mode 100644 src/assets/icons/fm.svg
create mode 100644 src/assets/icons/github.svg
create mode 100644 src/assets/icons/heart-solid.svg
create mode 100644 src/assets/icons/heart.svg
create mode 100644 src/assets/icons/index.js
create mode 100644 src/assets/icons/list.svg
create mode 100644 src/assets/icons/lock.svg
create mode 100644 src/assets/icons/login.svg
create mode 100644 src/assets/icons/logout.svg
create mode 100644 src/assets/icons/mail.svg
create mode 100644 src/assets/icons/mobile.svg
create mode 100644 src/assets/icons/more.svg
create mode 100644 src/assets/icons/next.svg
create mode 100644 src/assets/icons/pause.svg
create mode 100644 src/assets/icons/play.svg
create mode 100644 src/assets/icons/plus.svg
create mode 100644 src/assets/icons/previous.svg
create mode 100644 src/assets/icons/repeat-1.svg
create mode 100644 src/assets/icons/repeat.svg
create mode 100644 src/assets/icons/search.svg
create mode 100644 src/assets/icons/settings.svg
create mode 100644 src/assets/icons/shuffle.svg
create mode 100644 src/assets/icons/sort-up.svg
create mode 100644 src/assets/icons/thumbs-down.svg
create mode 100644 src/assets/icons/volume-half.svg
create mode 100644 src/assets/icons/volume-mute.svg
create mode 100644 src/assets/icons/volume.svg
create mode 100644 src/assets/icons/x.svg
create mode 100644 src/background.js
create mode 100644 src/components/ArtistsInLine.vue
create mode 100644 src/components/ButtonIcon.vue
create mode 100644 src/components/ButtonTwoTone.vue
create mode 100644 src/components/ContextMenu.vue
create mode 100644 src/components/Cover.vue
create mode 100644 src/components/CoverRow.vue
create mode 100644 src/components/DailyTracksCard.vue
create mode 100644 src/components/ExplicitSymbol.vue
create mode 100644 src/components/FMCard.vue
create mode 100644 src/components/LinuxTitlebar.vue
create mode 100644 src/components/Modal.vue
create mode 100644 src/components/ModalAddTrackToPlaylist.vue
create mode 100644 src/components/ModalNewPlaylist.vue
create mode 100644 src/components/MvRow.vue
create mode 100644 src/components/Navbar.vue
create mode 100644 src/components/Player.vue
create mode 100644 src/components/Scrollbar.vue
create mode 100644 src/components/SvgIcon.vue
create mode 100644 src/components/Toast.vue
create mode 100644 src/components/TrackList.vue
create mode 100644 src/components/TrackListItem.vue
create mode 100644 src/components/Win32Titlebar.vue
create mode 100644 src/electron/dockMenu.js
create mode 100644 src/electron/globalShortcut.js
create mode 100644 src/electron/ipcMain.js
create mode 100644 src/electron/ipcRenderer.js
create mode 100644 src/electron/menu.js
create mode 100644 src/electron/mpris.js
create mode 100644 src/electron/services.js
create mode 100644 src/electron/touchBar.js
create mode 100644 src/electron/tray.js
create mode 100644 src/locale/index.js
create mode 100644 src/locale/lang/en.js
create mode 100644 src/locale/lang/tr.js
create mode 100644 src/locale/lang/zh-CN.js
create mode 100644 src/locale/lang/zh-TW.js
create mode 100644 src/main.js
create mode 100644 src/ncmModDef.js
create mode 100644 src/registerServiceWorker.js
create mode 100644 src/router/index.js
create mode 100644 src/store/actions.js
create mode 100644 src/store/index.js
create mode 100644 src/store/initLocalStorage.js
create mode 100644 src/store/mutations.js
create mode 100644 src/store/plugins/localStorage.js
create mode 100644 src/store/plugins/sendSettings.js
create mode 100644 src/store/state.js
create mode 100644 src/utils/Player.js
create mode 100644 src/utils/auth.js
create mode 100644 src/utils/base64.js
create mode 100644 src/utils/checkAuthToken.js
create mode 100644 src/utils/common.js
create mode 100644 src/utils/db.js
create mode 100644 src/utils/filters.js
create mode 100644 src/utils/lyrics.js
create mode 100644 src/utils/nativeAlert.js
create mode 100644 src/utils/platform.js
create mode 100644 src/utils/playList.js
create mode 100644 src/utils/request.js
create mode 100644 src/utils/shortcuts.js
create mode 100644 src/utils/staticData.js
create mode 100644 src/utils/updateApp.js
create mode 100644 src/views/album.vue
create mode 100644 src/views/artist.vue
create mode 100644 src/views/artistMV.vue
create mode 100644 src/views/dailyTracks.vue
create mode 100644 src/views/explore.vue
create mode 100644 src/views/home.vue
create mode 100644 src/views/lastfmCallback.vue
create mode 100644 src/views/library.vue
create mode 100644 src/views/login.vue
create mode 100644 src/views/loginAccount.vue
create mode 100644 src/views/loginUsername.vue
create mode 100644 src/views/lyrics.vue
create mode 100644 src/views/mv.vue
create mode 100644 src/views/newAlbum.vue
create mode 100644 src/views/next.vue
create mode 100644 src/views/playlist.vue
create mode 100644 src/views/search.vue
create mode 100644 src/views/searchType.vue
create mode 100644 src/views/settings.vue
create mode 100644 vercel.example.json
create mode 100644 vue.config.js
create mode 100644 yarn.lock
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..03f2450
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,16 @@
+node_modules
+npm-debug.log
+Dockerfile*
+docker-compose*
+.dockerignore
+.git
+.github
+.gitignore
+README.md
+LICENSE
+.vscode
+dist
+dist_electron
+build
+images
+script
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..db87e1f
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,8 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = false
+insert_final_newline = false
\ No newline at end of file
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..7c0058a
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,7 @@
+VUE_APP_NETEASE_API_URL=/api
+VUE_APP_ELECTRON_API_URL=/api
+VUE_APP_ELECTRON_API_URL_DEV=http://127.0.0.1:10754
+VUE_APP_LASTFM_API_KEY=09c55292403d961aa517ff7f5e8a3d9c
+VUE_APP_LASTFM_API_SHARED_SECRET=307c9fda32b3904e53654baff215cb67
+DEV_SERVER_PORT=20201
+
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..ac10488
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,7 @@
+* text eol=lf
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.mp3 binary
+*.icns binary
+*.gif binary
diff --git a/.github/ISSUE_TEMPLATE/----------.md b/.github/ISSUE_TEMPLATE/----------.md
new file mode 100644
index 0000000..ba42d00
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/----------.md
@@ -0,0 +1,21 @@
+---
+name: 反馈问题或请求新功能
+about: bug & feature
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+# 尽量每个 issue 只提一个 bug 或新功能
+
+### 提新 issue 前请确认 👉
+
+- 没人提过这个 issue([这里看所有 issue](https://github.com/qier222/YesPlayMusic/issues))
+- 项目的 Todo 里没有与你 issue 相关的内容([这里看 Todo](https://github.com/qier222/YesPlayMusic/projects/1))
+
+### 反馈 bug 需要的信息
+
+- 用的是网页版还是客户端
+- 浏览器名称或电脑操作系统
+- 控制台 Console 页面的截图(按 F12 可打开控制台)
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
new file mode 100644
index 0000000..4caf481
--- /dev/null
+++ b/.github/workflows/build.yaml
@@ -0,0 +1,116 @@
+name: Release
+
+env:
+ YARN_INSTALL_NOPT: yarn add --ignore-platform --ignore-optional
+
+on:
+ push:
+ branches:
+ - master
+ tags:
+ - v*
+ workflow_dispatch:
+
+jobs:
+ release:
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os: [macos-latest, windows-latest, ubuntu-22.04]
+
+ steps:
+ - name: Check out Git repository
+ uses: actions/checkout@v3
+ with:
+ submodules: "recursive"
+
+ - name: Install Node.js, NPM and Yarn
+ uses: actions/setup-node@v3
+ with:
+ node-version: 16
+ cache: 'yarn'
+
+ - name: Install RPM & Pacman (on Ubuntu)
+ if: runner.os == 'Linux'
+ run: |
+ sudo apt-get update &&
+ sudo apt-get install --no-install-recommends -y rpm &&
+ sudo apt-get install --no-install-recommends -y libarchive-tools &&
+ sudo apt-get install --no-install-recommends -y libopenjp2-tools
+
+ - name: Install Snapcraft (on Ubuntu)
+ uses: samuelmeuli/action-snapcraft@v1
+ if: startsWith(matrix.os, 'ubuntu')
+ with:
+ snapcraft_token: ${{ secrets.snapcraft_token }}
+
+ - id: get_unm_version
+ name: Get the installed UNM version
+ run: |
+ yarn --ignore-optional
+ unm_version=$(node -e "console.log(require('./node_modules/@unblockneteasemusic/rust-napi/package.json').version)")
+ echo "::set-output name=unmver::${unm_version}"
+ shell: bash
+
+ - name: Install UNM dependencies for Windows
+ if: runner.os == 'Windows'
+ run: |
+ ${{ env.YARN_INSTALL_NOPT }} \
+ @unblockneteasemusic/rust-napi-win32-x64-msvc@${{steps.get_unm_version.outputs.unmver}}
+ shell: bash
+
+ - name: Install UNM dependencies for macOS
+ if: runner.os == 'macOS'
+ run: |
+ ${{ env.YARN_INSTALL_NOPT }} \
+ @unblockneteasemusic/rust-napi-darwin-x64@${{steps.get_unm_version.outputs.unmver}} \
+ @unblockneteasemusic/rust-napi-darwin-arm64@${{steps.get_unm_version.outputs.unmver}} \
+ dmg-license
+ shell: bash
+
+ - name: Install UNM dependencies for Linux
+ if: runner.os == 'Linux'
+ run: |
+ ${{ env.YARN_INSTALL_NOPT }} \
+ @unblockneteasemusic/rust-napi-linux-x64-gnu@${{steps.get_unm_version.outputs.unmver}} \
+ @unblockneteasemusic/rust-napi-linux-arm64-gnu@${{steps.get_unm_version.outputs.unmver}} \
+ @unblockneteasemusic/rust-napi-linux-arm-gnueabihf@${{steps.get_unm_version.outputs.unmver}}
+ shell: bash
+
+ - name: Build/release Electron app
+ uses: samuelmeuli/action-electron-builder@v1.6.0
+ env:
+ VUE_APP_NETEASE_API_URL: /api
+ VUE_APP_ELECTRON_API_URL: /api
+ VUE_APP_ELECTRON_API_URL_DEV: http://127.0.0.1:10754
+ VUE_APP_LASTFM_API_KEY: 09c55292403d961aa517ff7f5e8a3d9c
+ VUE_APP_LASTFM_API_SHARED_SECRET: 307c9fda32b3904e53654baff215cb67
+ with:
+ # GitHub token, automatically provided to the action
+ # (No need to define this secret in the repo settings)
+ github_token: ${{ secrets.github_token }}
+
+ # If the commit is tagged with a version (e.g. "v1.0.0"),
+ # release the app after building
+ release: ${{ startsWith(github.ref, 'refs/tags/v') }}
+
+ use_vue_cli: true
+
+ - uses: actions/upload-artifact@v3
+ with:
+ name: YesPlayMusic-mac
+ path: dist_electron/*-universal.dmg
+ if-no-files-found: ignore
+
+ - uses: actions/upload-artifact@v3
+ with:
+ name: YesPlayMusic-win
+ path: dist_electron/*Setup*.exe
+ if-no-files-found: ignore
+
+ - uses: actions/upload-artifact@v3
+ with:
+ name: YesPlayMusic-linux
+ path: dist_electron/*.AppImage
+ if-no-files-found: ignore
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
new file mode 100644
index 0000000..f8e0be8
--- /dev/null
+++ b/.github/workflows/sync.yml
@@ -0,0 +1,48 @@
+name: Upstream Sync
+
+permissions:
+ contents: write
+ issues: write
+ actions: write
+
+on:
+ schedule:
+ - cron: '0 * * * *' # every hour
+ workflow_dispatch:
+
+jobs:
+ sync_latest_from_upstream:
+ name: Sync latest commits from upstream repo
+ runs-on: ubuntu-latest
+ if: ${{ github.event.repository.fork }}
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Clean issue notice
+ uses: actions-cool/issues-helper@v3
+ with:
+ actions: 'close-issues'
+ labels: '🚨 Sync Fail'
+
+ - name: Sync upstream changes
+ id: sync
+ uses: aormsby/Fork-Sync-With-Upstream-action@v3.4
+ with:
+ upstream_sync_repo: qier222/YesPlayMusic
+ upstream_sync_branch: master
+ target_sync_branch: master
+ target_repo_token: ${{ secrets.GITHUB_TOKEN }} # automatically generated, no need to set
+ test_mode: false
+
+ - name: Sync check
+ if: failure()
+ uses: actions-cool/issues-helper@v3
+ with:
+ actions: 'create-issue'
+ title: '🚨 同步失败 | Sync Fail'
+ labels: '🚨 Sync Fail'
+ body: |
+ Due to a change in the workflow file of the upstream repository, GitHub has automatically suspended the scheduled automatic update. You need to manually sync your fork.
+
+ 由于上游仓库的 workflow 文件变更,导致 GitHub 自动暂停了本次自动更新,你需要手动 Sync Fork 一次。
diff --git a/.gitignore b/.gitignore
index dc99ae8..b96fe0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,8 +2,8 @@
node_modules
/dist
-
# local env files
+.env
.env.local
.env.*.local
@@ -12,14 +12,23 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
-package-lock.json
# Editor directories and files
.idea
-.vscode/*
-!.vscode/preview.yml
+.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+
+.vercel
+
+#Electron-builder output
+/dist_electron
+NeteaseCloudMusicApi-master
+NeteaseCloudMusicApi-master.zip
+
+# Local Netlify folder
+.netlify
+vercel.json
diff --git a/.inscode b/.inscode
index ecc8bdd..ca9dbb6 100644
--- a/.inscode
+++ b/.inscode
@@ -1,6 +1,10 @@
-run = "npm i && npm run dev"
+run = "yarn install && yarn serve"
+language = "node"
[env]
PATH = "/root/${PROJECT_DIR}/.config/npm/node_global/bin:/root/${PROJECT_DIR}/node_modules/.bin:${PATH}"
XDG_CONFIG_HOME = "/root/.config"
-npm_config_prefix = "/root/${PROJECT_DIR}/.config/npm/node_global"
\ No newline at end of file
+npm_config_prefix = "/root/${PROJECT_DIR}/.config/npm/node_global"
+
+[debugger]
+program = "main.js"
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..da2d398
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+14
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..13859d2
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,3 @@
+build
+coverage
+dist
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..38800a3
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,12 @@
+{
+ "trailingComma": "es5",
+ "tabWidth": 2,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": true,
+ "jsxSingleQuote": true,
+ "arrowParens": "avoid",
+ "endOfLine": "lf",
+ "bracketSpacing": true,
+ "htmlWhitespaceSensitivity": "strict"
+}
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..2fb8f95
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,25 @@
+FROM node:16.13.1-alpine as build
+ENV VUE_APP_NETEASE_API_URL=/api
+WORKDIR /app
+RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories &&\
+ apk add --no-cache python3 make g++ git
+COPY package.json yarn.lock ./
+RUN yarn install
+COPY . .
+RUN yarn config set electron_mirror https://npmmirror.com/mirrors/electron/ && \
+ yarn build
+
+FROM nginx:1.20.2-alpine as app
+
+COPY --from=build /app/package.json /usr/local/lib/
+
+RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories &&\
+ apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.14/main libuv \
+ && apk add --no-cache --update-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.14/main nodejs npm \
+ && npm i -g $(awk -F \" '{if($2=="NeteaseCloudMusicApi") print $2"@"$4}' /usr/local/lib/package.json) \
+ && rm -f /usr/local/lib/package.json
+
+COPY --from=build /app/docker/nginx.conf.example /etc/nginx/conf.d/default.conf
+COPY --from=build /app/dist /usr/share/nginx/html
+
+CMD nginx ; exec npx NeteaseCloudMusicApi
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7385fd2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020-2023 qier222
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..35018c4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,260 @@
+
+
+
+
+
+
YesPlayMusic
+
+
+ 高颜值的第三方网易云播放器
+
+ 🌎 访问DEMO |
+ 📦️ 下载安装包 |
+ 💬 加入交流群
+
+
+
+
+
+[![Library][library-screenshot]](https://music.qier222.com)
+
+
+## 全新版本
+全新2.0 Alpha测试版已发布,欢迎前往 [Releases](https://github.com/qier222/YesPlayMusic/releases) 页面下载。
+当前版本将会进入维护模式,除重大bug修复外,不会再更新新功能。
+
+## ✨ 特性
+
+- ✅ 使用 Vue.js 全家桶开发
+- 🔴 网易云账号登录(扫码/手机/邮箱登录)
+- 📺 支持 MV 播放
+- 📃 支持歌词显示
+- 📻 支持私人 FM / 每日推荐歌曲
+- 🚫🤝 无任何社交功能
+- 🌎️ 海外用户可直接播放(需要登录网易云账号)
+- 🔐 支持 [UnblockNeteaseMusic](https://github.com/UnblockNeteaseMusic/server#音源清单),自动使用[各类音源](https://github.com/UnblockNeteaseMusic/server#音源清单)替换变灰歌曲链接 (网页版不支持)
+ - 「各类音源」指默认启用的音源。
+ - YouTube 音源需自行安装 `yt-dlp`。
+- ✔️ 每日自动签到(手机端和电脑端同时签到)
+- 🌚 Light/Dark Mode 自动切换
+- 👆 支持 Touch Bar
+- 🖥️ 支持 PWA,可在 Chrome/Edge 里点击地址栏右边的 ➕ 安装到电脑
+- 🟥 支持 Last.fm Scrobble
+- ☁️ 支持音乐云盘
+- ⌨️ 自定义快捷键和全局快捷键
+- 🎧 支持 Mpris
+- 🛠 更多特性开发中
+
+## 📦️ 安装
+
+Electron 版本由 [@hawtim](https://github.com/hawtim) 和 [@qier222](https://github.com/qier222) 适配并维护,支持 macOS、Windows、Linux。
+
+访问本项目的 [Releases](https://github.com/qier222/YesPlayMusic/releases)
+页面下载安装包。
+
+- macOS 用户可以通过 Homebrew 来安装:`brew install --cask yesplaymusic`
+
+- Windows 用户可以通过 Scoop 来安装:`scoop install extras/yesplaymusic`
+
+## ⚙️ 部署至 Vercel
+
+除了下载安装包使用,你还可以将本项目部署到 Vercel 或你的服务器上。下面是部署到 Vercel 的方法。
+
+本项目的 Demo (https://music.qier222.com) 就是部署在 Vercel 上的网站。
+
+[](https://vercel.com/?utm_source=ohmusic&utm_campaign=oss)
+
+1. 部署网易云 API,详情参见 [Binaryify/NeteaseCloudMusicApi](https://neteasecloudmusicapi.vercel.app/#/?id=%e5%ae%89%e8%a3%85)
+ 。你也可以将 API 部署到 Vercel。
+
+2. 点击本仓库右上角的 Fork,复制本仓库到你的 GitHub 账号。
+
+3. 点击仓库的 Add File,选择 Create new file,输入 `vercel.json`,将下面的内容复制粘贴到文件中,并将 `https://your-netease-api.example.com` 替换为你刚刚部署的网易云 API 地址:
+
+```json
+{
+ "rewrites": [
+ {
+ "source": "/api/:match*",
+ "destination": "https://your-netease-api.example.com/:match*"
+ }
+ ]
+}
+```
+
+4. 打开 [Vercel.com](https://vercel.com),使用 GitHub 登录。
+
+5. 点击 Import Git Repository 并选择你刚刚复制的仓库并点击 Import。
+
+6. 点击 PERSONAL ACCOUNT 旁边的 Select。
+
+7. 点击 Environment Variables,填写 Name 为 `VUE_APP_NETEASE_API_URL`,Value 为 `/api`,点击 Add。最后点击底部的 Deploy 就可以部署到
+ Vercel 了。
+
+## ⚙️ 部署到自己的服务器
+
+除了部署到 Vercel,你还可以部署到自己的服务器上
+
+1. 部署网易云 API,详情参见 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi)
+2. 克隆本仓库
+
+```sh
+git clone --recursive https://github.com/qier222/YesPlayMusic.git
+```
+
+3. 安装依赖
+
+```sh
+yarn install
+
+```
+
+4. (可选)使用 Nginx 反向代理 API,将 API 路径映射为 `/api`,如果 API 和网页不在同一个域名下的话(跨域),会有一些 bug。
+
+5. 复制 `/.env.example` 文件为 `/.env`,修改里面 `VUE_APP_NETEASE_API_URL` 的值为网易云 API 地址。本地开发的话可以填写 API 地址为 `http://localhost:3000`,YesPlayMusic 地址为 `http://localhost:8080`。如果你使用了反向代理 API,可以填写 API 地址为 `/api`。
+
+```
+VUE_APP_NETEASE_API_URL=http://localhost:3000
+```
+
+6. 编译打包
+
+```sh
+yarn run build
+```
+
+7. 将 `/dist` 目录下的文件上传到你的 Web 服务器
+
+## ⚙️ Docker 部署
+
+1. 构建 Docker Image
+
+```sh
+docker build -t yesplaymusic .
+```
+
+2. 启动 Docker Container
+
+```sh
+docker run -d --name YesPlayMusic -p 80:80 yesplaymusic
+```
+
+3. Docker Compose 启动
+
+```sh
+docker-compose up -d
+```
+
+YesPlayMusic 地址为 `http://localhost`
+
+## ⚙️ 部署至 Replit
+
+1. 新建 Repl,选择 Bash 模板
+
+2. 在 Replit shell 中运行以下命令
+
+```sh
+bash <(curl -s -L https://raw.githubusercontent.com/qier222/YesPlayMusic/main/install-replit.sh)
+```
+
+3. 首次运行成功后,只需点击绿色按钮 `Run` 即可再次运行
+
+4. 由于 replit 个人版限制内存为 1G(教育版为 3G),构建过程中可能会失败,请再次运行上述命令或运行以下命令:
+
+```sh
+cd /home/runner/${REPL_SLUG}/music && yarn install && yarn run build
+```
+
+## 👷♂️ 打包客户端
+
+如果在 Release 页面没有找到适合你的设备的安装包的话,你可以根据下面的步骤来打包自己的客户端。
+
+1. 打包 Electron 需要用到 Node.js 和 Yarn。可前往 [Node.js 官网](https://nodejs.org/zh-cn/) 下载安装包。安装 Node.js
+ 后可在终端里执行 `npm install -g yarn` 来安装 Yarn。
+
+2. 使用 `git clone --recursive https://github.com/qier222/YesPlayMusic.git` 克隆本仓库到本地。
+
+3. 使用 `yarn install` 安装项目依赖。
+
+4. 复制 `/.env.example` 文件为 `/.env` 。
+
+5. 选择下列表格的命令来打包适合的你的安装包,打包出来的文件在 `/dist_electron` 目录下。了解更多信息可访问 [electron-builder 文档](https://www.electron.build/cli)
+
+| 命令 | 说明 |
+| ------------------------------------------ | ------------------------- |
+| `yarn electron:build --windows nsis:ia32` | Windows 32 位 |
+| `yarn electron:build --windows nsis:arm64` | Windows ARM |
+| `yarn electron:build --linux deb:armv7l` | Debian armv7l(树莓派等) |
+| `yarn electron:build --macos dir:arm64` | macOS ARM |
+
+## :computer: 配置开发环境
+
+本项目由 [NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi) 提供 API。
+
+运行本项目
+
+```shell
+# 安装依赖
+yarn install
+
+# 创建本地环境变量
+cp .env.example .env
+
+# 运行(网页端)
+yarn serve
+
+# 运行(electron)
+yarn electron:serve
+```
+
+本地运行 NeteaseCloudMusicApi,或者将 API [部署至 Vercel](#%EF%B8%8F-部署至-vercel)
+
+```shell
+# 运行 API (默认 3000 端口)
+yarn netease_api:run
+```
+
+## ☑️ Todo
+
+查看 Todo 请访问本项目的 [Projects](https://github.com/qier222/YesPlayMusic/projects/1)
+
+欢迎提 Issue 和 Pull request。
+
+## 📜 开源许可
+
+本项目仅供个人学习研究使用,禁止用于商业及非法用途。
+
+基于 [MIT license](https://opensource.org/licenses/MIT) 许可进行开源。
+
+## 灵感来源
+
+API 源代码来自 [Binaryify/NeteaseCloudMusicApi](https://github.com/Binaryify/NeteaseCloudMusicApi)
+
+- [Apple Music](https://music.apple.com)
+- [YouTube Music](https://music.youtube.com)
+- [Spotify](https://www.spotify.com)
+- [网易云音乐](https://music.163.com)
+
+## 🖼️ 截图
+
+![lyrics][lyrics-screenshot]
+![library-dark][library-dark-screenshot]
+![album][album-screenshot]
+![home-2][home-2-screenshot]
+![artist][artist-screenshot]
+![search][search-screenshot]
+![home][home-screenshot]
+![explore][explore-screenshot]
+
+
+
+
+[album-screenshot]: images/album.png
+[artist-screenshot]: images/artist.png
+[explore-screenshot]: images/explore.png
+[home-screenshot]: images/home.png
+[home-2-screenshot]: images/home-2.png
+[lyrics-screenshot]: images/lyrics.png
+[library-screenshot]: images/library.png
+[library-dark-screenshot]: images/library-dark.png
+[search-screenshot]: images/search.png
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 0000000..707ce4a
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,11 @@
+module.exports = {
+ presets: [
+ [
+ '@vue/cli-plugin-babel/preset',
+ {
+ useBuiltIns: 'usage',
+ shippedProposals: true,
+ },
+ ],
+ ],
+};
diff --git a/build/icons/1024x1024.png b/build/icons/1024x1024.png
new file mode 100644
index 0000000000000000000000000000000000000000..9fc1c628fc2ad728018f8ddd6242b6952aaab0f1
GIT binary patch
literal 535997
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