diff --git a/.circleci/config.yml b/.circleci/config.yml index 5a6ef76e..fb495fd0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -136,11 +136,11 @@ jobs: if [[ "${APP_VERSION}" = *"beta"* ]]; then echo $'**Beta Release**\nA full changelog is unavailable, but you can view the branch comparison [here](https://github.com/ciderapp/cider/compare/stable...main).\nThese builds are considered bleeding edge, expect bugs and please do not use this as a representation of the fu ll app.\nOur full support disclaimer can be found [here](https://docs.cider.sh/support/disclaimer#support-nightly-beta-releases).' > release-notes.md gh release create "v${APP_VERSION}" --prerelease --title "Cider Version ${APP_VERSION} (${CIRCLE_BRANCH})" --notes-file release-notes.md -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 - curl http://129.146.42.180/api/v1/github/sync/main + curl -s http://129.146.42.180/api/v1/github/sync/main else echo $'**Stable Release**\nA full changelog is unavailable, but you can view the branch comparison [here](https://github.com/ciderapp/cider/compare/stable...main).\nThese are the most stable builds we can provide. If you experience any issues, please report them [here](https://github.com/ciderapp/cider/issues/new).\nOur full support disclaimer can be found [here](https://docs.cider.sh/support/disclaimer#support-releases).' > release-notes.md gh release create "v${APP_VERSION}" --title "Cider Version ${APP_VERSION} (${CIRCLE_BRANCH})" --notes-file release-notes.md -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 - curl http://129.146.42.180/api/v1/github/sync/stable + curl -s http://129.146.42.180/api/v1/github/sync/stable fi; # Orchestrate our job run sequence diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 00c9fea1..5009beff 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -10,7 +10,7 @@ contact_links: url: https://discord.com/invite/AppleMusic about: For quick support, make a ticket or ask for community support here. - name: Cider Documentation - url: https://docs.cider.sh/support/troubleshooting + url: https://docs.cider.sh/support/faqs about: In most cases, these troubleshooting tips can resolve basic issues. Try them out before opening an issue. - name: GitHub Issues url: https://github.com/ciderapp/Cider/issues diff --git a/.github/workflows/cider-chores.yml b/.github/workflows/cider-chores.yml index dfb3eb59..48136a22 100644 --- a/.github/workflows/cider-chores.yml +++ b/.github/workflows/cider-chores.yml @@ -69,7 +69,7 @@ jobs: commit_message: "chore: Prettified Code\n [ci skip]" commit_user_name: "cider-chore[bot]" commit_user_email: "cider-chore[bot]@users.noreply.github.com" - + update-i18n-source: runs-on: ubuntu-latest @@ -93,7 +93,8 @@ jobs: commit_message: "chore: Updated i18n Source\n [ci skip]" commit_user_name: "cider-chore[bot]" commit_user_email: "cider-chore[bot]@users.noreply.github.com" - + + synchronize-with-crowdin: runs-on: ubuntu-latest if: ${{ false }} # disable for now diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index 9163dd1b..38267fe3 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -219,6 +219,7 @@ "action.favorite": "Favorite", "action.removeFavorite": "Remove Favorite", "action.refresh": "Refresh", + "action.save": "Save", "home.title": "Home", "home.recentlyPlayed": "Recently Played", "home.recentlyAdded": "Recently Added", @@ -231,6 +232,7 @@ "error.connectionError": "There was a problem connecting to Apple Music.", "error.noResults": "No Results.", "error.noResults.description": "Try a new search.", + "error.musickitError": "MusicKit Encountered an Error: ", "podcast.followOnCider": "Follow On Cider", "podcast.followedOnCider": "Following On Cider", "podcast.subscribeOnItunes": "Subscribe On iTunes", @@ -249,6 +251,7 @@ "action.done": "Done", "action.submit": "Submit", "action.editTracklist": "Edit Tracklist", + "action.editDescription": "Edit Description", "action.addToLibrary": "Add to Library", "action.addToLibrary.success": "Added to Library", "action.addToLibrary.error": "Error Adding to Library", @@ -263,6 +266,7 @@ "action.createPlaylist": "Create a New Playlist", "action.addToPlaylist.duplicate": "Item already exists in playlist. Do you want to continue?", "action.addToPlaylist": "Add to Playlist", + "action.addToPlaylist.duplicate": "Item already exists in playlist. Do you want to continue?", "action.removeFromPlaylist": "Remove from Playlist", "action.addToFavorites": "Add to Favorites", "action.follow": "Follow", @@ -539,6 +543,7 @@ "settings.option.connectivity.discordRPC.buttons.viewOnAppleMusic": "View on Apple Music", "settings.option.connectivity.discordRPC.buttons.viewOnOtherMusicServices": "View on Other Music Services", "settings.option.connectivity.discordRPC.showSongLink": "Show Song.link button instead of Apple Music button on Discord Rich Presence", + "settings.option.connectivity.discordRPC.hideButtons": "Hide buttons on Discord Rich Presence", "settings.option.connectivity.discordRPC.hideTimestamp": "Hide timestamp on Discord Rich Presence", "settings.option.connectivity.discordRPC.detailsFormat": "Details Format", "settings.option.connectivity.discordRPC.stateFormat": "State Format", diff --git a/src/i18n/source/en_US.json b/src/i18n/source/en_US.json index 9163dd1b..38267fe3 100644 --- a/src/i18n/source/en_US.json +++ b/src/i18n/source/en_US.json @@ -219,6 +219,7 @@ "action.favorite": "Favorite", "action.removeFavorite": "Remove Favorite", "action.refresh": "Refresh", + "action.save": "Save", "home.title": "Home", "home.recentlyPlayed": "Recently Played", "home.recentlyAdded": "Recently Added", @@ -231,6 +232,7 @@ "error.connectionError": "There was a problem connecting to Apple Music.", "error.noResults": "No Results.", "error.noResults.description": "Try a new search.", + "error.musickitError": "MusicKit Encountered an Error: ", "podcast.followOnCider": "Follow On Cider", "podcast.followedOnCider": "Following On Cider", "podcast.subscribeOnItunes": "Subscribe On iTunes", @@ -249,6 +251,7 @@ "action.done": "Done", "action.submit": "Submit", "action.editTracklist": "Edit Tracklist", + "action.editDescription": "Edit Description", "action.addToLibrary": "Add to Library", "action.addToLibrary.success": "Added to Library", "action.addToLibrary.error": "Error Adding to Library", @@ -263,6 +266,7 @@ "action.createPlaylist": "Create a New Playlist", "action.addToPlaylist.duplicate": "Item already exists in playlist. Do you want to continue?", "action.addToPlaylist": "Add to Playlist", + "action.addToPlaylist.duplicate": "Item already exists in playlist. Do you want to continue?", "action.removeFromPlaylist": "Remove from Playlist", "action.addToFavorites": "Add to Favorites", "action.follow": "Follow", @@ -539,6 +543,7 @@ "settings.option.connectivity.discordRPC.buttons.viewOnAppleMusic": "View on Apple Music", "settings.option.connectivity.discordRPC.buttons.viewOnOtherMusicServices": "View on Other Music Services", "settings.option.connectivity.discordRPC.showSongLink": "Show Song.link button instead of Apple Music button on Discord Rich Presence", + "settings.option.connectivity.discordRPC.hideButtons": "Hide buttons on Discord Rich Presence", "settings.option.connectivity.discordRPC.hideTimestamp": "Hide timestamp on Discord Rich Presence", "settings.option.connectivity.discordRPC.detailsFormat": "Details Format", "settings.option.connectivity.discordRPC.stateFormat": "State Format", diff --git a/src/main/base/browserwindow.ts b/src/main/base/browserwindow.ts index c044894a..f0b4731a 100644 --- a/src/main/base/browserwindow.ts +++ b/src/main/base/browserwindow.ts @@ -1445,16 +1445,18 @@ export class BrowserWindow { } }); - win.on("close", (e: any) => { + win.on("close", async (e: any) => { if ((process.platform === "darwin" || utils.getStoreValue("general.close_button_hide")) && !isQuitting) { e.preventDefault(); win.hide(); } else { - win.webContents.executeJavaScript(` + await win.webContents.executeJavaScript(` window.localStorage.setItem("currentTrack", JSON.stringify(app.mk.nowPlayingItem)); window.localStorage.setItem("currentTime", JSON.stringify(app.mk.currentPlaybackTime)); window.localStorage.setItem("currentQueue", JSON.stringify(app.mk.queue._unplayedQueueItems)); - ipcRenderer.send('stopGCast','');`); + ipcRenderer.send('stopGCast',''); + MusicKit.getInstance().stop(); + `); } }); diff --git a/src/preload/cider-preload.js b/src/preload/cider-preload.js index afc3cf74..1314f33d 100644 --- a/src/preload/cider-preload.js +++ b/src/preload/cider-preload.js @@ -144,7 +144,7 @@ const MusicKitInterop = { const attributes = nowPlayingItem != null ? nowPlayingItem.attributes : {}; attributes.songId = attributes.songId ?? attributes.playParams?.catalogId ?? attributes.playParams?.id; - attributes.kind = nowPlayingItem?.type ?? attributes.type ?? attributes.playParams.kind ?? ""; + attributes.kind = nowPlayingItem?.type ?? attributes?.type ?? attributes.playParams?.kind ?? ""; attributes.status = nowPlayingItem == null ? null : !!isPlayingExport; attributes.name = attributes?.name ?? "no-title-found"; attributes.artwork = attributes?.artwork ?? { url: "" }; @@ -229,42 +229,38 @@ const MusicKitInterop = { initMediaSession: () => { if ("mediaSession" in navigator) { - const defaultSkipTime = 10; - console.debug("[cider:preload] [initMediaSession] Media Session API supported"); navigator.mediaSession.setActionHandler("play", () => { MusicKitInterop.play(); - console.log("[cider:preload] [initMediaSession] Play"); }); navigator.mediaSession.setActionHandler("pause", () => { MusicKitInterop.pause(); - console.log("[cider:preload] [initMediaSession] Pause"); }); navigator.mediaSession.setActionHandler("stop", () => { MusicKit.getInstance().stop(); - console.log("[cider:preload] [initMediaSession] Stop"); }); navigator.mediaSession.setActionHandler("seekbackward", (details) => { - const skipTime = details.seekOffset || defaultSkipTime; - MusicKit.getInstance().seekToTime(Math.max(MusicKit.getInstance().currentPlaybackTime - skipTime, 0)); - console.log(`[cider:preload] [initMediaSession] Seek Backward ${skipTime}`); + if (details.seekOffset) { + MusicKit.getInstance().seekToTime(Math.max(MusicKit.getInstance().currentPlaybackTime - details.seekOffset, 0)); + } else { + MusicKit.getInstance().seekBackward(); + } }); navigator.mediaSession.setActionHandler("seekforward", (details) => { - const skipTime = details.seekOffset || defaultSkipTime; - MusicKit.getInstance().seekToTime(Math.max(MusicKit.getInstance().currentPlaybackTime + skipTime, 0)); - console.log(`[cider:preload] [initMediaSession] Seek Forward ${skipTime}`); + if (details.seekOffset) { + MusicKit.getInstance().seekToTime(Math.max(MusicKit.getInstance().currentPlaybackTime + details.seekOffset, 0)); + } else { + MusicKit.getInstance().seekForward(); + } }); navigator.mediaSession.setActionHandler("seekto", ({ seekTime, fastSeek }) => { MusicKit.getInstance().seekToTime(seekTime); - console.log(`[cider:preload] [initMediaSession] Seek To ${seekTime}`); }); navigator.mediaSession.setActionHandler("previoustrack", () => { MusicKitInterop.previous(); - console.log("[cider:preload] [initMediaSession] Previous Track"); }); navigator.mediaSession.setActionHandler("nexttrack", () => { MusicKitInterop.next(); - console.log("[cider:preload] [initMediaSession] Next Track"); }); } else { console.debug("[cider:preload] [initMediaSession] Media Session API not supported"); diff --git a/src/renderer/audio/audio.js b/src/renderer/audio/audio.js index 9a993c14..cbf84d1e 100644 --- a/src/renderer/audio/audio.js +++ b/src/renderer/audio/audio.js @@ -972,8 +972,6 @@ const CiderAudio = { MusicKit.getInstance().pause(); // Pause first } - CiderAudioRenderer.off(); // Clean up IMMEDIATELY - CiderAudio.audioNodes.optimizedNode = CiderAudio.context.createConvolver(); CiderAudio.audioNodes.optimizedNode.normalize = false; @@ -981,6 +979,8 @@ const CiderAudio = { CiderAudio.audioNodes.optimizedNode.buffer = res; }); + CiderAudioRenderer.off(); // Clean up IMMEDIATELY + // Load the sucker up CiderAudio.hierarchical_unloading(); diff --git a/src/renderer/main/ciderfrontapi.js b/src/renderer/main/ciderfrontapi.js index 8a7ef76a..6b87ad3f 100644 --- a/src/renderer/main/ciderfrontapi.js +++ b/src/renderer/main/ciderfrontapi.js @@ -4,10 +4,15 @@ const CiderFrontAPI = { this.id = ""; this.name = ""; this.onClick = () => {}; + this.top = false; }, }, AddMenuEntry(entry) { - app.pluginMenuEntries.push(entry); + if (entry?.top) { + app.pluginMenuTopEntries.push(entry); + } else { + app.pluginMenuEntries.push(entry); + } app.pluginInstalled = true; }, StyleSheets: { diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index 49b3606c..52fe2de6 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -18,6 +18,7 @@ const app = new Vue({ mk: {}, pluginInstalled: false, pluginMenuEntries: [], + pluginMenuTopEntries: [], lz: ipcRenderer.sendSync("get-i18n", "en_US"), lzListing: ipcRenderer.sendSync("get-i18n-listing"), radiohls: null, @@ -305,6 +306,20 @@ const app = new Vue({ app.cfg.musickit["stored-attributes"][attr] = val; }); } + const ERROR_CODES = ["drmUnsupported", "mediaPlaybackError"]; + /* MusicKit.Events */ + ERROR_CODES.forEach((code) => { + MusicKit.getInstance().addEventListener(MusicKit.Events[code], (e) => { + console.error(`[MusicKit] MusicKit Error ${code}`); + console.error({ e: e }); + app.notyf.open({ + duration: 20000, + type: "error", + className: "notyf-info", + message: `${app.getLz("error.musickitError")} \n${code.toUpperCase()}`, + }); + }); + }); }, async oobeInit() { this.appMode = "oobe"; diff --git a/src/renderer/views/app/app-navigation.ejs b/src/renderer/views/app/app-navigation.ejs index 7e03c957..bf6da9dc 100644 --- a/src/renderer/views/app/app-navigation.ejs +++ b/src/renderer/views/app/app-navigation.ejs @@ -1,166 +1,151 @@
- -
-
- - - + + - + - + - + - + - + - + - + + - + -
+ +
+
+ + + + + + +
+
+
+ + +
- - - - - - -
-
-
- - - -
-
- - -
-
- -
- -
-
+
+ + +
+
+ +
+ +
+