diff --git a/.circleci/config.yml b/.circleci/config.yml index 28c3749e..6496dce4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -23,9 +23,6 @@ jobs: key: yarn-packages-{{ checksum "cider-yarn.lock" }} paths: - ~/.cache/yarn - - run: - name: Install Playwright - command: yarn playwright install --with-deps - run: name: Install system build dependencies command: | diff --git a/src/i18n/en_GB.json b/src/i18n/en_GB.json index 4ce16049..6555b245 100644 --- a/src/i18n/en_GB.json +++ b/src/i18n/en_GB.json @@ -11,5 +11,10 @@ "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Audio Spatialisation", "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Spatialise audio and make audio more 3-dimensional (note: This is not Dolby Atmos)", "spatial.notTurnedOn": "Audio Spatialisation is disabled. To use, please enable it first.", - "action.tray.minimize": "Minimise to Tray" + "action.tray.minimize": "Minimise to Tray", + "term.tracks": "songs", + "term.track": { + "one" : "song", + "other" : "songs" + } } diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index 06f4d0fd..2e0f5e81 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -92,13 +92,25 @@ "term.time.released": "Released", "term.time.updated": "Updated", "term.time.days": "days", - "term.time.day": "day", + "term.time.day": { + "one": "day", + "other": "days" + }, "term.time.hours": "hours", - "term.time.hour": "hour", + "term.time.hour": { + "one": "hour", + "other": "hours" + }, "term.time.minutes": "minutes", - "term.time.minute": "minute", + "term.time.minute": { + "one": "minute", + "other": "minutes" + }, "term.time.seconds": "seconds", - "term.time.second": "second", + "term.time.second": { + "one": "second", + "other": "seconds" + }, "term.fullscreenView": "Fullscreen View", "term.defaultView": "Default View", "term.audioSettings": "Audio Settings", diff --git a/src/i18n/source/en_US.json b/src/i18n/source/en_US.json index 06f4d0fd..2e0f5e81 100644 --- a/src/i18n/source/en_US.json +++ b/src/i18n/source/en_US.json @@ -92,13 +92,25 @@ "term.time.released": "Released", "term.time.updated": "Updated", "term.time.days": "days", - "term.time.day": "day", + "term.time.day": { + "one": "day", + "other": "days" + }, "term.time.hours": "hours", - "term.time.hour": "hour", + "term.time.hour": { + "one": "hour", + "other": "hours" + }, "term.time.minutes": "minutes", - "term.time.minute": "minute", + "term.time.minute": { + "one": "minute", + "other": "minutes" + }, "term.time.seconds": "seconds", - "term.time.second": "second", + "term.time.second": { + "one": "second", + "other": "seconds" + }, "term.fullscreenView": "Fullscreen View", "term.defaultView": "Default View", "term.audioSettings": "Audio Settings", diff --git a/src/i18n/zh_TW.json b/src/i18n/zh_TW.json index 04382661..82279d02 100644 --- a/src/i18n/zh_TW.json +++ b/src/i18n/zh_TW.json @@ -218,6 +218,14 @@ "settings.option.audio.seamlessTransition": "無間斷播放", "settings.option.audio.enableAdvancedFunctionality": "進階音訊功能", "settings.option.audio.enableAdvancedFunctionality.description": "啟用 AudioContext 將開啟類似音訊平衡和等化器的進階設定。但這並不一定適合每部電腦,可能會發生音樂卡頓。", + "settings.option.audio.audioLab": "Cider 音訊實驗室", + "settings.option.audio.audioLab.description": "包含由 Cider 開發團隊進行的各種音訊改善功能。", + "settings.warn.audioLab.withoutAF": "使用 Cider 音訊實驗室需要開啟進階音訊功能才能使用。" , + "settings.option.audio.enableAdvancedFunctionality.analogWarmth": "模擬溫暖", + "settings.option.audio.enableAdvancedFunctionality.analogWarmth.description": "以 Korg Nutube 6P1 為設計的模擬溫暖", + "settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.description": "改變模擬溫暖模組處理的強度。", + "settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.smooth": "溫和", + "settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.warm": "溫暖", "settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider 數位增強音訊處理™️", "settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "將欺騙您的大腦讓您感受到近似保真壓縮的音質。| 由 Maikiwi 設計", "settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength": "數位增強音訊處理設定", @@ -251,13 +259,19 @@ "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", "settings.header.visual.theme": "主題", "settings.option.visual.theme.github.download": "從 GitHub 網址安裝", - "settings.option.visual.theme.github.explore": "瀏覽 GitHub 上的主題", + "settings.option.visual.theme.github.explore": "探索 GitHub 上的主題", + "settings.option.visual.plugin.github.explore": "探索 GitHub 插件", + "settings.header.visual.plugin.github.page": "來自 GitHub 的插件", "settings.prompt.visual.theme.github.URL": "輸入你要安裝的主題網址", "settings.notyf.visual.theme.install.success": "主題成功安裝", "settings.notyf.visual.theme.install.error": "主題安裝失敗", - "settings.option.visual.theme.default": "Cider", - "settings.option.visual.theme.dark": "暗黑模式", + "settings.option.visual.theme.default": "預設", + "settings.option.visual.theme.dark": "午夜黑", "settings.option.visual.showPersonalInfo": "顯示個人檔案", + "settings.header.window": "視窗", + "settings.header.window.description": "調整 Cider 的視窗設定", + "settings.option.window.openOnStartup": "開機時,啟動 Cider ", + "settings.option.window.openOnStartup.hidden": "啟動時,自動隱藏至系統列", "settings.header.lyrics": "歌詞", "settings.header.lyrics.description": "調整 Cider 的歌詞設定", "settings.option.lyrics.enableMusixmatch": "啟用 Musixmatch 歌詞", @@ -285,7 +299,11 @@ "settings.option.experimental.closeButtonBehaviour": "關閉按鈕操作", "settings.option.window.close_button_hide": "關閉按鈕將 Cider 隱藏至系統列", "settings.option.experimental.inline_playlists": "將播放列表做為行内元素顯示", - "spatial.notTurnedOn": "空間音訊目前是關閉狀態,請先啟用再使用。", + "settings.option.advanced.playlistTrackMapping": "播放列表追蹤映射", + "settings.option.advanced.playlistTrackMapping.description": "開啟對播放列表的深度掃描,以確定歌曲在哪些播放列表中。但播放列表快取時間會顯著增加。", + "settings.option.visual.transparent": "透明視窗框架", + "settings.option.visual.transparent.description": "透明視窗框架(需要主題支援,且須重新啟動)。", + "spatial.notTurnedOn": "空間音訊目前是關閉狀態,請先開啟再使用。", "spatial.spatialProperties": "空間音訊屬性設定", "spatial.width": "寬度", "spatial.height": "高度", diff --git a/src/main/base/browserwindow.ts b/src/main/base/browserwindow.ts index fc6eb37e..d922ad0d 100644 --- a/src/main/base/browserwindow.ts +++ b/src/main/base/browserwindow.ts @@ -894,11 +894,7 @@ export class BrowserWindow { }) app.on('before-quit', () => { - BrowserWindow.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.items)); - ipcRenderer.send('stopGCast','');`) + }) @@ -1135,6 +1131,11 @@ export class BrowserWindow { event.preventDefault(); BrowserWindow.win.hide(); } else { + BrowserWindow.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.items)); + ipcRenderer.send('stopGCast','');`) BrowserWindow.win.destroy(); } }) diff --git a/src/main/plugins/discordrpc.ts b/src/main/plugins/discordrpc.ts index e395b9fa..0a994ae2 100644 --- a/src/main/plugins/discordrpc.ts +++ b/src/main/plugins/discordrpc.ts @@ -164,7 +164,7 @@ export default class DiscordRichPresence { this._activity = { details: attributes.name, state: `${attributes.artistName ? `by ${attributes.artistName}` : ''}`, - startTimestamp: attributes.startTime, + startTimestamp: Date.now() - (attributes?.durationInMillis - attributes?.remainingTime), endTimestamp: attributes.endTime, largeImageKey: attributes?.artwork?.url?.replace('{w}', '1024').replace('{h}', '1024'), largeImageText: attributes.albumName, diff --git a/src/renderer/audio/audio.js b/src/renderer/audio/audio.js index 78a3bf5f..ce57ee12 100644 --- a/src/renderer/audio/audio.js +++ b/src/renderer/audio/audio.js @@ -72,21 +72,21 @@ const CiderAudio = { CiderAudio.audioNodes.spatialNode.normalize = true; switch (app.cfg.audio.maikiwiAudio.spatialType) { case 0: - fetch('./audio/impulses/CiderSpatial_Conv.wav').then(async (impulseData) => { + fetch('./audio/impulses/CiderSpatial_v69_Standard.wav').then(async (impulseData) => { let bufferedImpulse = await impulseData.arrayBuffer(); CiderAudio.audioNodes.spatialNode.buffer = await CiderAudio.context.decodeAudioData(bufferedImpulse); }); break; case 1: - fetch('./audio/impulses/CiderSpatial_Conv_v2.wav').then(async (impulseData) => { + fetch('./audio/impulses/CiderSpatial_v69_Audiophile.wav').then(async (impulseData) => { let bufferedImpulse = await impulseData.arrayBuffer(); CiderAudio.audioNodes.spatialNode.buffer = await CiderAudio.context.decodeAudioData(bufferedImpulse); }); break; default: - fetch('./audio/impulses/CiderSpatial_Conv.wav').then(async (impulseData) => { + fetch('./audio/impulses/CiderSpatial_v69_Standard.wav').then(async (impulseData) => { let bufferedImpulse = await impulseData.arrayBuffer(); CiderAudio.audioNodes.spatialNode.buffer = await CiderAudio.context.decodeAudioData(bufferedImpulse); diff --git a/src/renderer/audio/impulses/CiderSpatial_Conv.wav b/src/renderer/audio/impulses/CiderSpatial_Conv.wav deleted file mode 100644 index 06b2551e..00000000 Binary files a/src/renderer/audio/impulses/CiderSpatial_Conv.wav and /dev/null differ diff --git a/src/renderer/audio/impulses/CiderSpatial_Conv_v2.wav b/src/renderer/audio/impulses/CiderSpatial_Conv_v2.wav deleted file mode 100644 index dad94064..00000000 Binary files a/src/renderer/audio/impulses/CiderSpatial_Conv_v2.wav and /dev/null differ diff --git a/src/renderer/audio/impulses/CiderSpatial_v69_Audiophile.wav b/src/renderer/audio/impulses/CiderSpatial_v69_Audiophile.wav new file mode 100644 index 00000000..fb2b7716 Binary files /dev/null and b/src/renderer/audio/impulses/CiderSpatial_v69_Audiophile.wav differ diff --git a/src/renderer/audio/impulses/CiderSpatial_v69_Standard.wav b/src/renderer/audio/impulses/CiderSpatial_v69_Standard.wav new file mode 100644 index 00000000..0c1f6186 Binary files /dev/null and b/src/renderer/audio/impulses/CiderSpatial_v69_Standard.wav differ diff --git a/src/renderer/less/pages.less b/src/renderer/less/pages.less index 41fc5ea4..823c85f9 100644 --- a/src/renderer/less/pages.less +++ b/src/renderer/less/pages.less @@ -1,63 +1,65 @@ // Helpers .content-inner { - position: absolute; - top: var(--navigationBarHeight); - left: 0; - padding: 32px; - width: 100%; + position : absolute; + top : var(--navigationBarHeight); + left : 0; + padding : 32px; + width : 100%; transition: zoom 1s; - zoom: 1; + zoom : 1; } .content-inner.centered { - height: 100%; - display: flex; - flex-flow: column; + height : 100%; + display : flex; + flex-flow : column; justify-content: center; - align-items: center; + align-items : center; } + // End Helpers // GitHub Themes .github-themes-page { - display: flex; + display : flex; flex-direction: column; - padding: 0px; - height: calc(100% - var(--navigationBarHeight)); + padding : 0px; + height : calc(100% - var(--navigationBarHeight)); .github-avatar { - height: 42px; - width: 42px; - margin: 6px; + height : 42px; + width : 42px; + margin : 6px; border-radius: 32px; } .repo-name { - margin:0px; - font-weight: 500; - overflow: hidden; + margin : 0px; + font-weight : 500; + overflow : hidden; text-overflow: ellipsis; - white-space: break-spaces; + white-space : break-spaces; } .repo-url { - color: var(--textColor); + color : var(--textColor); font-size: 0.8em; } .repo-preview-name { - margin:0px; + margin: 0px; } .repos-list { - height: 100%; + height : 100%; overflow-y: overlay; - width: 320px; - font-size: 14px; + width : 320px; + font-size : 14px; >.list-group { - margin:0px; + margin: 0px; } + .list-group-item { padding: 12px 6px; @@ -72,18 +74,18 @@ } .github-preview { - height: 100%; - flex: 1; + height : 100%; + flex : 1; background: var(--color2); - padding: 16px 32px; - overflow-y:overlay; + padding : 16px 32px; + overflow-y: overlay; } .gh-content { - display: flex; + display : flex; flex-direction: row; - flex: 1; - overflow: hidden; + flex : 1; + overflow : hidden; } .gh-header { @@ -96,16 +98,16 @@ padding: 0px; .library-header { - position: sticky; - top: 0; - left: 0; - border-bottom: 1px solid rgba(200, 200, 200, 0.05); - z-index: 6; - background: black; - padding: 0px 2em; + position : sticky; + top : 0; + left : 0; + border-bottom : 1px solid rgba(200, 200, 200, 0.05); + z-index : 6; + background : black; + padding : 0px 2em; backdrop-filter: blur(32px); - background: rgba(0, 0, 0, 0.25); - top: var(--navigationBarHeight); + background : rgba(0, 0, 0, 0.25); + top : var(--navigationBarHeight); } .well { @@ -116,7 +118,7 @@ // Podcast Page .content-inner.podcasts-page { display: flex; - height: calc(100% - var(--navigationBarHeight)); + height : calc(100% - var(--navigationBarHeight)); padding: 0px; .list-flat { @@ -124,45 +126,45 @@ } .podcast-artwork { - width: 200px; + width : 200px; margin: 16px auto; height: 200px; } .podcasts-list { - height: 100%; - width: 280px; - background: rgb(200 200 200 / 10%); - overflow-y: overlay; + height : 100%; + width : 280px; + background : rgb(200 200 200 / 10%); + overflow-y : overlay; border-right: 1px solid var(--color2); - flex: none; - overflow-x: hidden; + flex : none; + overflow-x : hidden; .podcast-list-header { - border-bottom: 1px solid var(--color2); - font-size: 0.7em; - padding: 6px; - background: #ffffff17; + border-bottom : 1px solid var(--color2); + font-size : 0.7em; + padding : 6px; + background : #ffffff17; text-transform: uppercase; - font-weight: 600; - opacity: 0.5; + font-weight : 600; + opacity : 0.5; } .podcasts-search { - padding: 10px; - position: sticky; - top: 0; - left: 0; - width: 100%; + padding : 10px; + position : sticky; + top : 0; + left : 0; + width : 100%; border-bottom: 1px solid var(--color2); - z-index: 2; - background: #303030; + z-index : 2; + background : #303030; } } .episodes-list { - height: 100%; - width: 100%; + height : 100%; + width : 100%; background: rgb(200 200 200 / 6%); overflow-y: overlay; overflow-x: hidden; @@ -171,20 +173,20 @@ padding: 14px 14px 0px 14px; .podcast-show-info { - display: flex; + display : flex; justify-content: center; - flex-direction: column; + flex-direction : column; } .podcast-show-description { - margin: 32px 6px; - font-size: 0.8rem; + margin : 32px 6px; + font-size : 0.8rem; white-space: pre-wrap; - display: block; + display : block; } .podcast-artwork { - width: 120px; + width : 120px; margin: 0px auto; height: 120px; } @@ -197,14 +199,14 @@ } .podcasts-details { - width: 300px; - flex: none; - background: rgb(255 255 255 / 5%); - overflow-y: overlay; - overflow-x: hidden; - top: 2%; - z-index: 2; - border-left: 1px solid var(--color2); + width : 300px; + flex : none; + background : rgb(255 255 255 / 5%); + overflow-y : overlay; + overflow-x : hidden; + top : 2%; + z-index : 2; + border-left : 1px solid var(--color2); padding-bottom: 1em; .meta-btn { @@ -212,27 +214,27 @@ } .podcasts-details-header { - display: flex; + display : flex; justify-content: end; - align-items: center; - position: sticky; - top: 0; - z-index: 2; + align-items : center; + position : sticky; + top : 0; + z-index : 2; } .close-btn { - width: 50px; - height: 42px; - background-image: var(--gfx-closeBtn); + width : 50px; + height : 42px; + background-image : var(--gfx-closeBtn); background-position: center; - background-repeat: no-repeat; - -webkit-app-region: no-drag; - appearance: none; - border: 0; - background-color: transparent; - position: absolute; - top: 0; - right: 0; + background-repeat : no-repeat; + -webkit-app-region : no-drag; + appearance : none; + border : 0; + background-color : transparent; + position : absolute; + top : 0; + right : 0; &:hover { background-color: rgb(196, 43, 28) @@ -240,17 +242,17 @@ } .podcast-genre { - text-align: center; - margin: 6px; - font-size: 0.8em; + text-align : center; + margin : 6px; + font-size : 0.8em; font-weight: 500; - opacity: 0.8; + opacity : 0.8; } .podcast-metainfo { text-align: center; - font-size: 0.7em; - opacity: 0.8; + font-size : 0.7em; + opacity : 0.8; } .podcast-header { @@ -258,17 +260,17 @@ } .podcast-play-btn { - width: 50%; + width : 50%; display: block; - margin: 0 auto; + margin : 0 auto; } .podcast-description { - margin: 12px; - font-size: 0.75em; + margin : 12px; + font-size : 0.75em; white-space: pre-wrap; - display: block; - line-break: anywhere; + display : block; + line-break : anywhere; } @@ -279,188 +281,188 @@ @media only screen and (max-width: 1230px) { .content-inner.podcasts-page { .podcasts-details { - height: 96%; - width: 300px; - flex: none; - background: rgb(20 20 20 / 97%); - overflow-y: overlay; - overflow-x: hidden; - position: absolute; - right: 2%; - top: 2%; + height : 96%; + width : 300px; + flex : none; + background : rgb(20 20 20 / 97%); + overflow-y : overlay; + overflow-x : hidden; + position : absolute; + right : 2%; + top : 2%; border-radius: 10px; - box-shadow: var(--ciderShadow-Generic); - z-index: 2; + box-shadow : var(--ciderShadow-Generic); + z-index : 2; } } } /* Album / Playlist Page */ .playlist-page { - --bgColor: transparent; - padding: 0px; + --bgColor : transparent; + padding : 0px; //background: linear-gradient(180deg, var(--bgColor) 32px, var(--bgColor) 18px, transparent 60px, transparent 100%); - top: 0; - padding-top: var(--navigationBarHeight); + top : 0; + padding-top : var(--navigationBarHeight); .playlist-body { - padding: var(--contentInnerPadding) 2em; + padding : var(--contentInnerPadding) 2em; margin-top: -75px; } .floating-header { - position: sticky; - top: 0; - left: 0; - border-bottom: 1px solid rgba(200, 200, 200, 0.05); - z-index: 6; - padding: 0px 1em; + position : sticky; + top : 0; + left : 0; + border-bottom : 1px solid rgba(200, 200, 200, 0.05); + z-index : 6; + padding : 0px 1em; backdrop-filter: blur(32px); - background: rgba(0, 0, 0, 0.25); - top: var(--navigationBarHeight); - transition: opacity 0.1s var(--appleEase); + background : rgba(0, 0, 0, 0.25); + top : var(--navigationBarHeight); + transition : opacity 0.1s var(--appleEase); } .playlist-display { - padding: var(--contentInnerPadding); + padding : var(--contentInnerPadding); min-height: 300px; - position: relative; + position : relative; .artworkContainer { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - margin: 0; - margin-top: calc(var(--navigationBarHeight) * -1); - margin-bottom: -10px; - padding: 0; + position : absolute; + top : 0; + left : 0; + bottom : 0; + right : 0; + margin : 0; + margin-top : calc(var(--navigationBarHeight) * -1); + margin-bottom : -10px; + padding : 0; -webkit-mask-image: radial-gradient(at top left, black, transparent 70%), radial-gradient(at top right, black, transparent 70%), linear-gradient(180deg, rgb(200 200 200), transparent 98%); - opacity: .7; - animation: playlistArtworkFadeIn 1s var(--appleEase); + opacity : .7; + animation : playlistArtworkFadeIn 1s var(--appleEase); - .artworkMaterial > img { - filter: brightness(100%) blur(80px) saturate(100%) contrast(1); + .artworkMaterial>img { + filter : brightness(100%) blur(80px) saturate(100%) contrast(1); object-position: center; - object-fit: cover; - width: 100%; - height: 100%; - transform: unset; + object-fit : cover; + width : 100%; + height : 100%; + transform : unset; } } .playlistInfo { - z-index: 1; - position: absolute; - bottom: 0; - left: 0; - right: 0; - top: 0; - display: flex; + z-index : 1; + position : absolute; + bottom : 0; + left : 0; + right : 0; + top : 0; + display : flex; justify-content: center; - align-items: center; - width: 100%; - height: 100%; + align-items : center; + width : 100%; + height : 100%; - > .row { + >.row { width: calc(100% - 32px); } .playlist-info { - flex-shrink: unset; - display: flex; - flex-flow: column; + flex-shrink : unset; + display : flex; + flex-flow : column; justify-content: flex-end; .playlist-name { - font-weight: 700; - font-size: 1.6rem; + font-weight : 700; + font-size : 1.6rem; //margin-bottom: 6px; - margin-right: 6px; - flex-shrink: unset; + margin-right : 6px; + flex-shrink : unset; } .nameEdit { - font-weight: 700; - font-size: 1.6rem; + font-weight : 700; + font-size : 1.6rem; margin-bottom: 6px; - margin-right: 6px; - flex-shrink: unset; - background: transparent; - border: 0px; - color: inherit; - font-family: inherit; + margin-right : 6px; + flex-shrink : unset; + background : transparent; + border : 0px; + color : inherit; + font-family : inherit; } .playlist-artist { - font-size: 20px; + font-size : 20px; margin-bottom: 6px; - margin-right: 6px; - flex-shrink: unset; + margin-right : 6px; + flex-shrink : unset; } .playlist-desc { - box-sizing: border-box; - font-size: 14px; - flex-shrink: unset; + box-sizing : border-box; + font-size : 14px; + flex-shrink : unset; margin-right: 5px; - max-height: 100px; - position: relative; + max-height : 100px; + position : relative; .content { - height: 100px; + height : 100px; -webkit-mask-image: -webkit-gradient(linear, left 50%, left 90%, from(rgba(0, 0, 0, 1)), to(rgba(0, 0, 0, 0))); } .more-btn { - appearance: none; - position: absolute; - right: 0; - bottom: 0; - padding: 0 5px; - font-size: 14px; - color: var(--keyColor); + appearance : none; + position : absolute; + right : 0; + bottom : 0; + padding : 0 5px; + font-size : 14px; + color : var(--keyColor); background-color: transparent; - border: 0px; - cursor: pointer; - width: 100%; - height: 100%; - overflow: hidden; - display: flex; - justify-content: flex-end; - align-items: flex-end; - font-weight: 600; - font-family: inherit; - text-transform: uppercase; + border : 0px; + cursor : pointer; + width : 100%; + height : 100%; + overflow : hidden; + display : flex; + justify-content : flex-end; + align-items : flex-end; + font-weight : 600; + font-family : inherit; + text-transform : uppercase; } } .playlist-desc-expanded { box-sizing: border-box; - font-size: 14px; - position: relative; + font-size : 14px; + position : relative; .more-btn { - appearance: none; - position: absolute; - right: 0; - bottom: 0; - padding: 0 5px; - font-size: 14px; - color: var(--keyColor); + appearance : none; + position : absolute; + right : 0; + bottom : 0; + padding : 0 5px; + font-size : 14px; + color : var(--keyColor); background-color: transparent; - border: 0px; - cursor: pointer; - width: 100%; - height: 100%; - overflow: hidden; - display: flex; - justify-content: flex-end; - align-items: flex-end; - font-weight: 600; - font-family: inherit; - text-transform: uppercase; + border : 0px; + cursor : pointer; + width : 100%; + height : 100%; + overflow : hidden; + display : flex; + justify-content : flex-end; + align-items : flex-end; + font-weight : 600; + font-family : inherit; + text-transform : uppercase; } } } @@ -470,21 +472,21 @@ } .friends-info { - display: flex; + display : flex; flex-flow: column; .badge-container { - display: flex; + display : flex; flex-flow: wrap; .socialBadge { - width: 40px; - height: 40px; + width : 40px; + height : 40px; border-radius: 100%; - overflow: hidden; - box-shadow: var(--mediaItemShadow-ShadowSubtle); - transition: transform .2s var(--appleEase); - margin: 6px; + overflow : hidden; + box-shadow : var(--mediaItemShadow-ShadowSubtle); + transition : transform .2s var(--appleEase); + margin : 6px; &:hover { transform: scale(1.2); @@ -494,54 +496,56 @@ .friends-name { text-align: center; - font-size: 0.9em; - margin: 8px; + font-size : 0.9em; + margin : 8px; } } .playlist-time { font-size: 0.9em; - margin: 6px; - opacity: 0.7; + margin : 6px; + opacity : 0.7; } &.inline-playlist { - overflow: hidden; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.5); - display: flex; + overflow : hidden; + width : 100%; + height : 100%; + background : rgba(0, 0, 0, 0.5); + display : flex; justify-content: center; - align-items: center; - z-index: 6; - position: sticky; - margin-top: calc(var(--navigationBarHeight) * -1); + align-items : center; + z-index : 6; + position : sticky; + margin-top : calc(var(--navigationBarHeight) * -1); .floating-header { - opacity: 1; - top: 0px; - z-index: 6; - padding: 1em; + opacity : 1; + top : 0px; + z-index : 6; + padding : 1em; backdrop-filter: unset; - background: black; + background : black; + h3 { display: none; } } + .playlist-inner { - background: black; - width: 80%; - height: 100%; - overflow: overlay; - box-shadow: var(--ciderShadow-Generic); + background : black; + width : 80%; + height : 100%; + overflow : overlay; + box-shadow : var(--ciderShadow-Generic); border-radius: var(--mediaItemRadius) var(--mediaItemRadius) 0px 0px; .close-btn { - position: sticky; - top: 16px; - left: 16px; + position : sticky; + top : 16px; + left : 16px; margin-left: 16px; - z-index: 7; + z-index : 7; } } } @@ -551,6 +555,7 @@ 0% { opacity: 0; } + 100% { opacity: 0.7; } @@ -561,20 +566,20 @@ padding-bottom: 128px; .top-fab { - height: 52px; - width: 52px; - position: fixed; - bottom: 32px; - right: 32px; + height : 52px; + width : 52px; + position : fixed; + bottom : 32px; + right : 32px; border-radius: 100%; - background: rgb(60 60 60); - border: 0px; - appearance: none; - box-shadow: var(--ciderShadow-Generic); + background : rgb(60 60 60); + border : 0px; + appearance : none; + box-shadow : var(--ciderShadow-Generic); - > svg { - height: 50%; - color: #eee; + >svg { + height : 50%; + color : #eee; pointer-events: none; } @@ -596,88 +601,88 @@ .artist-page { padding: 0px; - top: 0; + top : 0; .floating-header { - position: sticky; - top: 0; - left: 0; - border-bottom: 1px solid rgba(200, 200, 200, 0.05); - z-index: 6; - padding: 0px 1em; + position : sticky; + top : 0; + left : 0; + border-bottom : 1px solid rgba(200, 200, 200, 0.05); + z-index : 6; + padding : 0px 1em; backdrop-filter: blur(32px); - background: rgba(0, 0, 0, 0.25); - top: var(--navigationBarHeight); - transition: opacity 0.1s var(--appleEase); + background : rgba(0, 0, 0, 0.25); + top : var(--navigationBarHeight); + transition : opacity 0.1s var(--appleEase); } &.animated .artist-header .more-btn-round { position: absolute; - bottom: 22px !important; - right: 28px; + bottom : 22px !important; + right : 28px; } .artist-header { //background: linear-gradient(45deg, var(--keyColor), #0e0e0e); - color: white; - display: flex; - align-items: center; + color : white; + display : flex; + align-items : center; justify-content: space-between; - min-height: 400px; - position: relative; - pointer-events: none; + min-height : 400px; + position : relative; + pointer-events : none; .header-content { - z-index: 1; + z-index : 1; margin-top: -16px; } .artworkContainer { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - margin: 0; - padding: 0; + position : absolute; + top : 0; + left : 0; + bottom : 0; + right : 0; + margin : 0; + padding : 0; -webkit-mask-image: radial-gradient(at top left, black, transparent 70%), radial-gradient(at top right, black, transparent 70%), linear-gradient(180deg, rgb(200 200 200), transparent 98%); - opacity: .7; - animation: playlistArtworkFadeIn 1s var(--appleEase); + opacity : .7; + animation : playlistArtworkFadeIn 1s var(--appleEase); - .artworkMaterial > img { - filter: brightness(100%) blur(80px) saturate(100%) contrast(1); + .artworkMaterial>img { + filter : brightness(100%) blur(80px) saturate(100%) contrast(1); object-position: center; - object-fit: cover; - width: 100%; - height: 100%; - transform: unset; + object-fit : cover; + width : 100%; + height : 100%; + transform : unset; } } .more-btn-round { position: absolute; - bottom: 82px; - right: 28px; + bottom : 82px; + right : 28px; } .animated { - width: 100%; - height: 100%; + width : 100%; + height : 100%; align-self: center; - position: absolute; - overflow: hidden; + position : absolute; + overflow : hidden; box-shadow: rgb(0 0 0 / 50%) 0 0 0 1000000px inset; video { - overflow: hidden; - height: 100%; - width: 100%; + overflow : hidden; + height : 100%; + width : 100%; min-height: 56.25vw; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); + position : absolute; + top : 50%; + left : 50%; + transform : translate(-50%, -50%); } } @@ -687,29 +692,29 @@ } .artist-image { - width: 200px; - height: 200px; - margin: 32px; + width : 200px; + height : 200px; + margin : 32px; position: relative; .overlay-play { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - opacity: 0; - background: rgb(0 0 0 / 50%); - transition: opacity 0.1s var(--appleEase); - border-radius: 100%; - z-index: 1; - display: flex; - align-items: center; + position : absolute; + top : 0; + left : 0; + width : 100%; + height : 100%; + opacity : 0; + background : rgb(0 0 0 / 50%); + transition : opacity 0.1s var(--appleEase); + border-radius : 100%; + z-index : 1; + display : flex; + align-items : center; justify-content: center; - cursor: pointer; - appearance: none; - border: 0px; - padding: 0px; + cursor : pointer; + appearance : none; + border : 0px; + padding : 0px; &:hover { opacity: 1; @@ -719,32 +724,32 @@ background: var(--selected-click); } - > svg { + >svg { width: 70%; } } } .artist-play { - width: 32px; - height: 32px; - background: rgba(100, 100, 100, 0.5); - box-shadow: var(--ciderShadow-Generic); + width : 32px; + height : 32px; + background : rgba(100, 100, 100, 0.5); + box-shadow : var(--ciderShadow-Generic); border-radius: 100%; - box-shadow: var(--mediaItemShadow); - display: none; - cursor: pointer; - appearance: none; - border: 0px; - padding: 0px; + box-shadow : var(--mediaItemShadow); + display : none; + cursor : pointer; + appearance : none; + border : 0px; + padding : 0px; &:hover { filter: brightness(125%); } &:active { - filter: brightness(75%); - transform: scale(0.98); + filter : brightness(75%); + transform : scale(0.98); transition: transform 0s var(--appleEase), box-shadow 0.2s var(--appleEase); } } @@ -753,16 +758,16 @@ .artist-play { transform: translateY(3px); - margin: 14px; + margin : 14px; } &.artist-animation-on { - width: 100%; - flex: unset; + width : 100%; + flex : unset; margin-left: 0.5em; - color: whitesmoke; - position: absolute; - bottom: 0; + color : whitesmoke; + position : absolute; + bottom : 0; .artist-play { display: block; @@ -772,27 +777,43 @@ .artist-body { padding: 0px var(--contentInnerPadding) 0px var(--contentInnerPadding); - margin: -140px 20px; + margin : -140px 20px; + + .arow { + display : flex; + overflow: hidden; + padding : 16px 32px; + >.latestRelease { + width: 250px; + } + >.topSongs { + width: calc(100% - 250px); + } + + &.arowb>.topSongs { + width: 100%; + } + } } - &.animated > .artist-body { - padding: 0px var(--contentInnerPadding) 0px var(--contentInnerPadding); + &.animated>.artist-body { + padding : 0px var(--contentInnerPadding) 0px var(--contentInnerPadding); margin-top: -57px; } .showmoreless { - font-family: inherit; - font-size: 16px; - font-weight: 500; - background: transparent; - border: 0px; + font-family : inherit; + font-size : 16px; + font-weight : 500; + background : transparent; + border : 0px; border-radius: 6px; - appearance: none; - color: var(--keyColor); - padding: 8px 12px; - cursor: pointer; - margin-top: 12px; - float: right; + appearance : none; + color : var(--keyColor); + padding : 8px 12px; + cursor : pointer; + margin-top : 12px; + float : right; } .showmoreless:hover { @@ -807,12 +828,12 @@ padding: 0px; .md-option-header { - padding: 1.25em 1.25em; + padding : 1.25em 1.25em; border-bottom: unset; - border-top: unset; - font-weight: 600; - font-size: 1.0em; - background: rgb(255 255 255 / 3%); + border-top : unset; + font-weight : 600; + font-size : 1.0em; + background : rgb(255 255 255 / 3%); } .settings-option-body { @@ -822,79 +843,80 @@ //Home .home-page { - top: 0; + top : 0; padding-top: var(--navbarHeight); .md-btn-replay { - background: var(--replayGradient); - border: 0px; - box-shadow: inset 0px 0px 0px 1px rgba(200, 200, 200, 0.2); + background : var(--replayGradient); + border : 0px; + box-shadow : inset 0px 0px 0px 1px rgba(200, 200, 200, 0.2); text-transform: uppercase; - font-weight: bold; + font-weight : bold; } + .md-btn-replay--hero { - font-size: 1em; - padding: 16px; - background: var(--replayGradient); - border: 0px; - box-shadow: inset 0px 0px 0px 1px rgb(200 200 200 / 20%); - margin-top: 1em; - font-size: 0.9em; + font-size : 1em; + padding : 16px; + background : var(--replayGradient); + border : 0px; + box-shadow : inset 0px 0px 0px 1px rgb(200 200 200 / 20%); + margin-top : 1em; + font-size : 0.9em; text-transform: uppercase; - font-weight: bold; + font-weight : bold; } .artist-feed-card { - position: absolute; - bottom: 0; - left: 10%; - z-index: 1; - background: black; - width: 80%; - height: 96%; - overflow: scroll; + position : absolute; + bottom : 0; + left : 10%; + z-index : 1; + background : black; + width : 80%; + height : 96%; + overflow : scroll; border-radius: 10px; } .col.madeforyou-col { - width: 420px; + width : 420px; min-width: 0px; max-width: 420px; } .well.artistfeed-well { - margin-top: 0px; - height: 392px; + margin-top : 0px; + height : 392px; align-content: flex-start; } .hint-text { font-size: 0.9rem; - color: rgb(200 200 200 / 70%); + color : rgb(200 200 200 / 70%); } .user-icon { border-radius: 100%; - width: 128px; - height: 128px; - overflow: hidden; - box-shadow: var(--mediaItemShadow-Shadow); - margin: 16px; + width : 128px; + height : 128px; + overflow : hidden; + box-shadow : var(--mediaItemShadow-Shadow); + margin : 16px; } .well.profile-well { - flex-direction: column; + flex-direction : column; justify-content: center; - align-items: center; + align-items : center; .name { - margin: 4px; + margin : 4px; font-weight: 500; } .handle { - margin: 4px; - opacity: 0.7; + margin : 4px; + opacity : 0.7; font-weight: 500; } } @@ -905,29 +927,32 @@ --replayTextShadow: 0px 3px 2px #6f3f52; .replay-period { - height: 200px; - width: 200px; - margin: 6px; - border-radius: var(--mediaItemRadius); - overflow: hidden; - cursor: pointer; - transition: transform .2s var(--appleEase); + height : 200px; + width : 200px; + margin : 6px; + border-radius : var(--mediaItemRadius); + overflow : hidden; + cursor : pointer; + transition : transform .2s var(--appleEase); transition-delay: .1s; - align-self: center; + align-self : center; + &:hover { - transform: translateY(-6px); + transform : translateY(-6px); transition-delay: 0s; } + .artwork-container { - height:200px; - width:200px; + height: 200px; + width : 200px; } } .replay-playlist-container { .cd-mediaitem-square { height: 230px; - width: 230px; + width : 230px; + .info-rect { display: none; } @@ -936,42 +961,44 @@ .replay-video { max-height: 300px; - max-width: 800px; - margin: 0 auto; + max-width : 800px; + margin : 0 auto; .mediaitem-artwork { max-height: 300px; - max-width: 800px; + max-width : 800px; } .mediaitem-artwork .animatedartwork-view-box .animated video { object-fit: cover; } } + .top-genres-container { .genre-name { - font-size: 0.9em; - margin: 6px 0px; + font-size : 0.9em; + margin : 6px 0px; font-weight: 500; } + .genre-count { - width: 100%; - height: 32px; - background: #ffffff14; + width : 100%; + height : 32px; + background : #ffffff14; border-radius: 10px; - overflow: hidden; + overflow : hidden; .genre-count-bar { - height: 100%; - width: 0%; - background: var(--keyColor); - display: flex; + height : 100%; + width : 0%; + background : var(--keyColor); + display : flex; justify-content: center; - align-items: center; - min-width: 32px; - font-size: 0.9em; - font-weight: 500; + align-items : center; + min-width : 32px; + font-size : 0.9em; + font-weight : 500; } } } @@ -980,10 +1007,12 @@ .mediaitem-artwork { animation: replayFadeIn .5s var(--appleEase); } - transition: transform .2s var(--appleEase); + + transition : transform .2s var(--appleEase); transition-delay: .1s; + &:hover { - transform: scale(1.1); + transform : scale(1.1); transition-delay: 0s; } } @@ -992,31 +1021,32 @@ 0% { //border-radius: 100%; transform: translateY(10px) scale(0.9); - opacity: 0; + opacity : 0; } 100% { //border-radius: var(--mediaItemRadius); transform: scale(1); - opacity: 1; + opacity : 1; } } .replay-viewport { - background: var(--replayGradient); - padding: 16px 40px; + background : var(--replayGradient); + padding : 16px 40px; border-radius: 10px; - box-shadow: var(--mediaItemShadow), var(--mediaItemShadow-Shadow); - color: rgb(238 238 238 / 86%); + box-shadow : var(--mediaItemShadow), var(--mediaItemShadow-Shadow); + color : rgb(238 238 238 / 86%); .replay-header { - text-align: center; - font-size: 3em; + text-align : center; + font-size : 3em; text-shadow: var(--replayTextShadow); } } + .replay-card { background: transparent; - border:0px; + border : 0px; } } \ No newline at end of file diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index 3d3a3572..2573e87a 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -297,6 +297,10 @@ const app = new Vue({ } this.lz = ipcRenderer.sendSync("get-i18n", lang) this.mklang = await this.MKJSLang() + try{ + this.listennow.timestamp = 0; + this.browsepage.timestamp = 0; + }catch(e){} }, /** * Grabs translation for localization. @@ -1400,72 +1404,58 @@ const app = new Vue({ } }, /** - * Converts seconds to dd:hh:mm:ss - * @param {number} time (in seconds) + * Converts seconds to dd:hh:mm:ss / Days:Hours:Minutes:Seconds + * @param {number} seconds * @param {string} format (short, long) * @returns {string} * @author Core#1034 * @memberOf app */ - convertTime(time = 0, format = 'short') { + convertTime(seconds, format = "short") { - if (isNaN(time)) { - time = 0 + if (isNaN(seconds)) { + seconds = 0 } - if (typeof time !== "number") { - time = parseInt(time) + seconds = parseInt(seconds); + + const datetime = new Date(seconds * 1000) + + if (format === "long") { + const d = Math.floor(seconds / (3600*24)); + const h = Math.floor(seconds % (3600*24) / 3600); + const m = Math.floor(seconds % 3600 / 60); + const s = Math.floor(seconds % 60); + + const dDisplay = d > 0 ? `${d} ${app.getLz("term.time.day", {"count": d})}, ` : ""; + const hDisplay = h > 0 ? `${h} ${app.getLz("term.time.hour", {"count": h})}, ` : ""; + const mDisplay = m > 0 ? `${m} ${app.getLz("term.time.minute", {"count": m})}, ` : ""; + const sDisplay = s > 0 ? `${s} ${app.getLz("term.time.second", {"count": s})}` : ""; + + return dDisplay + hDisplay + mDisplay + sDisplay; } + else { + let returnTime = datetime.toISOString().substring(11, 19); - const timeGates = { - 600: 15, // 10 Minutes - 3600: 14, // Hour - 36000: 12, // 10 Hours - } - - const datetime = new Date(time * 1000) - - let returnTime = datetime.toISOString().substring(11, 19); - for (let key in timeGates) { - if (time < key) { - returnTime = datetime.toISOString().substring(timeGates[key], 19) - break - } - } - - // Add the days on the front - let day; - if (time >= 86400) { - day = datetime.toISOString().substring(8, 10) - day = parseInt(day) - 1 - returnTime = day + ":" + returnTime - } - - if (format === 'long') { - const longFormat = [] - - // Seconds - if (datetime.getSeconds() !== 0) { - longFormat.push(`${datetime.getSeconds()} ${app.getLz('term.time.seconds')}`) + const timeGates = { + 600: 15, // 10 Minutes + 3600: 14, // Hour + 36000: 12, // 10 Hours } - // Minutes - if (time >= 60) { - longFormat.push(`${datetime.getMinutes()} ${app.getLz(`term.time.${datetime.getMinutes() === 1 ? 'minute' : 'minutes'}`)}`) + for (let key in timeGates) { + if (seconds < key) { + returnTime = datetime.toISOString().substring(timeGates[key], 19) + break + } } - // Hours - if (time >= 3600) { - longFormat.push(`${datetime.getHours()} ${app.getLz(`term.time.${datetime.getHours() === 1 ? 'hour' : 'hours'}`)}`) + // Add the days on the front + if (seconds >= 86400) { + returnTime = parseInt(datetime.toISOString().substring(8, 10)) - 1 + ":" + returnTime } - // Days - if (time >= 86400) { - longFormat.push(`${day} ${app.getLz(`term.time.${day === 1 ? 'day' : 'days'}`)}`) - } - returnTime = longFormat.reverse().join(', ') + return returnTime } - - return returnTime }, hashCode(str) { let hash = 0, @@ -1862,10 +1852,10 @@ const app = new Vue({ } // remove any non-alphanumeric characters and spaces from search term and item name - searchTerm = searchTerm.replace(/[^a-z0-9 ]/gi, "") - itemName = itemName.replace(/[^a-z0-9 ]/gi, "") - artistName = artistName.replace(/[^a-z0-9 ]/gi, "") - albumName = albumName.replace(/[^a-z0-9 ]/gi, "") + searchTerm = searchTerm.replace(/[^\p{L}\p{N} ]/gu, "") + itemName = itemName.replace(/[^\p{L}\p{N} ]/gu, "") + artistName = artistName.replace(/[^\p{L}\p{N} ]/gu, "") + albumName = albumName.replace(/[^\p{L}\p{N} ]/gu, "") if (itemName.includes(searchTerm) || artistName.includes(searchTerm) || albumName.includes(searchTerm)) { return item @@ -1931,10 +1921,10 @@ const app = new Vue({ } // remove any non-alphanumeric characters and spaces from search term and item name - searchTerm = searchTerm.replace(/[^a-z0-9 ]/gi, "") - itemName = itemName.replace(/[^a-z0-9 ]/gi, "") - artistName = artistName.replace(/[^a-z0-9 ]/gi, "") - albumName = albumName.replace(/[^a-z0-9 ]/gi, "") + searchTerm = searchTerm.replace(/[^\p{L}\p{N} ]/gu, "") + itemName = itemName.replace(/[^\p{L}\p{N} ]/gu, "") + artistName = artistName.replace(/[^\p{L}\p{N} ]/gu, "") + albumName = albumName.replace(/[^\p{L}\p{N} ]/gu, "") if (itemName.includes(searchTerm) || artistName.includes(searchTerm) || albumName.includes(searchTerm)) { return item @@ -1996,8 +1986,8 @@ const app = new Vue({ // } // remove any non-alphanumeric characters and spaces from search term and item name - searchTerm = searchTerm.replace(/[^a-z0-9 ]/gi, "") - itemName = itemName.replace(/[^a-z0-9 ]/gi, "") + searchTerm = searchTerm.replace(/[^\p{L}\p{N} ]/gu, "") + itemName = itemName.replace(/[^\p{L}\p{N} ]/gu, "") if (itemName.includes(searchTerm) || artistName.includes(searchTerm) || albumName.includes(searchTerm)) { @@ -4021,4 +4011,4 @@ const app = new Vue({ }) -export { app } \ No newline at end of file +export { app } diff --git a/src/renderer/views/pages/artist.ejs b/src/renderer/views/pages/artist.ejs index b7bcab37..04171b26 100644 --- a/src/renderer/views/pages/artist.ejs +++ b/src/renderer/views/pages/artist.ejs @@ -56,8 +56,8 @@