diff --git a/.circleci/config.yml b/.circleci/config.yml index 62dc1183..83d25acc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,18 +1,21 @@ version: 2.1 -orbs: # adds orbs to your configuration - jira: circleci/jira@1.0.5 # invokes the Jira orb, making its commands accessible -branches: - only: - - main - - develop -jobs: - build: - working_directory: ~/Cider + +executors: + cider-ci: docker: - image: circleci/node:16 - + working_directory: ~/Cider + +orbs: # adds orbs to your configuration + jira: circleci/jira@1.0.5 # invokes the Jira orb, making its commands accessible + +# The jobs for this project +jobs: + prepare-build: + executor: cider-ci steps: - checkout + - run: ls -la - run: name: Set App Version command: echo "export APP_VERSION=$(grep '"version":.*' package.json | cut -d '"' -f 4 | head -1)" >> $BASH_ENV @@ -32,50 +35,144 @@ jobs: paths: - ~/.cache/yarn - run: - name: Install system build dependencies + name: TypeScript Compile + command: yarn build + - persist_to_workspace: + # Must be an absolute path, or relative path from working_directory. This is a directory on the container which is + # taken to be the root directory of the workspace. + root: . + # Must be relative path from root + paths: + - node_modules + - build + - resources + - yarn.lock + - package.json + - winget.json # winget.json is a file that is generated by the winget package manager + - LICENSE + - license.txt + + build-windows: + executor: cider-ci + steps: + - attach_workspace: + at: ~/Cider + - run: + name: Install Windows System Build Dependencies command: | sudo apt-get update -y - curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null sudo apt-get install -y dpkg fakeroot wine64 sudo dpkg --add-architecture i386 sudo apt-get update -y sudo apt-get install -y wine32 - sudo apt install -y gh - run: name: Fix Versioning and Add Channel command: yarn circle:script - - run: - name: TypeScript Compile - command: yarn build - - run: - name: Generate Builds (Linux) - command: yarn electron-builder -l -p never - post-steps: - - jira/notify - run: name: Generate Builds (Windows) command: yarn electron-builder -w --x64 -p never post-steps: - jira/notify + - persist_to_workspace: + root: . + paths: + - dist/*.exe + - dist/latest.yml + + build-linux: + executor: cider-ci + steps: + - attach_workspace: + at: ~/Cider + - run: + name: Fix Versioning and Add Channel + command: yarn circle:script + - run: + name: Generate Builds (Linux) + command: yarn electron-builder -l -p never + post-steps: + - jira/notify + - persist_to_workspace: + root: . + paths: + - dist/*.deb + - dist/*.AppImage + - dist/*.snap + - dist/latest-linux.yml + + build-winget: + executor: cider-ci + steps: + - attach_workspace: + at: ~/Cider + - run: + name: Install Windows System Build Dependencies + command: | + sudo apt-get update -y + sudo apt-get install -y dpkg fakeroot wine64 + sudo dpkg --add-architecture i386 + sudo apt-get update -y + sudo apt-get install -y wine32 + - run: + name: Fix Versioning and Add Channel + command: yarn circle:script - run: name: Generate Builds (Winget) command: yarn electron-builder --win -c winget.json -p never post-steps: - jira/notify + - persist_to_workspace: + root: . + paths: + - dist/*.exe + # - dist/*.yml + + release: + executor: cider-ci + steps: + - attach_workspace: + at: ~/Cider/ + - run: + name: Installing GitHub Command Line Interface + command: | + sudo apt-get update -y + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null + sudo apt-get update -y + sudo apt install -y gh - run: name: Move Build Files command: | - mkdir ~/Cider/dist/artifacts/ - mv ~/Cider/dist/*.exe ~/Cider/dist/artifacts - mv ~/Cider/dist/*.deb ~/Cider/dist/artifacts - mv ~/Cider/dist/*.AppImage ~/Cider/dist/artifacts - mv ~/Cider/dist/*.snap ~/Cider/dist/artifacts - mv ~/Cider/dist/*.yml ~/Cider/dist/artifacts - mv ~/Cider/dist/*.blockmap ~/Cider/dist/artifacts + mkdir ~/Cider/dist/artifacts/ + mv ~/Cider/dist/*.exe ~/Cider/dist/artifacts + mv ~/Cider/dist/*.deb ~/Cider/dist/artifacts + mv ~/Cider/dist/*.AppImage ~/Cider/dist/artifacts + mv ~/Cider/dist/*.snap ~/Cider/dist/artifacts + mv ~/Cider/dist/*.yml ~/Cider/dist/artifacts + mv ~/Cider/dist/*.blockmap ~/Cider/dist/artifacts - store_artifacts: - path: ~/Cider/dist/artifacts + path: ~/Cider/dist/artifacts - run: name: Publish Release command: | - gh release create "v${APP_VERSION}.${CIRCLE_BUILD_NUM}" --title "Cider Version ${APP_VERSION} - Build ${CIRCLE_BUILD_NUM} (${CIRCLE_BRANCH})" --generate-notes -R ciderapp/cider-releases ~/Cider/dist/artifacts/*.deb ~/Cider/dist/artifacts/*.AppImage ~/Cider/dist/artifacts/*.snap ~/Cider/dist/artifacts/*.exe ~/Cider/dist/artifacts/*.yml ~/Cider/dist/artifacts/*.blockmap + gh release create "v${APP_VERSION}.${CIRCLE_BUILD_NUM}" --title "Cider Version ${APP_VERSION} - Build ${CIRCLE_BUILD_NUM} (${CIRCLE_BRANCH})" --generate-notes -R ciderapp/cider-releases ~/Cider/dist/artifacts/*.deb ~/Cider/dist/artifacts/*.AppImage ~/Cider/dist/artifacts/*.snap ~/Cider/dist/artifacts/*.exe ~/Cider/dist/artifacts/*.yml ~/Cider/dist/artifacts/*.blockmap + +# Orchestrate our job run sequence +workflows: + build_and_release: + jobs: + - prepare-build + - build-windows: + requires: + - prepare-build + - build-linux: + requires: + - prepare-build + - build-winget: + requires: + - prepare-build + - release: + requires: + - build-windows + - build-linux + - build-winget diff --git a/src/i18n/hu_HU.json b/src/i18n/hu_HU.json index 814ab20e..55706b2c 100644 --- a/src/i18n/hu_HU.json +++ b/src/i18n/hu_HU.json @@ -73,7 +73,6 @@ "term.viewAs": "Megjelenítés", "term.viewAs.coverArt": "Borító", "term.viewAs.list": "Lista", - "term.dynamic": "Dinamikus", "term.size": "Méret", "term.size.normal": "Normál", "term.size.compact": "Kompakt", @@ -407,6 +406,7 @@ "settings.option.lyrics.enableMusixmatchKaraoke": "Karaoke mód bekapcsolása (Csak MusixMatch)", "settings.option.lyrics.musixmatchPreferredLanguage": "MusixMatch fordítás nyelve", "settings.option.lyrics.enableYoutubeLyrics": "YouTube dalszövegek engedélyezése a zenei videóknál", + "settings.option.lyrics.enableQQLyrics": "QQLyrics dalszövegek engedélyezése", "settings.header.connectivity": "Csatlakozások", "settings.header.connectivity.description": "A Cider csatlakozás beállításainak módosítása.", "settings.option.connectivity.playbackNotifications": "Lejátszási értesítések", diff --git a/src/i18n/zh_TW.json b/src/i18n/zh_TW.json index 8c5083cc..ce9cf9a4 100644 --- a/src/i18n/zh_TW.json +++ b/src/i18n/zh_TW.json @@ -215,6 +215,10 @@ "settings.option.general.resumebehavior.locally.description": "Cider 將還原你在這台電腦上的最後一次操作。", "settings.option.general.resumebehavior.history": "歷史", "settings.option.general.resumebehavior.history.description": "Cider 將跨裝置將你的整個 Apple Music 歷史記錄中的最後一首歌曲排隊入列。", + "settings.option.general.resumetabs": "啟動時打開的選項", + "settings.option.general.resumetabs.description": "你可以選擇啟動 Cider 時要預設打開的左側選項欄。", + "settings.option.general.resumetabs.dynamic": "動態", + "settings.option.general.resumetabs.dynamic.description": "Cider 將打開你上次停留的左側選項欄。", "settings.option.general.language.main": "語言", "settings.option.general.language.fun": "特殊語言", "settings.option.general.language.unsorted": "未分類", @@ -345,8 +349,8 @@ "settings.option.connectivity.discordRPC.hideButtons": "隱藏 Discord 動態上的按鈕", "settings.option.connectivity.discordRPC.detailsFormat": "詳細資訊格式", "settings.option.connectivity.discordRPC.stateFormat": "狀態格式", - "settings.option.connectivity.lastfmScrobble": "Last.FM Scrobbling 記錄", - "settings.option.connectivity.lastfmScrobble.delay": "Last.FM Scrobble 延遲 (%)", + "settings.option.connectivity.lastfmScrobble": "Last.FM 音樂記錄", + "settings.option.connectivity.lastfmScrobble.delay": "Last.FM 歌曲追蹤延遲 (%)", "settings.option.connectivity.lastfmScrobble.nowPlaying": "開啟 Last.FM 正在聆聽", "settings.option.connectivity.lastfmScrobble.removeFeatured": "從歌名中移除客串藝人 (Last.FM)", "settings.option.connectivity.lastfmScrobble.filterLoop": "不記錄單曲循環 (Last.FM)", diff --git a/src/main/base/plugins.ts b/src/main/base/plugins.ts index a09ee3e9..d51e8a85 100644 --- a/src/main/base/plugins.ts +++ b/src/main/base/plugins.ts @@ -26,9 +26,9 @@ export class Plugins { } public static getPluginFromMap(plugin: string): any { - if(Plugins.PluginMap[plugin]) { + if (Plugins.PluginMap[plugin]) { return Plugins.PluginMap[plugin]; - }else{ + } else { return plugin; } } diff --git a/src/renderer/assets/feather/heart-fill.svg b/src/renderer/assets/feather/heart-fill.svg new file mode 100644 index 00000000..1f790aad --- /dev/null +++ b/src/renderer/assets/feather/heart-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/index.js b/src/renderer/index.js index 8df442f8..6f83b9b1 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -105,7 +105,7 @@ function fallbackinitMusicKit() { }) setTimeout(() => { app.init() - if(app.cfg.visual.window_background_style == "mica" && !app.isDev) { + if (app.cfg.visual.window_background_style == "mica" && !app.isDev) { app.spawnMica() } }, 1000) @@ -134,7 +134,7 @@ document.addEventListener('musickitloaded', function () { function waitForApp() { if (typeof app.init !== "undefined") { app.init() - if(app.cfg.visual.window_background_style == "mica" && !app.isDev) { + if (app.cfg.visual.window_background_style == "mica" && !app.isDev) { app.spawnMica() } } diff --git a/src/renderer/less/elements.css b/src/renderer/less/elements.css index d4547eae..7aef758e 100644 --- a/src/renderer/less/elements.css +++ b/src/renderer/less/elements.css @@ -371,6 +371,12 @@ filter: contrast(0); background-repeat: no-repeat; } +.heart-icon { + height: 18px; + width: 39px; + filter: contrast(0); + background-repeat: no-repeat; +} @keyframes load-bar { 10% { box-shadow: inset 0 -4px 0; diff --git a/src/renderer/less/elements.less b/src/renderer/less/elements.less index 716b71a4..c5fae7a8 100644 --- a/src/renderer/less/elements.less +++ b/src/renderer/less/elements.less @@ -456,6 +456,13 @@ background-repeat: no-repeat; } + .heart-icon { + height: 18px; + width: 39px; + filter: contrast(0); + background-repeat: no-repeat; + } + /* CSS.gg */ @keyframes load-bar { diff --git a/src/renderer/main/events.js b/src/renderer/main/events.js index 0b2e13d3..f2140460 100644 --- a/src/renderer/main/events.js +++ b/src/renderer/main/events.js @@ -22,7 +22,7 @@ const Events = { if (event.keyCode === 82 && event.ctrlKey) { event.preventDefault() bootbox.confirm("Reload Cider?", (res)=>{ - if(res) { + if (res) { window.location.reload() } }) diff --git a/src/renderer/main/gamepad.js b/src/renderer/main/gamepad.js index a902cd5f..abe20631 100644 --- a/src/renderer/main/gamepad.js +++ b/src/renderer/main/gamepad.js @@ -251,9 +251,9 @@ function simulateGamepad () { cursorPos[1] -= cursorSpeed // sounds.Hover.play() - // if(intTabIndex <= 0) { + // if (intTabIndex <= 0) { // intTabIndex = 0 - // }else{ + // } else { // intTabIndex-- // } // $(tabbable[intTabIndex]).focus() @@ -263,9 +263,9 @@ function simulateGamepad () { e.preventDefault() cursorPos[1] += cursorSpeed - // if(intTabIndex < tabbable.length) { + // if (intTabIndex < tabbable.length) { // intTabIndex++ - // }else{ + // } else { // intTabIndex = tabbable.length // } // $(tabbable[intTabIndex]).focus() diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index d6dfb6cd..a00c345d 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -1579,7 +1579,7 @@ const app = new Vue({ } route = route.replace(/#/g, "") if (app.cfg.general.resumeTabs.tab == "dynamic") { - if (route == "home" || route == "library-songs" || route == "library-albums" || route == "library-artists" || route == "library-videos" || route == "podcasts") { + if (route == "home" || route == "listen_now" || route == "browse" || route == "radio" || route == "library-songs" || route == "library-albums" || route == "library-artists" || route == "library-videos" || route == "podcasts") { app.cfg.general.resumeTabs.dynamicData = route } else { app.cfg.general.resumeTabs.dynamicData = "home" @@ -1671,11 +1671,11 @@ const app = new Vue({ params["meta[albums:tracks]"] = 'popularity' params["fields[albums]"] = "artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialNotes,editorialVideo,name,playParams,releaseDate,url,copyright" } - if(kind.includes("playlist") || kind.includes("album")){ + if (kind.includes("playlist") || kind.includes("album")){ app.page = (kind) + "_" + (id); window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}` app.getTypeFromID((kind), (id), (isLibrary), params); - }else{ + } else { app.page = (kind) window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}` } @@ -2817,7 +2817,7 @@ const app = new Vue({ }); app.lyrics = preLrc; } - if (lrcfile != null && lrcfile != '' && lang != "disabled") { + if (lrcfile != null && lrcfile != '') { // load translation getMXMTrans(id, lang, token); } else { diff --git a/src/renderer/main/wsapi_interop.js b/src/renderer/main/wsapi_interop.js index d9477a23..4439d956 100644 --- a/src/renderer/main/wsapi_interop.js +++ b/src/renderer/main/wsapi_interop.js @@ -108,11 +108,11 @@ const wsapi = { app.mk.isPlaying ? app.mk.pause() : app.mk.play() }, toggleRepeat() { - if(MusicKit.getInstance().repeatMode == 0) { + if (MusicKit.getInstance().repeatMode == 0) { MusicKit.getInstance().repeatMode = 1 - }else if(MusicKit.getInstance().repeatMode == 1){ + } else if (MusicKit.getInstance().repeatMode == 1){ MusicKit.getInstance().repeatMode = 2 - }else{ + } else { MusicKit.getInstance().repeatMode = 0 } }, diff --git a/src/renderer/style.css b/src/renderer/style.css index 180d1296..4ef47570 100644 --- a/src/renderer/style.css +++ b/src/renderer/style.css @@ -7936,6 +7936,12 @@ fieldset:disabled .btn { filter: contrast(0); background-repeat: no-repeat; } +.cd-mediaitem-list-item .heart-icon { + height: 18px; + width: 39px; + filter: contrast(0); + background-repeat: no-repeat; +} @keyframes load-bar { 10% { box-shadow: inset 0 -4px 0; diff --git a/src/renderer/style.less b/src/renderer/style.less index 13e7de3b..3900c772 100644 --- a/src/renderer/style.less +++ b/src/renderer/style.less @@ -1207,6 +1207,14 @@ body[platform="darwin"] .app-chrome .app-chrome-item > .window-controls > div.cl background-repeat: no-repeat; margin-left: 3px; } + + .heart-icon { + height: 9px; + width: 13px; + filter: contrast(0); + background-repeat: no-repeat; + margin-left: 3px; + } } .lossless-icon { diff --git a/src/renderer/todo.js b/src/renderer/todo.js index 3e8deaf9..4c95d8ed 100644 --- a/src/renderer/todo.js +++ b/src/renderer/todo.js @@ -133,11 +133,11 @@ app.mkapi("artists", false, "412778295", { var library = [] var downloaded = null; function downloadChunk () { - if(downloaded == null) { + if (downloaded == null) { app.mk.api.library.songs("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{ processChunk(response) }) - }else{ + } else { downloaded.next("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{ processChunk(response) }) diff --git a/src/renderer/views/components/artist-chip.ejs b/src/renderer/views/components/artist-chip.ejs index 12453996..9c2d884b 100644 --- a/src/renderer/views/components/artist-chip.ejs +++ b/src/renderer/views/components/artist-chip.ejs @@ -29,7 +29,7 @@ template: '#artist-chip', async mounted() { let artistId = this.item.id - if(typeof this.item.relationships == "object") { + if (typeof this.item.relationships == "object") { artistId = this.item.relationships.catalog.data[0].id } app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/artists/${artistId}`).then(response => { diff --git a/src/renderer/views/components/audio-settings.ejs b/src/renderer/views/components/audio-settings.ejs index c8e0c5d4..249d49ca 100644 --- a/src/renderer/views/components/audio-settings.ejs +++ b/src/renderer/views/components/audio-settings.ejs @@ -54,7 +54,7 @@ app.modals.audioSettings = false }, openSpatialAudio() { - if(app.cfg.audio.spatial === true && app.cfg.audio.maikiwiAudio.spatial === false) { + if (app.cfg.audio.spatial === true && app.cfg.audio.maikiwiAudio.spatial === false) { app.modals.spatialProperties = true app.modals.audioSettings = false } else { diff --git a/src/renderer/views/components/lyrics-view.ejs b/src/renderer/views/components/lyrics-view.ejs index 3047bde6..26001890 100644 --- a/src/renderer/views/components/lyrics-view.ejs +++ b/src/renderer/views/components/lyrics-view.ejs @@ -115,7 +115,7 @@ }, methods: { seekTo(startTime) { - if(startTime != 9999999) this.app.seekTo(startTime, false); + if (startTime != 9999999) this.app.seekTo(startTime, false); }, getActiveLyric() { const delayfix = 0.1 @@ -125,7 +125,7 @@ if (app.currentLyricsLine != i) { app.currentLyricsLine = i; if (((app.lyricon && app.drawer.open) || app.appMode == 'fullscreen') && this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${i}"]`)) { - if(this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${prevLine}"]`)) {this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${prevLine}"]`).classList.remove("active");} + if (this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${prevLine}"]`)) {this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${prevLine}"]`).classList.remove("active");} this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${i}"]`).classList.add("active") if (this.checkIfScrollIsStatic) { let lyricElement = this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${i}"]`) diff --git a/src/renderer/views/components/mediaitem-artwork.ejs b/src/renderer/views/components/mediaitem-artwork.ejs index f282629b..7fa4ea0d 100644 --- a/src/renderer/views/components/mediaitem-artwork.ejs +++ b/src/renderer/views/components/mediaitem-artwork.ejs @@ -76,9 +76,9 @@ }, event) }, getVideoPriority() { - if(app.cfg.visual.animated_artwork == "always") { + if (app.cfg.visual.animated_artwork == "always") { return true; - }else if (this.videoPriority && app.cfg.visual.animated_artwork == "limited") { + } else if (this.videoPriority && app.cfg.visual.animated_artwork == "limited") { return true } else if (app.cfg.visual.animated_artwork == "disabled") { return false diff --git a/src/renderer/views/components/mediaitem-list-item.ejs b/src/renderer/views/components/mediaitem-list-item.ejs index 0a1ab179..d2b318d6 100644 --- a/src/renderer/views/components/mediaitem-list-item.ejs +++ b/src/renderer/views/components/mediaitem-list-item.ejs @@ -65,6 +65,9 @@ +