Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
47a48673e6
43 changed files with 367 additions and 99 deletions
|
@ -39,7 +39,7 @@
|
||||||
"@sentry/electron": "^3.0.7",
|
"@sentry/electron": "^3.0.7",
|
||||||
"@sentry/integrations": "^6.19.6",
|
"@sentry/integrations": "^6.19.6",
|
||||||
"adm-zip": "0.4.10",
|
"adm-zip": "0.4.10",
|
||||||
"airtunes2": "git+https://github.com/vapormusic/node_airtunes2.git",
|
"airtunes2": "git+https://github.com/vapormusic/node_airtunes2.git#hap",
|
||||||
"castv2-client": "^1.2.0",
|
"castv2-client": "^1.2.0",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"discord-rpc": "^4.0.1",
|
"discord-rpc": "^4.0.1",
|
||||||
|
@ -109,9 +109,9 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"build": {
|
"build": {
|
||||||
"electronVersion": "18.1.0",
|
"electronVersion": "18.2.0",
|
||||||
"electronDownload": {
|
"electronDownload": {
|
||||||
"version": "18.1.0+wvcus",
|
"version": "18.2.0+wvcus",
|
||||||
"mirror": "https://github.com/castlabs/electron-releases/releases/download/v"
|
"mirror": "https://github.com/castlabs/electron-releases/releases/download/v"
|
||||||
},
|
},
|
||||||
"appId": "cider",
|
"appId": "cider",
|
||||||
|
|
|
@ -406,6 +406,7 @@
|
||||||
"settings.option.lyrics.enableMusixmatchKaraoke": "Karaoke mód bekapcsolása (Csak MusixMatch)",
|
"settings.option.lyrics.enableMusixmatchKaraoke": "Karaoke mód bekapcsolása (Csak MusixMatch)",
|
||||||
"settings.option.lyrics.musixmatchPreferredLanguage": "MusixMatch fordítás nyelve",
|
"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.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": "Csatlakozások",
|
||||||
"settings.header.connectivity.description": "A Cider csatlakozás beállításainak módosítása.",
|
"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",
|
"settings.option.connectivity.playbackNotifications": "Lejátszási értesítések",
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"term.login": "登录",
|
"term.login": "登录",
|
||||||
"term.about": "关于",
|
"term.about": "关于",
|
||||||
"term.privateSession": "私人聆听",
|
"term.privateSession": "私人聆听",
|
||||||
|
"term.lyrics": "歌词",
|
||||||
"term.queue": "待播清单",
|
"term.queue": "待播清单",
|
||||||
"term.history": "历史记录",
|
"term.history": "历史记录",
|
||||||
"term.miniplayer": "迷你播放器",
|
"term.miniplayer": "迷你播放器",
|
||||||
|
@ -115,7 +116,11 @@
|
||||||
"term.contributors": "贡献者",
|
"term.contributors": "贡献者",
|
||||||
"term.equalizer": "均衡器",
|
"term.equalizer": "均衡器",
|
||||||
"term.reset": "重置",
|
"term.reset": "重置",
|
||||||
"term.tracks": "首歌曲",
|
"term.track": {
|
||||||
|
"one": "首歌曲",
|
||||||
|
"other": "首歌曲"
|
||||||
|
},
|
||||||
|
"term.tracks": "歌曲",
|
||||||
"term.videos": "音乐视频",
|
"term.videos": "音乐视频",
|
||||||
"term.menu": "菜单",
|
"term.menu": "菜单",
|
||||||
"term.check": "检查",
|
"term.check": "检查",
|
||||||
|
@ -161,6 +166,9 @@
|
||||||
"podcast.episodes": "单集",
|
"podcast.episodes": "单集",
|
||||||
"podcast.playEpisode": "播放单集",
|
"podcast.playEpisode": "播放单集",
|
||||||
"podcast.website": "Podcast 网站",
|
"podcast.website": "Podcast 网站",
|
||||||
|
"action.edit": "编辑",
|
||||||
|
"action.done": "完成",
|
||||||
|
"action.editTracklist": "编辑歌曲清单",
|
||||||
"action.addToLibrary": "加入资料库",
|
"action.addToLibrary": "加入资料库",
|
||||||
"action.addToLibrary.success": "成功加入资料库",
|
"action.addToLibrary.success": "成功加入资料库",
|
||||||
"action.addToLibrary.error": "加入资料库的过程发生了错误",
|
"action.addToLibrary.error": "加入资料库的过程发生了错误",
|
||||||
|
@ -187,6 +195,7 @@
|
||||||
"action.startRadio": "开始电台",
|
"action.startRadio": "开始电台",
|
||||||
"action.goToArtist": "前往艺人",
|
"action.goToArtist": "前往艺人",
|
||||||
"action.goToAlbum": "前往专辑",
|
"action.goToAlbum": "前往专辑",
|
||||||
|
"action.showInAppleMusic": "显示于 Apple Music",
|
||||||
"action.moveToTop": "移到顶部",
|
"action.moveToTop": "移到顶部",
|
||||||
"action.share": "分享歌曲",
|
"action.share": "分享歌曲",
|
||||||
"action.rename": "重命名",
|
"action.rename": "重命名",
|
||||||
|
@ -203,11 +212,19 @@
|
||||||
"action.showAlbum": "显示专辑",
|
"action.showAlbum": "显示专辑",
|
||||||
"action.tray.minimize": "最小化",
|
"action.tray.minimize": "最小化",
|
||||||
"action.tray.quit": "退出",
|
"action.tray.quit": "退出",
|
||||||
|
|
||||||
"action.update": "更新",
|
"action.update": "更新",
|
||||||
"action.copy": "复制",
|
"action.copy": "复制",
|
||||||
"action.newpreset": "新建默认...",
|
"action.newpreset": "新建默认...",
|
||||||
"action.deletepreset": "删除默认",
|
"action.deletepreset": "删除默认",
|
||||||
|
"action.open": "打开",
|
||||||
|
"action.cast.chromecast": "Chromecast",
|
||||||
|
"action.cast.todevices": "投射到设备",
|
||||||
|
"action.cast.stop": "停止投射到所有设备",
|
||||||
|
"action.cast.airplay": "AirPlay",
|
||||||
|
"action.cast.airplay.underdevelopment": "AirPlay 仍处于开发阶段中,敬请期待。",
|
||||||
|
"action.cast.scan": "搜索",
|
||||||
|
"action.cast.scanning": "搜索中...",
|
||||||
|
"action.createNew": "添加...",
|
||||||
"settings.header.general": "通用",
|
"settings.header.general": "通用",
|
||||||
"settings.header.general.description": "调整 Cider 的通用设置",
|
"settings.header.general.description": "调整 Cider 的通用设置",
|
||||||
"settings.option.audio.volumeStep": "音量改变量",
|
"settings.option.audio.volumeStep": "音量改变量",
|
||||||
|
@ -218,6 +235,10 @@
|
||||||
"settings.option.general.resumebehavior.locally.description": "Cider 将还原你在这台电脑上的最后一次操作。",
|
"settings.option.general.resumebehavior.locally.description": "Cider 将还原你在这台电脑上的最后一次操作。",
|
||||||
"settings.option.general.resumebehavior.history": "历史",
|
"settings.option.general.resumebehavior.history": "历史",
|
||||||
"settings.option.general.resumebehavior.history.description": "Cider 将跨设备将你的整个 Apple Music 历史记录中的最后一首歌曲排队入列。",
|
"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": "语言",
|
"settings.option.general.language": "语言",
|
||||||
"settings.option.general.language.main": "语言",
|
"settings.option.general.language.main": "语言",
|
||||||
"settings.option.general.language.fun": "恶搞语言",
|
"settings.option.general.language.fun": "恶搞语言",
|
||||||
|
@ -229,6 +250,8 @@
|
||||||
"settings.option.general.updateCider.branch.develop": "测试(Develop)",
|
"settings.option.general.updateCider.branch.develop": "测试(Develop)",
|
||||||
"settings.option.general.customizeSidebar": "自定义侧边栏的功能",
|
"settings.option.general.customizeSidebar": "自定义侧边栏的功能",
|
||||||
"settings.option.general.customizeSidebar.customize": "自定义",
|
"settings.option.general.customizeSidebar.customize": "自定义",
|
||||||
|
"settings.option.general.keybindings": "快捷操作键",
|
||||||
|
"settings.option.general.keybindings.open": "打开",
|
||||||
"settings.notyf.updateCider.update-not-available": "没有可用的更新",
|
"settings.notyf.updateCider.update-not-available": "没有可用的更新",
|
||||||
"settings.notyf.updateCider.update-downloaded": "更新已成功下载,重启后进行更新",
|
"settings.notyf.updateCider.update-downloaded": "更新已成功下载,重启后进行更新",
|
||||||
"settings.notyf.updateCider.update-error": "更新时,发生错误",
|
"settings.notyf.updateCider.update-error": "更新时,发生错误",
|
||||||
|
@ -250,20 +273,27 @@
|
||||||
"settings.option.audio.audioLab": "Cider 音频实验室",
|
"settings.option.audio.audioLab": "Cider 音频实验室",
|
||||||
"settings.option.audio.audioLab.description": "包含由 Cider 开发团队进行的各种音频优化功能。",
|
"settings.option.audio.audioLab.description": "包含由 Cider 开发团队进行的各种音频优化功能。",
|
||||||
"settings.warn.audioLab.withoutAF": "使用 Cider 音频实验室需要打开进阶音频功能才可使用。" ,
|
"settings.warn.audioLab.withoutAF": "使用 Cider 音频实验室需要打开进阶音频功能才可使用。" ,
|
||||||
"settings.option.audio.enableAdvancedFunctionality.analogWarmth": "模拟温暖",
|
"settings.option.audio.enableAdvancedFunctionality.analogWarmth": "模拟温暖",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.analogWarmth.description": "以 Korg Nutube 6P1 为蓝本的模拟温暖。",
|
"settings.option.audio.enableAdvancedFunctionality.analogWarmth.description": "以 Korg Nutube 6P1 为蓝本的模拟温暖。",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity": "模拟温暖强度",
|
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity": "模拟温暖强度",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.description": "改变模拟温暖模组处理的强度。",
|
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.description": "改变模拟温暖模组处理的强度。",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.smooth": "温和",
|
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.smooth": "温和",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.warm": "温暖",
|
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.warm": "温暖",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider 数码增强音频处理™️",
|
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer": "Cider 音乐气氛实现器™️",
|
||||||
|
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer.description": "以最先进的音频置为蓝本,实现不同的音乐气氛。",
|
||||||
|
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode": "Cider 音乐气氛™️模式",
|
||||||
|
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.description": "更改气氛实现器模块的操作模式。",
|
||||||
|
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural1": "自然(标准)",
|
||||||
|
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural2": "自然(高)",
|
||||||
|
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural3": "自然(增强)",
|
||||||
|
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider 数码增强音频处理™️",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "通过人类的听力心理学模型和 AAC 编码特色的即时算法,强化 256 kbps AAC 音频的感知音频质量。",
|
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "通过人类的听力心理学模型和 AAC 编码特色的即时算法,强化 256 kbps AAC 音频的感知音频质量。",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength": "数码增强音频处理设置",
|
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength": "数码增强音频处理设置",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.description": "将更改音频处理的激进/振奋程度(增强选项有可能会引起杂讯)。",
|
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.description": "将更改音频处理的激进/振奋程度(增强选项有可能会引起杂讯)。",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.standard": "标准",
|
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.standard": "标准",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.aggressive": "增强",
|
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.aggressive": "增强",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.audioNormalization": "音量平衡",
|
"settings.option.audio.enableAdvancedFunctionality.audioNormalization": "音量平衡",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "自动将歌曲播放音量调整到相同水平,享受更舒适的聆听体验。",
|
"settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "自动将歌曲播放音量调整到相同水平,享受更舒适的聆听体验。",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.audioNormalization.disabled": "此功能由音频实验室管理",
|
"settings.option.audio.enableAdvancedFunctionality.audioNormalization.disabled": "此功能由音频实验室管理",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "空间音频",
|
"settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "空间音频",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "将音频进行空间化处理来制造一个更立体的聆听体验(注:此功能不是官方的杜比全景声)。",
|
"settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "将音频进行空间化处理来制造一个更立体的聆听体验(注:此功能不是官方的杜比全景声)。",
|
||||||
|
@ -274,6 +304,7 @@
|
||||||
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.standard": "标准",
|
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.standard": "标准",
|
||||||
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.audiophile": "发烧友",
|
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.audiophile": "发烧友",
|
||||||
"settings.warn.audio.enableAdvancedFunctionality.audioSpatialization.compatibility": "音频空间无法与 CAP 相容,请关闭 CAP 在进行操作。",
|
"settings.warn.audio.enableAdvancedFunctionality.audioSpatialization.compatibility": "音频空间无法与 CAP 相容,请关闭 CAP 在进行操作。",
|
||||||
|
"settings.option.visual.uiscale": "UI界面大小",
|
||||||
"settings.header.visual": "外观",
|
"settings.header.visual": "外观",
|
||||||
"settings.header.visual.description": "调整 Cider 的外观",
|
"settings.header.visual.description": "调整 Cider 的外观",
|
||||||
"settings.option.visual.windowBackgroundStyle": "窗口背景样式",
|
"settings.option.visual.windowBackgroundStyle": "窗口背景样式",
|
||||||
|
@ -327,14 +358,16 @@
|
||||||
"settings.option.lyrics.enableMusixmatchKaraoke": "启用卡拉 OK 模式(仅 Musixmatch)",
|
"settings.option.lyrics.enableMusixmatchKaraoke": "启用卡拉 OK 模式(仅 Musixmatch)",
|
||||||
"settings.option.lyrics.musixmatchPreferredLanguage": "Musixmatch 歌词语言偏好",
|
"settings.option.lyrics.musixmatchPreferredLanguage": "Musixmatch 歌词语言偏好",
|
||||||
"settings.option.lyrics.enableYoutubeLyrics": "播放 MV 时使用 YouTube 歌词",
|
"settings.option.lyrics.enableYoutubeLyrics": "播放 MV 时使用 YouTube 歌词",
|
||||||
|
"settings.option.lyrics.enableQQLyrics": "启用 QQ 音乐的歌词",
|
||||||
"settings.header.connectivity": "外部连接",
|
"settings.header.connectivity": "外部连接",
|
||||||
"settings.header.connectivity.description": "调整 Cider 与外部应用的交互设置",
|
"settings.header.connectivity.description": "调整 Cider 与外部应用的交互设置",
|
||||||
"settings.option.connectivity.discordRPC": "Discord 动态",
|
"settings.option.connectivity.discordRPC": "Discord 动态",
|
||||||
"settings.option.connectivity.playbackNotifications": "歌曲播放通知",
|
"settings.option.connectivity.playbackNotifications": "歌曲播放通知",
|
||||||
"settings.header.connectivity.discordRPC.cider": "显示正在使用 'Cider'",
|
"settings.option.connectivity.discordRPC.clientName": "应用程序名称",
|
||||||
"settings.header.connectivity.discordRPC.appleMusic": "显示正在使用 'Apple Music'",
|
|
||||||
"settings.option.connectivity.discordRPC.clearOnPause": "暂停时清除 Discord 动态",
|
"settings.option.connectivity.discordRPC.clearOnPause": "暂停时清除 Discord 动态",
|
||||||
"settings.option.connectivity.discordRPC.hideButtons": "隐藏 Discord 动态上的按钮",
|
"settings.option.connectivity.discordRPC.hideButtons": "隐藏 Discord 动态上的按钮",
|
||||||
|
"settings.option.connectivity.discordRPC.detailsFormat": "详细信息格式",
|
||||||
|
"settings.option.connectivity.discordRPC.stateFormat": "动态格式",
|
||||||
"settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling 记录",
|
"settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling 记录",
|
||||||
"settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble 延迟 (%)",
|
"settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble 延迟 (%)",
|
||||||
"settings.option.connectivity.lastfmScrobble.nowPlaying": "打开 LastFM 正在播放",
|
"settings.option.connectivity.lastfmScrobble.nowPlaying": "打开 LastFM 正在播放",
|
||||||
|
|
|
@ -151,6 +151,9 @@
|
||||||
"podcast.episodes": "單集",
|
"podcast.episodes": "單集",
|
||||||
"podcast.playEpisode": "播放單集",
|
"podcast.playEpisode": "播放單集",
|
||||||
"podcast.website": "Podcast 網站",
|
"podcast.website": "Podcast 網站",
|
||||||
|
"action.edit": "編輯",
|
||||||
|
"action.done": "完成",
|
||||||
|
"action.editTracklist": "編輯歌曲清單",
|
||||||
"action.addToLibrary": "加入到資料庫",
|
"action.addToLibrary": "加入到資料庫",
|
||||||
"action.addToLibrary.success": "成功加入資料庫",
|
"action.addToLibrary.success": "成功加入資料庫",
|
||||||
"action.addToLibrary.error": "加入資料庫時,發生錯誤",
|
"action.addToLibrary.error": "加入資料庫時,發生錯誤",
|
||||||
|
@ -215,6 +218,10 @@
|
||||||
"settings.option.general.resumebehavior.locally.description": "Cider 將還原你在這台電腦上的最後一次操作。",
|
"settings.option.general.resumebehavior.locally.description": "Cider 將還原你在這台電腦上的最後一次操作。",
|
||||||
"settings.option.general.resumebehavior.history": "歷史",
|
"settings.option.general.resumebehavior.history": "歷史",
|
||||||
"settings.option.general.resumebehavior.history.description": "Cider 將跨裝置將你的整個 Apple Music 歷史記錄中的最後一首歌曲排隊入列。",
|
"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.main": "語言",
|
||||||
"settings.option.general.language.fun": "特殊語言",
|
"settings.option.general.language.fun": "特殊語言",
|
||||||
"settings.option.general.language.unsorted": "未分類",
|
"settings.option.general.language.unsorted": "未分類",
|
||||||
|
@ -345,8 +352,8 @@
|
||||||
"settings.option.connectivity.discordRPC.hideButtons": "隱藏 Discord 動態上的按鈕",
|
"settings.option.connectivity.discordRPC.hideButtons": "隱藏 Discord 動態上的按鈕",
|
||||||
"settings.option.connectivity.discordRPC.detailsFormat": "詳細資訊格式",
|
"settings.option.connectivity.discordRPC.detailsFormat": "詳細資訊格式",
|
||||||
"settings.option.connectivity.discordRPC.stateFormat": "狀態格式",
|
"settings.option.connectivity.discordRPC.stateFormat": "狀態格式",
|
||||||
"settings.option.connectivity.lastfmScrobble": "Last.FM Scrobbling 記錄",
|
"settings.option.connectivity.lastfmScrobble": "Last.FM 音樂記錄",
|
||||||
"settings.option.connectivity.lastfmScrobble.delay": "Last.FM Scrobble 延遲 (%)",
|
"settings.option.connectivity.lastfmScrobble.delay": "Last.FM 歌曲追蹤延遲 (%)",
|
||||||
"settings.option.connectivity.lastfmScrobble.nowPlaying": "開啟 Last.FM 正在聆聽",
|
"settings.option.connectivity.lastfmScrobble.nowPlaying": "開啟 Last.FM 正在聆聽",
|
||||||
"settings.option.connectivity.lastfmScrobble.removeFeatured": "從歌名中移除客串藝人 (Last.FM)",
|
"settings.option.connectivity.lastfmScrobble.removeFeatured": "從歌名中移除客串藝人 (Last.FM)",
|
||||||
"settings.option.connectivity.lastfmScrobble.filterLoop": "不記錄單曲循環 (Last.FM)",
|
"settings.option.connectivity.lastfmScrobble.filterLoop": "不記錄單曲循環 (Last.FM)",
|
||||||
|
|
|
@ -212,7 +212,6 @@ export class AppEvents {
|
||||||
* Handles the creation of a new instance of the app
|
* Handles the creation of a new instance of the app
|
||||||
*/
|
*/
|
||||||
private InstanceHandler() {
|
private InstanceHandler() {
|
||||||
|
|
||||||
// Detects of an existing instance is running (So if the lock has been achieved, no existing instance has been found)
|
// Detects of an existing instance is running (So if the lock has been achieved, no existing instance has been found)
|
||||||
const gotTheLock = app.requestSingleInstanceLock()
|
const gotTheLock = app.requestSingleInstanceLock()
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ export class BrowserWindow {
|
||||||
platform: process.platform,
|
platform: process.platform,
|
||||||
dev: app.isPackaged,
|
dev: app.isPackaged,
|
||||||
osRelease: os.release(),
|
osRelease: os.release(),
|
||||||
|
updatable: !process.windowsStore || !process.mas,
|
||||||
components: [
|
components: [
|
||||||
"pages/podcasts",
|
"pages/podcasts",
|
||||||
"pages/apple-account-settings",
|
"pages/apple-account-settings",
|
||||||
|
@ -95,6 +96,7 @@ export class BrowserWindow {
|
||||||
"components/fullscreen",
|
"components/fullscreen",
|
||||||
"components/miniplayer",
|
"components/miniplayer",
|
||||||
"components/castmenu",
|
"components/castmenu",
|
||||||
|
"components/airplay-modal",
|
||||||
"components/artist-chip",
|
"components/artist-chip",
|
||||||
"components/hello-world",
|
"components/hello-world",
|
||||||
"components/inline-collection-list",
|
"components/inline-collection-list",
|
||||||
|
@ -897,6 +899,10 @@ export class BrowserWindow {
|
||||||
event.returnValue = process.platform;
|
event.returnValue = process.platform;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on("get-port", (event) => {
|
||||||
|
event.returnValue = this.clientPort;
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.on("is-dev", (event) => {
|
ipcMain.on("is-dev", (event) => {
|
||||||
event.returnValue = this.devMode;
|
event.returnValue = this.devMode;
|
||||||
});
|
});
|
||||||
|
@ -1209,16 +1215,27 @@ export class BrowserWindow {
|
||||||
shell.openPath(app.getPath('userData'));
|
shell.openPath(app.getPath('userData'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//#region Cider Connect
|
||||||
ipcMain.on('cc-auth', (_event) => {
|
ipcMain.on('cc-auth', (_event) => {
|
||||||
shell.openExternal(String(utils.getStoreValue('cc_authURL')));
|
shell.openExternal(String(utils.getStoreValue('cc_authURL')));
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('cc-logout', (_event) => {
|
ipcMain.on('cc-logout', (_event) => { //Make sure to update the default store
|
||||||
utils.setStoreValue('connectUser', {
|
utils.setStoreValue('connectUser', {
|
||||||
auth: null
|
"auth": null,
|
||||||
|
"sync": {
|
||||||
|
themes: false,
|
||||||
|
plugins: false,
|
||||||
|
settings: false,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
utils.getWindow().reload();
|
utils.getWindow().reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on('cc-push', (_event) => {
|
||||||
|
utils.pushStoreToConnect();
|
||||||
|
})
|
||||||
/* *********************************************************************************************
|
/* *********************************************************************************************
|
||||||
* Window Events
|
* Window Events
|
||||||
* **********************************************************************************************/
|
* **********************************************************************************************/
|
||||||
|
|
|
@ -26,9 +26,9 @@ export class Plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getPluginFromMap(plugin: string): any {
|
public static getPluginFromMap(plugin: string): any {
|
||||||
if(Plugins.PluginMap[plugin]) {
|
if (Plugins.PluginMap[plugin]) {
|
||||||
return Plugins.PluginMap[plugin];
|
return Plugins.PluginMap[plugin];
|
||||||
}else{
|
} else {
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as ElectronStore from 'electron-store';
|
import * as ElectronStore from 'electron-store';
|
||||||
import * as electron from "electron";
|
import * as electron from "electron";
|
||||||
import {app} from "electron";
|
import {app} from "electron";
|
||||||
|
import fetch from "electron-fetch";
|
||||||
export class Store {
|
export class Store {
|
||||||
static cfg: ElectronStore;
|
static cfg: ElectronStore;
|
||||||
|
|
||||||
|
@ -212,6 +212,11 @@ export class Store {
|
||||||
},
|
},
|
||||||
"connectUser": {
|
"connectUser": {
|
||||||
"auth": null,
|
"auth": null,
|
||||||
|
"sync": {
|
||||||
|
themes: false,
|
||||||
|
plugins: false,
|
||||||
|
settings: false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
private migrations: any = {
|
private migrations: any = {
|
||||||
|
@ -261,6 +266,7 @@ export class Store {
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IPC Handler
|
* IPC Handler
|
||||||
*/
|
*/
|
||||||
|
@ -281,5 +287,43 @@ export class Store {
|
||||||
Store.cfg.store = store
|
Store.cfg.store = store
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static pushToCloud(): void {
|
||||||
|
if (Store.cfg.get('connectUser.auth') === null) return;
|
||||||
|
var syncData = Object();
|
||||||
|
if (Store.cfg.get('connectUser.sync.themes')) {
|
||||||
|
syncData.push({
|
||||||
|
themes: Store.cfg.store.themes
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (Store.cfg.get('connectUser.sync.plugins')) {
|
||||||
|
syncData.push({
|
||||||
|
plugins: Store.cfg.store.plugins
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Store.cfg.get('connectUser.sync.settings')) {
|
||||||
|
syncData.push({
|
||||||
|
general: Store.cfg.get('general'),
|
||||||
|
home: Store.cfg.get('home'),
|
||||||
|
libraryPrefs: Store.cfg.get('libraryPrefs'),
|
||||||
|
advanced: Store.cfg.get('advanced'),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let postBody = {
|
||||||
|
id: Store.cfg.get('connectUser.id'),
|
||||||
|
app: electron.app.getName(),
|
||||||
|
version: electron.app.isPackaged ? electron.app.getVersion() : 'dev',
|
||||||
|
syncData: syncData
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch('https://connect.cidercollective.dev/api/v1/setttings/set', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(postBody)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ export class utils {
|
||||||
return Store.cfg.store
|
return Store.cfg.store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the store instance
|
* Get the store instance
|
||||||
* @returns {Store}
|
* @returns {Store}
|
||||||
|
@ -97,6 +98,18 @@ export class utils {
|
||||||
Store.cfg.set(key, value)
|
Store.cfg.set(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes Store to Connect
|
||||||
|
* @return Function
|
||||||
|
*/
|
||||||
|
static pushStoreToConnect(): Function {
|
||||||
|
return Store.pushToCloud
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the browser window
|
* Gets the browser window
|
||||||
*/
|
*/
|
||||||
|
@ -198,4 +211,6 @@ export class utils {
|
||||||
autoUpdater.logger = log
|
autoUpdater.logger = log
|
||||||
await autoUpdater.checkForUpdatesAndNotify()
|
await autoUpdater.checkForUpdatesAndNotify()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ export default class ChromecastPlugin {
|
||||||
// private GCstream = new Stream.PassThrough(),
|
// private GCstream = new Stream.PassThrough(),
|
||||||
private connectedHosts: any = {};
|
private connectedHosts: any = {};
|
||||||
private connectedPlayer: any;
|
private connectedPlayer: any;
|
||||||
// private port = false;
|
private ciderPort :any = 9000;
|
||||||
// private server = false;
|
// private server = false;
|
||||||
// private bufcount = 0;
|
// private bufcount = 0;
|
||||||
// private bufcount2 = 0;
|
// private bufcount2 = 0;
|
||||||
|
@ -148,7 +148,7 @@ export default class ChromecastPlugin {
|
||||||
}
|
}
|
||||||
let media = {
|
let media = {
|
||||||
// Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
|
// Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
|
||||||
contentId: 'http://' + this.getIp() + ':9000/audio.wav',
|
contentId: 'http://' + this.getIp() + ':'+ this.ciderPort +'/audio.wav',
|
||||||
contentType: 'audio/wav',
|
contentType: 'audio/wav',
|
||||||
streamType: 'LIVE', // or LIVE
|
streamType: 'LIVE', // or LIVE
|
||||||
|
|
||||||
|
@ -361,4 +361,12 @@ export default class ChromecastPlugin {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onRendererReady(): void {
|
||||||
|
this._win.webContents.executeJavaScript(
|
||||||
|
`ipcRenderer.sendSync('get-port')`
|
||||||
|
).then((result: any) => {
|
||||||
|
this.ciderPort = result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -89,9 +89,9 @@ export default class RAOP {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
private ondeviceup(name: any, host: any, port: any, addresses: any, text: any) {
|
private ondeviceup(name: any, host: any, port: any, addresses: any, text: any) {
|
||||||
if (this.castDevices.findIndex((item: any) => item.name === host && item.port === port && item.addresses === addresses) === -1) {
|
if (this.castDevices.findIndex((item: any) => item.name == host.replace(".local","") && item.port == port && item.addresses == addresses) === -1) {
|
||||||
this.castDevices.push({
|
this.castDevices.push({
|
||||||
name: host,
|
name: host.replace(".local",""),
|
||||||
host: addresses ? addresses[0] : '',
|
host: addresses ? addresses[0] : '',
|
||||||
port: port,
|
port: port,
|
||||||
addresses: addresses,
|
addresses: addresses,
|
||||||
|
@ -147,14 +147,28 @@ export default class RAOP {
|
||||||
browser.on('ready', browser.discover);
|
browser.on('ready', browser.discover);
|
||||||
|
|
||||||
browser.on('update', (service: any) => {
|
browser.on('update', (service: any) => {
|
||||||
if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp') || service.fullname.includes('_airplay._tcp'))) {
|
if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp') || service.fullname.includes('_airplay._tcp'))) {
|
||||||
// console.log(service.txt)
|
// console.log(service.txt)
|
||||||
this._win.webContents.executeJavaScript(`console.log(
|
this._win.webContents.executeJavaScript(`console.log(
|
||||||
"${service.name} ${service.host}:${service.port} ${service.addresses}"
|
"${service.name} ${service.host}:${service.port} ${service.addresses}"
|
||||||
)`);
|
)`);
|
||||||
this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt);}
|
this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// const browser2 = this.mdns.createBrowser(this.mdns.tcp('airplay'));
|
||||||
|
// browser2.on('ready', browser2.discover);
|
||||||
|
|
||||||
|
// browser2.on('update', (service: any) => {
|
||||||
|
// if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp') || service.fullname.includes('_airplay._tcp'))) {
|
||||||
|
// // console.log(service.txt)
|
||||||
|
// this._win.webContents.executeJavaScript(`console.log(
|
||||||
|
// "${service.name} ${service.host}:${service.port} ${service.addresses}"
|
||||||
|
// )`);
|
||||||
|
// this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,6 +192,15 @@ export default class RAOP {
|
||||||
this._win.webContents.setAudioMuted(true);
|
this._win.webContents.setAudioMuted(true);
|
||||||
this._win.webContents.executeJavaScript(`CiderAudio.sendAudio()`).catch((err: any) => console.error(err));
|
this._win.webContents.executeJavaScript(`CiderAudio.sendAudio()`).catch((err: any) => console.error(err));
|
||||||
}
|
}
|
||||||
|
if (status == "need_password"){
|
||||||
|
this._win.webContents.executeJavaScript(`app.setAirPlayCodeUI()`)
|
||||||
|
}
|
||||||
|
if (status == "pair_success"){
|
||||||
|
this._win.webContents.executeJavaScript(`app.sendAirPlaySuccess()`)
|
||||||
|
}
|
||||||
|
if (status == "pair_failed"){
|
||||||
|
this._win.webContents.executeJavaScript(`app.sendAirPlayFailed()`)
|
||||||
|
}
|
||||||
if (status == 'stopped') {
|
if (status == 'stopped') {
|
||||||
this.airtunes.stopAll(() => {
|
this.airtunes.stopAll(() => {
|
||||||
console.log('end');
|
console.log('end');
|
||||||
|
@ -210,6 +233,12 @@ export default class RAOP {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
electron.ipcMain.on('setAirPlayPasscode', (event, passcode) => {
|
||||||
|
if (this.device){
|
||||||
|
this.device.setPasscode(passcode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
electron.ipcMain.on('writeWAV', (event, leftbuffer, rightbuffer) => {
|
electron.ipcMain.on('writeWAV', (event, leftbuffer, rightbuffer) => {
|
||||||
if (this.airtunes != null) {
|
if (this.airtunes != null) {
|
||||||
if (this.worker == null) {
|
if (this.worker == null) {
|
||||||
|
|
1
src/renderer/assets/feather/heart-fill.svg
Normal file
1
src/renderer/assets/feather/heart-fill.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-heart"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg>
|
After Width: | Height: | Size: 379 B |
|
@ -105,7 +105,7 @@ function fallbackinitMusicKit() {
|
||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
app.init()
|
app.init()
|
||||||
if(app.cfg.visual.window_background_style == "mica" && !app.isDev) {
|
if (app.cfg.visual.window_background_style == "mica" && !app.isDev) {
|
||||||
app.spawnMica()
|
app.spawnMica()
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
@ -134,7 +134,7 @@ document.addEventListener('musickitloaded', function () {
|
||||||
function waitForApp() {
|
function waitForApp() {
|
||||||
if (typeof app.init !== "undefined") {
|
if (typeof app.init !== "undefined") {
|
||||||
app.init()
|
app.init()
|
||||||
if(app.cfg.visual.window_background_style == "mica" && !app.isDev) {
|
if (app.cfg.visual.window_background_style == "mica" && !app.isDev) {
|
||||||
app.spawnMica()
|
app.spawnMica()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -371,6 +371,11 @@
|
||||||
filter: contrast(0);
|
filter: contrast(0);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
.heart-icon {
|
||||||
|
position: absolute;
|
||||||
|
filter: contrast(0);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
@keyframes load-bar {
|
@keyframes load-bar {
|
||||||
10% {
|
10% {
|
||||||
box-shadow: inset 0 -4px 0;
|
box-shadow: inset 0 -4px 0;
|
||||||
|
|
|
@ -456,6 +456,13 @@
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heart-icon {
|
||||||
|
position: absolute;
|
||||||
|
right:0;
|
||||||
|
filter: contrast(0);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
/* CSS.gg
|
/* CSS.gg
|
||||||
*/
|
*/
|
||||||
@keyframes load-bar {
|
@keyframes load-bar {
|
||||||
|
|
|
@ -70,10 +70,11 @@
|
||||||
|
|
||||||
.spatialproperties-panel {
|
.spatialproperties-panel {
|
||||||
.modal-window {
|
.modal-window {
|
||||||
|
&:not(.airplay-modal){
|
||||||
height : 700px;
|
height : 700px;
|
||||||
max-height: 700px;
|
max-height: 700px;
|
||||||
width : 800px;
|
width : 800px;
|
||||||
max-width : 800px;
|
max-width : 800px;}
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
|
|
||||||
.info-header {
|
.info-header {
|
||||||
|
|
|
@ -22,7 +22,7 @@ const Events = {
|
||||||
if (event.keyCode === 82 && event.ctrlKey) {
|
if (event.keyCode === 82 && event.ctrlKey) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
bootbox.confirm("Reload Cider?", (res)=>{
|
bootbox.confirm("Reload Cider?", (res)=>{
|
||||||
if(res) {
|
if (res) {
|
||||||
window.location.reload()
|
window.location.reload()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -251,9 +251,9 @@ function simulateGamepad () {
|
||||||
|
|
||||||
cursorPos[1] -= cursorSpeed
|
cursorPos[1] -= cursorSpeed
|
||||||
// sounds.Hover.play()
|
// sounds.Hover.play()
|
||||||
// if(intTabIndex <= 0) {
|
// if (intTabIndex <= 0) {
|
||||||
// intTabIndex = 0
|
// intTabIndex = 0
|
||||||
// }else{
|
// } else {
|
||||||
// intTabIndex--
|
// intTabIndex--
|
||||||
// }
|
// }
|
||||||
// $(tabbable[intTabIndex]).focus()
|
// $(tabbable[intTabIndex]).focus()
|
||||||
|
@ -263,9 +263,9 @@ function simulateGamepad () {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
cursorPos[1] += cursorSpeed
|
cursorPos[1] += cursorSpeed
|
||||||
// if(intTabIndex < tabbable.length) {
|
// if (intTabIndex < tabbable.length) {
|
||||||
// intTabIndex++
|
// intTabIndex++
|
||||||
// }else{
|
// } else {
|
||||||
// intTabIndex = tabbable.length
|
// intTabIndex = tabbable.length
|
||||||
// }
|
// }
|
||||||
// $(tabbable[intTabIndex]).focus()
|
// $(tabbable[intTabIndex]).focus()
|
||||||
|
|
|
@ -207,6 +207,7 @@ const app = new Vue({
|
||||||
showPlaylist: false,
|
showPlaylist: false,
|
||||||
castMenu: false,
|
castMenu: false,
|
||||||
moreInfo: false,
|
moreInfo: false,
|
||||||
|
airplayPW: false,
|
||||||
},
|
},
|
||||||
socialBadges: {
|
socialBadges: {
|
||||||
badgeMap: {},
|
badgeMap: {},
|
||||||
|
@ -1671,11 +1672,11 @@ const app = new Vue({
|
||||||
params["meta[albums:tracks]"] = 'popularity'
|
params["meta[albums:tracks]"] = 'popularity'
|
||||||
params["fields[albums]"] = "artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialNotes,editorialVideo,name,playParams,releaseDate,url,copyright"
|
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);
|
app.page = (kind) + "_" + (id);
|
||||||
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
||||||
app.getTypeFromID((kind), (id), (isLibrary), params);
|
app.getTypeFromID((kind), (id), (isLibrary), params);
|
||||||
}else{
|
} else {
|
||||||
app.page = (kind)
|
app.page = (kind)
|
||||||
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
||||||
}
|
}
|
||||||
|
@ -3830,6 +3831,15 @@ const app = new Vue({
|
||||||
|
|
||||||
// tracks are found in relationship.data
|
// tracks are found in relationship.data
|
||||||
},
|
},
|
||||||
|
setAirPlayCodeUI() {
|
||||||
|
this.modals.airplayPW = true
|
||||||
|
},
|
||||||
|
sendAirPlaySuccess(){
|
||||||
|
notyf.success('Device paired successfully!');
|
||||||
|
},
|
||||||
|
sendAirPlayFailed(){
|
||||||
|
notyf.error('Device paring failed!');
|
||||||
|
},
|
||||||
windowFocus(val) {
|
windowFocus(val) {
|
||||||
if (val) {
|
if (val) {
|
||||||
document.querySelectorAll(".animated-artwork-video").forEach(el => {
|
document.querySelectorAll(".animated-artwork-video").forEach(el => {
|
||||||
|
@ -4009,7 +4019,8 @@ const app = new Vue({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app.mk.nowPlayingItem._container["attributes"] && app.mk.nowPlayingItem._container.name != "station") {
|
const nowPlayingContainer = app.mk.nowPlayingItem._container;
|
||||||
|
if (nowPlayingContainer && nowPlayingContainer["attributes"] && nowPlayingContainer.name != "station") {
|
||||||
menus.normal.items.find(x => x.id == "showInMusic").hidden = false
|
menus.normal.items.find(x => x.id == "showInMusic").hidden = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,11 +108,11 @@ const wsapi = {
|
||||||
app.mk.isPlaying ? app.mk.pause() : app.mk.play()
|
app.mk.isPlaying ? app.mk.pause() : app.mk.play()
|
||||||
},
|
},
|
||||||
toggleRepeat() {
|
toggleRepeat() {
|
||||||
if(MusicKit.getInstance().repeatMode == 0) {
|
if (MusicKit.getInstance().repeatMode == 0) {
|
||||||
MusicKit.getInstance().repeatMode = 1
|
MusicKit.getInstance().repeatMode = 1
|
||||||
}else if(MusicKit.getInstance().repeatMode == 1){
|
} else if (MusicKit.getInstance().repeatMode == 1){
|
||||||
MusicKit.getInstance().repeatMode = 2
|
MusicKit.getInstance().repeatMode = 2
|
||||||
}else{
|
} else {
|
||||||
MusicKit.getInstance().repeatMode = 0
|
MusicKit.getInstance().repeatMode = 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -7936,6 +7936,15 @@ fieldset:disabled .btn {
|
||||||
filter: contrast(0);
|
filter: contrast(0);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
.cd-mediaitem-list-item .playIcon{
|
||||||
|
width: 44px;
|
||||||
|
margin-left: 11px;
|
||||||
|
}
|
||||||
|
.cd-mediaitem-list-item .heart-icon {
|
||||||
|
position: absolute;
|
||||||
|
filter: contrast(0);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
@keyframes load-bar {
|
@keyframes load-bar {
|
||||||
10% {
|
10% {
|
||||||
box-shadow: inset 0 -4px 0;
|
box-shadow: inset 0 -4px 0;
|
||||||
|
|
|
@ -1207,6 +1207,14 @@ body[platform="darwin"] .app-chrome .app-chrome-item > .window-controls > div.cl
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heart-icon {
|
||||||
|
height: 9px;
|
||||||
|
width: 13px;
|
||||||
|
filter: contrast(0);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.lossless-icon {
|
.lossless-icon {
|
||||||
|
|
|
@ -133,11 +133,11 @@ app.mkapi("artists", false, "412778295", {
|
||||||
var library = []
|
var library = []
|
||||||
var downloaded = null;
|
var downloaded = null;
|
||||||
function downloadChunk () {
|
function downloadChunk () {
|
||||||
if(downloaded == null) {
|
if (downloaded == null) {
|
||||||
app.mk.api.library.songs("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{
|
app.mk.api.library.songs("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{
|
||||||
processChunk(response)
|
processChunk(response)
|
||||||
})
|
})
|
||||||
}else{
|
} else {
|
||||||
downloaded.next("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{
|
downloaded.next("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{
|
||||||
processChunk(response)
|
processChunk(response)
|
||||||
})
|
})
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
<transition name="modal">
|
<transition name="modal">
|
||||||
<castmenu v-if="modals.castMenu"></castmenu>
|
<castmenu v-if="modals.castMenu"></castmenu>
|
||||||
</transition>
|
</transition>
|
||||||
|
<transition name="modal">
|
||||||
|
<airplay-modal v-if="modals.airplayPW"></airplay-modal>
|
||||||
|
</transition>
|
||||||
<transition name="modal">
|
<transition name="modal">
|
||||||
<plugin-menu v-if="modals.pluginMenu"></plugin-menu>
|
<plugin-menu v-if="modals.pluginMenu"></plugin-menu>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
42
src/renderer/views/components/airplay-modal.ejs
Normal file
42
src/renderer/views/components/airplay-modal.ejs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<script type="text/x-template" id="airplay-modal">
|
||||||
|
<div class="spatialproperties-panel castmenu modal-fullscreen airplay-modal" @click.self="close()" @contextmenu.self="close()">
|
||||||
|
<div class="modal-window airplay-modal">
|
||||||
|
<div class="modal-header">
|
||||||
|
<div class="modal-title">{{'Enter password'}}</div>
|
||||||
|
<button class="close-btn" @click="close()"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-content" style="overflow-y: overlay; padding: 3%">
|
||||||
|
<input type="text" v-model="passcode"/>
|
||||||
|
</div>
|
||||||
|
<div class="md-footer">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col" >
|
||||||
|
<button style="width:100%" @click="enterPassword()" class="md-btn md-btn-block md-btn-primary">{{'OK'}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
Vue.component('airplay-modal', {
|
||||||
|
template: '#airplay-modal',
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
passcode: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
close() {
|
||||||
|
this.$root.modals.airplayPW = false
|
||||||
|
},
|
||||||
|
enterPassword() {
|
||||||
|
console.log('Entered passCode: ', this.passcode)
|
||||||
|
ipcRenderer.send("setAirPlayPasscode",this.passcode)
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -29,7 +29,7 @@
|
||||||
template: '#artist-chip',
|
template: '#artist-chip',
|
||||||
async mounted() {
|
async mounted() {
|
||||||
let artistId = this.item.id
|
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
|
artistId = this.item.relationships.catalog.data[0].id
|
||||||
}
|
}
|
||||||
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/artists/${artistId}`).then(response => {
|
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/artists/${artistId}`).then(response => {
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
app.modals.audioSettings = false
|
app.modals.audioSettings = false
|
||||||
},
|
},
|
||||||
openSpatialAudio() {
|
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.spatialProperties = true
|
||||||
app.modals.audioSettings = false
|
app.modals.audioSettings = false
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<div class="md-option-container" style="margin-top: 12px;margin-bottom: 12px;">
|
<div class="md-option-container" style="margin-top: 12px;margin-bottom: 12px;">
|
||||||
<div class="md-option-line">
|
<div class="md-option-line">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{true ? 'Homepods only for now! (NO PASSWORD PLEASE!)' : 'Please add FFmpeg location in Settings -> Advanced'}}
|
{{'EXPERIMENTAL!!! Supports Homepods / Apple TVs / Shairport for now, AirPlay on Samsung/LG/Sony devices will be added later'}}
|
||||||
<!-- {{$root.getLz('action.cast.airplay.underdevelopment')}} -->
|
<!-- {{$root.getLz('action.cast.airplay.underdevelopment')}} -->
|
||||||
<template v-if="true" v-for="(device) in devices.airplay">
|
<template v-if="true" v-for="(device) in devices.airplay">
|
||||||
<div class="md-option-line" style="cursor: pointer" @click="setAirPlayCast(device)">
|
<div class="md-option-line" style="cursor: pointer" @click="setAirPlayCast(device)">
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
seekTo(startTime) {
|
seekTo(startTime) {
|
||||||
if(startTime != 9999999) this.app.seekTo(startTime, false);
|
if (startTime != 9999999) this.app.seekTo(startTime, false);
|
||||||
},
|
},
|
||||||
getActiveLyric() {
|
getActiveLyric() {
|
||||||
const delayfix = 0.1
|
const delayfix = 0.1
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
if (app.currentLyricsLine != i) {
|
if (app.currentLyricsLine != i) {
|
||||||
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 (((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")
|
this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${i}"]`).classList.add("active")
|
||||||
if (this.checkIfScrollIsStatic) {
|
if (this.checkIfScrollIsStatic) {
|
||||||
let lyricElement = this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${i}"]`)
|
let lyricElement = this.$refs.lyricsview.querySelector(`.lyric-line[line-index="${i}"]`)
|
||||||
|
|
|
@ -76,9 +76,9 @@
|
||||||
}, event)
|
}, event)
|
||||||
},
|
},
|
||||||
getVideoPriority() {
|
getVideoPriority() {
|
||||||
if(app.cfg.visual.animated_artwork == "always") {
|
if (app.cfg.visual.animated_artwork == "always") {
|
||||||
return true;
|
return true;
|
||||||
}else if (this.videoPriority && app.cfg.visual.animated_artwork == "limited") {
|
} else if (this.videoPriority && app.cfg.visual.animated_artwork == "limited") {
|
||||||
return true
|
return true
|
||||||
} else if (app.cfg.visual.animated_artwork == "disabled") {
|
} else if (app.cfg.visual.animated_artwork == "disabled") {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<button @click="addToLibrary()" v-if="!addedToLibrary && (showIndex == false ||(showIndex == true && showIndexPlaylist != false))">
|
<button @click="addToLibrary()" v-if="!addedToLibrary && (showIndex == false ||(showIndex == true && showIndexPlaylist != false))">
|
||||||
<div class="svg-icon addIcon" :style="{'--color': 'var(--keyColor)', '--url': 'url(./assets/feather/plus.svg)'}"></div>
|
<div class="svg-icon addIcon" :style="{'--color': 'var(--keyColor)', '--url': 'url(./assets/feather/plus.svg)'}"></div>
|
||||||
</button>
|
</button>
|
||||||
<button v-else-if='!(showArtwork == true && (showIndex == false ||(showIndex == true && showIndexPlaylist != false)))' @click="playTrack()" style="width: 44px;margin-left: -5px;">
|
<button v-else-if='!(showArtwork == true && (showIndex == false ||(showIndex == true && showIndexPlaylist != false)))' @click="playTrack()">
|
||||||
<div class="svg-icon playIcon" :style="{'--color': 'var(--keyColor)', '--url': 'url(./assets/feather/play.svg)'}"></div>
|
<div class="svg-icon playIcon" :style="{'--color': 'var(--keyColor)', '--url': 'url(./assets/feather/play.svg)'}"></div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -65,6 +65,9 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="heart-icon" v-if="isLoved">
|
||||||
|
<div class="svg-icon" :style="{'--url': 'url(./assets/feather/heart-fill.svg)'}"></div>
|
||||||
|
</div>
|
||||||
<div class="explicit-icon" v-if="item.attributes && item.attributes.contentRating == 'explicit'"></div>
|
<div class="explicit-icon" v-if="item.attributes && item.attributes.contentRating == 'explicit'"></div>
|
||||||
<template v-if="showMetaData == true" @dblclick="route()">
|
<template v-if="showMetaData == true" @dblclick="route()">
|
||||||
<div class="metainfo">
|
<div class="metainfo">
|
||||||
|
@ -98,7 +101,8 @@
|
||||||
displayDuration: true,
|
displayDuration: true,
|
||||||
addClasses: {},
|
addClasses: {},
|
||||||
itemId: 0,
|
itemId: 0,
|
||||||
isLibrary: false
|
isLibrary: false,
|
||||||
|
isLoved: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -121,6 +125,9 @@
|
||||||
} else {
|
} else {
|
||||||
this.itemId = this.item.id;
|
this.itemId = this.item.id;
|
||||||
}
|
}
|
||||||
|
if (this.item.attributes.playParams) {
|
||||||
|
this.getHeartStatus();
|
||||||
|
}
|
||||||
let duration = this.item.attributes.durationInMillis ?? 0
|
let duration = this.item.attributes.durationInMillis ?? 0
|
||||||
if (duration == 0 || !this.showDuration) {
|
if (duration == 0 || !this.showDuration) {
|
||||||
this.displayDuration = false
|
this.displayDuration = false
|
||||||
|
@ -145,7 +152,7 @@
|
||||||
},
|
},
|
||||||
getClasses() {
|
getClasses() {
|
||||||
this.addClasses = {}
|
this.addClasses = {}
|
||||||
if(typeof this.item.attributes.playParams == "undefined") {
|
if (typeof this.item.attributes.playParams == "undefined") {
|
||||||
this.addClasses["disabled"] = true
|
this.addClasses["disabled"] = true
|
||||||
}
|
}
|
||||||
if (this.classList) {
|
if (this.classList) {
|
||||||
|
@ -178,7 +185,7 @@
|
||||||
} else {
|
} else {
|
||||||
return this.item.attributes.playParams.kind
|
return this.item.attributes.playParams.kind
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
return this.item.type
|
return this.item.type
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -323,6 +330,7 @@
|
||||||
"hidden": false,
|
"hidden": false,
|
||||||
"disabled": true,
|
"disabled": true,
|
||||||
"action": function () {
|
"action": function () {
|
||||||
|
self.isLoved = true
|
||||||
app.love(self.item)
|
app.love(self.item)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -333,6 +341,7 @@
|
||||||
"name": this.app.getLz('action.unlove'),
|
"name": this.app.getLz('action.unlove'),
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"action": function () {
|
"action": function () {
|
||||||
|
self.isLoved = false
|
||||||
app.unlove(self.item)
|
app.unlove(self.item)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -499,6 +508,19 @@
|
||||||
visibilityChanged: function (isVisible, entry) {
|
visibilityChanged: function (isVisible, entry) {
|
||||||
this.isVisible = isVisible
|
this.isVisible = isVisible
|
||||||
},
|
},
|
||||||
|
async getHeartStatus() {
|
||||||
|
try {
|
||||||
|
await app.getRating(this.item).then(res => {
|
||||||
|
if (res == 1) {
|
||||||
|
this.isLoved = true
|
||||||
|
} else {
|
||||||
|
this.isLoved = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
addToLibrary() {
|
addToLibrary() {
|
||||||
let item = this.item
|
let item = this.item
|
||||||
if (item.attributes.playParams.id) {
|
if (item.attributes.playParams.id) {
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<div class="title text-overflow-elipsis" @click='app.routeView(item)'>
|
<div class="title text-overflow-elipsis" @click='app.routeView(item)'>
|
||||||
{{ item.attributes.name ?? '' }}
|
{{ item.attributes.name ?? '' }}
|
||||||
</div>
|
</div>
|
||||||
<div class="subtitle text-overflow-elipsis item-navigate" v-if="item.attributes.artistName" :style = "{'z-index': ((item.attributes.editorialNotes == null) && item.attributes.artistName) ? '4' : ''}" @click="if(item.attributes.artistName)app.searchAndNavigate(item,'artist')">
|
<div class="subtitle text-overflow-elipsis item-navigate" v-if="item.attributes.artistName" :style = "{'z-index': ((item.attributes.editorialNotes == null) && item.attributes.artistName) ? '4' : ''}" @click="if (item.attributes.artistName)app.searchAndNavigate(item,'artist')">
|
||||||
{{ item.attributes.artistName ?? '' }}
|
{{ item.attributes.artistName ?? '' }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -93,12 +93,12 @@
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
await this.getBadges()
|
await this.getBadges()
|
||||||
if(typeof this.item.attributes.playParams == "object") {
|
if (typeof this.item.attributes.playParams == "object") {
|
||||||
if(this.item.attributes.playParams.kind.includes("radioStation") && (this.item.attributes.playParams.streamingKind == 1 || this.item.attributes.playParams.streamingKind == 2)) {
|
if (this.item.attributes.playParams.kind.includes("radioStation") && (this.item.attributes.playParams.streamingKind == 1 || this.item.attributes.playParams.streamingKind == 2)) {
|
||||||
this.unavailable = true
|
this.unavailable = true
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
if(this.item.type == "music-movies" || this.item.type == "tv-episodes") {
|
if (this.item.type == "music-movies" || this.item.type == "tv-episodes") {
|
||||||
this.unavailable = true
|
this.unavailable = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getSubtitle() {
|
getSubtitle() {
|
||||||
if(this.kind == 'card') {
|
if (this.kind == 'card') {
|
||||||
try {
|
try {
|
||||||
if (typeof this.item.attributes.artistNames != "undefined") {
|
if (typeof this.item.attributes.artistNames != "undefined") {
|
||||||
return this.item.attributes.artistNames
|
return this.item.attributes.artistNames
|
||||||
|
@ -130,7 +130,7 @@
|
||||||
}catch(e) {
|
}catch(e) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
if (typeof this.item.attributes.artistName != "undefined") {
|
if (typeof this.item.attributes.artistName != "undefined") {
|
||||||
return this.item.attributes.artistName
|
return this.item.attributes.artistName
|
||||||
} else {
|
} else {
|
||||||
|
@ -139,7 +139,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getSubtitleNavigation() {
|
getSubtitleNavigation() {
|
||||||
if(this.kind == 'card') {
|
if (this.kind == 'card') {
|
||||||
try {
|
try {
|
||||||
if (typeof this.item.attributes.artistNames != "undefined") {
|
if (typeof this.item.attributes.artistNames != "undefined") {
|
||||||
return app.routeView(this.item)
|
return app.routeView(this.item)
|
||||||
|
@ -153,7 +153,7 @@
|
||||||
}catch(e) {
|
}catch(e) {
|
||||||
return app.routeView(this.item)
|
return app.routeView(this.item)
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
if (typeof this.item.attributes.artistName != "undefined") {
|
if (typeof this.item.attributes.artistName != "undefined") {
|
||||||
return app.searchAndNavigate(this.item,'artist')
|
return app.searchAndNavigate(this.item,'artist')
|
||||||
} else {
|
} else {
|
||||||
|
@ -224,7 +224,7 @@
|
||||||
},
|
},
|
||||||
getArtworkUrl(size = -1, includeUrl = false) {
|
getArtworkUrl(size = -1, includeUrl = false) {
|
||||||
let artwork = this.item.attributes.artwork ? this.item.attributes.artwork.url : ''
|
let artwork = this.item.attributes.artwork ? this.item.attributes.artwork.url : ''
|
||||||
if(size != -1) {
|
if (size != -1) {
|
||||||
artwork = artwork.replace('{w}', size).replace('{h}', size).replace('{f}', "webp").replace('{c}', ((size === 900) ? "sr" : "cc"))
|
artwork = artwork.replace('{w}', size).replace('{h}', size).replace('{f}', "webp").replace('{c}', ((size === 900) ? "sr" : "cc"))
|
||||||
}
|
}
|
||||||
switch (this.kind) {
|
switch (this.kind) {
|
||||||
|
@ -232,9 +232,9 @@
|
||||||
artwork = this.item.attributes.editorialArtwork?.subscriptionHero?.url ?? (this.item.attributes.artwork?.url ?? (this.item.relationships?.contents?.data[0]?.attributes?.editorialArtwork?.subscriptionHero?.url ?? ''))
|
artwork = this.item.attributes.editorialArtwork?.subscriptionHero?.url ?? (this.item.attributes.artwork?.url ?? (this.item.relationships?.contents?.data[0]?.attributes?.editorialArtwork?.subscriptionHero?.url ?? ''))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!includeUrl) {
|
if (!includeUrl) {
|
||||||
return artwork
|
return artwork
|
||||||
}else{
|
} else {
|
||||||
return `url("${artwork}")`
|
return `url("${artwork}")`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -442,7 +442,7 @@
|
||||||
if (self.item.relationships.catalog){
|
if (self.item.relationships.catalog){
|
||||||
app.mkapi(self.item.attributes.playParams.kind, false, self.item.relationships.catalog.data[0].id).then(u => {self.app.copyToClipboard((u.data.data.length && u.data.data.length > 0)? u.data.data[0].attributes.url : u.data.data.attributes.url)})
|
app.mkapi(self.item.attributes.playParams.kind, false, self.item.relationships.catalog.data[0].id).then(u => {self.app.copyToClipboard((u.data.data.length && u.data.data.length > 0)? u.data.data[0].attributes.url : u.data.data.attributes.url)})
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
self.app.copyToClipboard(self.item.attributes.url)}
|
self.app.copyToClipboard(self.item.attributes.url)}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -454,7 +454,7 @@
|
||||||
if (self.item.relationships.catalog){
|
if (self.item.relationships.catalog){
|
||||||
app.mkapi(self.item.attributes.playParams.kind, false, self.item.relationships.catalog.data[0].id).then(u => {self.app.songLinkShare((u.data.data.length && u.data.data.length > 0)? u.data.data[0].attributes.url : u.data.data.attributes.url)})
|
app.mkapi(self.item.attributes.playParams.kind, false, self.item.relationships.catalog.data[0].id).then(u => {self.app.songLinkShare((u.data.data.length && u.data.data.length > 0)? u.data.data[0].attributes.url : u.data.data.attributes.url)})
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
self.app.songLinkShare(self.item.attributes.url)}
|
self.app.songLinkShare(self.item.attributes.url)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -471,10 +471,10 @@
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.isInLibrary().then((_) => {
|
await this.isInLibrary().then((_) => {
|
||||||
if(self.addedToLibrary) {
|
if (self.addedToLibrary) {
|
||||||
menus.normal.items.find(x => x.id == 'addToLibrary').hidden = true
|
menus.normal.items.find(x => x.id == 'addToLibrary').hidden = true
|
||||||
menus.normal.items.find(x => x.id == 'removeFromLibrary').hidden = false
|
menus.normal.items.find(x => x.id == 'removeFromLibrary').hidden = false
|
||||||
}else{
|
} else {
|
||||||
menus.normal.items.find(x => x.id == 'addToLibrary').disabled = false
|
menus.normal.items.find(x => x.id == 'addToLibrary').disabled = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -530,7 +530,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(self.app.cfg.home.followedArtists.includes(this.item.id)) {
|
if (self.app.cfg.home.followedArtists.includes(this.item.id)) {
|
||||||
followAction = "unfollow"
|
followAction = "unfollow"
|
||||||
}
|
}
|
||||||
app.showMenuPanel({
|
app.showMenuPanel({
|
||||||
|
|
|
@ -13,12 +13,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="queue-body" v-if="page == 'queue'">
|
<div class="queue-body" v-if="page == 'queue'">
|
||||||
<draggable v-model="queueItems" @start="drag=true" @end="drag=false;move()">
|
<draggable v-model="queueItems" @start="drag=true" @end="drag=false;move()">
|
||||||
<template v-for="(queueItem, position) in queueItems">
|
<template v-for="(queueItem, position) in displayQueueItems">
|
||||||
<div v-if="position <= queuePosition" style="display: none;">{{ position }}</div>
|
|
||||||
<div class="cd-queue-item"
|
<div class="cd-queue-item"
|
||||||
:class="{selected: selectedItems.includes(position)}"
|
:class="{selected: selectedItems.includes(position)}"
|
||||||
@click="select($event, position)"
|
@click="select($event, position)"
|
||||||
@dblclick="playQueueItem(position)" v-else :key="position"
|
@dblclick="playQueueItem(position)" :key="position"
|
||||||
@contextmenu="selected = position;queueContext($event, queueItem.item, position)">
|
@contextmenu="selected = position;queueContext($event, queueItem.item, position)">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-auto flex-center">
|
<div class="col-auto flex-center">
|
||||||
|
@ -61,6 +60,13 @@
|
||||||
app: this.$root
|
app: this.$root
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
displayQueueItems() {
|
||||||
|
const displayLimit = 50;
|
||||||
|
const lastDisplayPosition = Math.min(displayLimit + this.queuePosition, this.queueItems.length);
|
||||||
|
return this.queueItems.slice(this.queuePosition, lastDisplayPosition);
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.updateQueue()
|
this.updateQueue()
|
||||||
},
|
},
|
||||||
|
@ -70,8 +76,8 @@
|
||||||
this.history = history.data.data
|
this.history = history.data.data
|
||||||
},
|
},
|
||||||
select(e, position) {
|
select(e, position) {
|
||||||
if(e.ctrlKey || e.shiftKey) {
|
if (e.ctrlKey || e.shiftKey) {
|
||||||
if(this.selectedItems.indexOf(position) == -1) {
|
if (this.selectedItems.indexOf(position) == -1) {
|
||||||
this.selectedItems.push(position)
|
this.selectedItems.push(position)
|
||||||
} else {
|
} else {
|
||||||
this.selectedItems.splice(this.selectedItems.indexOf(position), 1)
|
this.selectedItems.splice(this.selectedItems.indexOf(position), 1)
|
||||||
|
@ -83,7 +89,7 @@
|
||||||
queueContext(event, item, position) {
|
queueContext(event, item, position) {
|
||||||
let self = this
|
let self = this
|
||||||
let useMenu = "single"
|
let useMenu = "single"
|
||||||
if(this.selectedItems.length > 1) {
|
if (this.selectedItems.length > 1) {
|
||||||
useMenu = "multiple"
|
useMenu = "multiple"
|
||||||
}
|
}
|
||||||
let menus = {
|
let menus = {
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
playlistSelect(playlist) {
|
playlistSelect(playlist) {
|
||||||
if(playlist.type != "library-playlist-folders") {
|
if (playlist.type != "library-playlist-folders") {
|
||||||
this.addToPlaylist(playlist.id)
|
this.addToPlaylist(playlist.id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -294,7 +294,7 @@
|
||||||
this.room_materials = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.room_materials))
|
this.room_materials = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.room_materials))
|
||||||
this.audio_position = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.audio_position))
|
this.audio_position = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.audio_position))
|
||||||
this.listener_position = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.listener_position))
|
this.listener_position = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.listener_position))
|
||||||
if(typeof this.app.mk.nowPlayingItem != "undefined") {
|
if (typeof this.app.mk.nowPlayingItem != "undefined") {
|
||||||
this.setRoom()
|
this.setRoom()
|
||||||
}
|
}
|
||||||
this.ready = true
|
this.ready = true
|
||||||
|
@ -320,7 +320,7 @@
|
||||||
},
|
},
|
||||||
objectContainerStyle() {
|
objectContainerStyle() {
|
||||||
let scale = 1
|
let scale = 1
|
||||||
if(this.room_dimensions.width * this.visualMultiplier > 300) {
|
if (this.room_dimensions.width * this.visualMultiplier > 300) {
|
||||||
scale = 300 / (this.room_dimensions.width * this.visualMultiplier)
|
scale = 300 / (this.room_dimensions.width * this.visualMultiplier)
|
||||||
}
|
}
|
||||||
let style = {
|
let style = {
|
||||||
|
@ -346,7 +346,7 @@
|
||||||
window.CiderAudio.audioNodes.spatialNode.setRoomProperties(this.room_dimensions, this.room_materials);
|
window.CiderAudio.audioNodes.spatialNode.setRoomProperties(this.room_dimensions, this.room_materials);
|
||||||
CiderAudio.audioNodes.spatialInput.setPosition(...this.audio_position)
|
CiderAudio.audioNodes.spatialInput.setPosition(...this.audio_position)
|
||||||
CiderAudio.audioNodes.spatialNode.setListenerPosition(...this.listener_position)
|
CiderAudio.audioNodes.spatialNode.setListenerPosition(...this.listener_position)
|
||||||
if(!this.app.cfg.audio.normalization) {
|
if (!this.app.cfg.audio.normalization) {
|
||||||
window.CiderAudio.audioNodes.gainNode.gain.value = app.cfg.audio.spatial_properties.gain
|
window.CiderAudio.audioNodes.gainNode.gain.value = app.cfg.audio.spatial_properties.gain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.app.cfg.home.followedArtists.includes(self.data.id)) {
|
if (this.app.cfg.home.followedArtists.includes(self.data.id)) {
|
||||||
followAction = "unfollow"
|
followAction = "unfollow"
|
||||||
}
|
}
|
||||||
app.showMenuPanel({
|
app.showMenuPanel({
|
||||||
|
|
|
@ -132,9 +132,9 @@
|
||||||
self.themes = []
|
self.themes = []
|
||||||
notyf.success(app.getLz('settings.notyf.visual.plugin.install.success'));
|
notyf.success(app.getLz('settings.notyf.visual.plugin.install.success'));
|
||||||
bootbox.confirm(app.getLz("settings.prompt.visual.plugin.github.success"), (ok)=>{
|
bootbox.confirm(app.getLz("settings.prompt.visual.plugin.github.success"), (ok)=>{
|
||||||
if(ok) {
|
if (ok) {
|
||||||
ipcRenderer.invoke("relaunchApp")
|
ipcRenderer.invoke("relaunchApp")
|
||||||
}else{
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -154,9 +154,9 @@
|
||||||
if (arg.success) {
|
if (arg.success) {
|
||||||
self.themes = ipcRenderer.sendSync("get-themes")
|
self.themes = ipcRenderer.sendSync("get-themes")
|
||||||
bootbox.confirm(app.getLz("settings.prompt.visual.plugin.github.success"), (ok)=>{
|
bootbox.confirm(app.getLz("settings.prompt.visual.plugin.github.success"), (ok)=>{
|
||||||
if(ok) {
|
if (ok) {
|
||||||
ipcRenderer.invoke("relaunchApp")
|
ipcRenderer.invoke("relaunchApp")
|
||||||
}else{
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -187,7 +187,7 @@
|
||||||
},
|
},
|
||||||
searchPodcasts() {
|
searchPodcasts() {
|
||||||
let self = this
|
let self = this
|
||||||
if(this.search.term == "") {
|
if (this.search.term == "") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
app.mk.api.v3.podcasts("/v1/catalog/us/search", {term: this.search.term, types: ["podcasts"], limit: 25}).then(response => {
|
app.mk.api.v3.podcasts("/v1/catalog/us/search", {term: this.search.term, types: ["podcasts"], limit: 25}).then(response => {
|
||||||
|
@ -227,7 +227,7 @@
|
||||||
async getNextEpisodes(next, podcastId) {
|
async getNextEpisodes(next, podcastId) {
|
||||||
|
|
||||||
let podcastShow = await app.mk.api.v3.podcasts(next)
|
let podcastShow = await app.mk.api.v3.podcasts(next)
|
||||||
if(podcastId != this.podcastSelected.id) {
|
if (podcastId != this.podcastSelected.id) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
podcastShow.data.data.forEach(ep => {
|
podcastShow.data.data.forEach(ep => {
|
||||||
|
|
|
@ -1542,7 +1542,7 @@
|
||||||
this.tabIndex = parseInt(window.location.hash.split("/")[1])
|
this.tabIndex = parseInt(window.location.hash.split("/")[1])
|
||||||
console.debug("tabIndex", this.tabIndex)
|
console.debug("tabIndex", this.tabIndex)
|
||||||
this.canChangeHash = true
|
this.canChangeHash = true
|
||||||
}else{
|
} else {
|
||||||
this.canChangeHash = true
|
this.canChangeHash = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
return "https://beta.music.apple.com/assets/product/MissingArtworkMusic.svg"
|
return "https://beta.music.apple.com/assets/product/MissingArtworkMusic.svg"
|
||||||
}
|
}
|
||||||
height = parseInt(height * window.devicePixelRatio)
|
height = parseInt(height * window.devicePixelRatio)
|
||||||
if(width) {
|
if (width) {
|
||||||
width = parseInt(width * window.devicePixelRatio)
|
width = parseInt(width * window.devicePixelRatio)
|
||||||
}
|
}
|
||||||
let newurl = `${url.replace('{w}', width ?? height).replace('{h}', height).replace('{f}', "webp").replace('{c}', ((width === 900) ? "sr" : "cc"))}`;
|
let newurl = `${url.replace('{w}', width ?? height).replace('{h}', height).replace('{f}', "webp").replace('{c}', ((width === 900) ? "sr" : "cc"))}`;
|
||||||
|
|
|
@ -86,14 +86,14 @@
|
||||||
|
|
||||||
if (luma > 140) {
|
if (luma > 140) {
|
||||||
return "#aaaaaa"
|
return "#aaaaaa"
|
||||||
}else{
|
} else {
|
||||||
return color
|
return color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
getSubtitle() {
|
getSubtitle() {
|
||||||
if(this.kind == 'card') {
|
if (this.kind == 'card') {
|
||||||
try {
|
try {
|
||||||
if (typeof this.item.attributes.artistNames != "undefined") {
|
if (typeof this.item.attributes.artistNames != "undefined") {
|
||||||
return this.item.attributes.artistNames
|
return this.item.attributes.artistNames
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
}catch(e) {
|
}catch(e) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
if (typeof this.item.attributes.artistName != "undefined") {
|
if (typeof this.item.attributes.artistName != "undefined") {
|
||||||
return this.item.attributes.artistName
|
return this.item.attributes.artistName
|
||||||
} else {
|
} else {
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getSubtitleNavigation() {
|
getSubtitleNavigation() {
|
||||||
if(this.kind == 'card') {
|
if (this.kind == 'card') {
|
||||||
try {
|
try {
|
||||||
if (typeof this.item.attributes.artistNames != "undefined") {
|
if (typeof this.item.attributes.artistNames != "undefined") {
|
||||||
return app.routeView(this.item)
|
return app.routeView(this.item)
|
||||||
|
@ -130,7 +130,7 @@
|
||||||
}catch(e) {
|
}catch(e) {
|
||||||
return app.routeView(this.item)
|
return app.routeView(this.item)
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
if (typeof this.item.attributes.artistName != "undefined") {
|
if (typeof this.item.attributes.artistName != "undefined") {
|
||||||
return app.searchAndNavigate(this.item,'artist')
|
return app.searchAndNavigate(this.item,'artist')
|
||||||
} else {
|
} else {
|
||||||
|
@ -200,7 +200,7 @@
|
||||||
},
|
},
|
||||||
getArtworkUrl(size = -1, includeUrl = false) {
|
getArtworkUrl(size = -1, includeUrl = false) {
|
||||||
let artwork = this.item.attributes.artwork ? this.item.attributes.artwork.url : ''
|
let artwork = this.item.attributes.artwork ? this.item.attributes.artwork.url : ''
|
||||||
if(size != -1) {
|
if (size != -1) {
|
||||||
artwork = artwork.replace('{w}', size).replace('{h}', size).replace('{f}', "webp").replace('{c}', ((size === 900) ? "sr" : "cc"))
|
artwork = artwork.replace('{w}', size).replace('{h}', size).replace('{f}', "webp").replace('{c}', ((size === 900) ? "sr" : "cc"))
|
||||||
}
|
}
|
||||||
switch (this.kind) {
|
switch (this.kind) {
|
||||||
|
@ -208,9 +208,9 @@
|
||||||
artwork = this.item.attributes.editorialArtwork.subscriptionHero.url
|
artwork = this.item.attributes.editorialArtwork.subscriptionHero.url
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!includeUrl) {
|
if (!includeUrl) {
|
||||||
return artwork
|
return artwork
|
||||||
}else{
|
} else {
|
||||||
return `url("${artwork}")`
|
return `url("${artwork}")`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -423,10 +423,10 @@
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.isInLibrary().then((_) => {
|
await this.isInLibrary().then((_) => {
|
||||||
if(self.addedToLibrary) {
|
if (self.addedToLibrary) {
|
||||||
menus.normal.items.find(x => x.id == 'addToLibrary').hidden = true
|
menus.normal.items.find(x => x.id == 'addToLibrary').hidden = true
|
||||||
menus.normal.items.find(x => x.id == 'removeFromLibrary').hidden = false
|
menus.normal.items.find(x => x.id == 'removeFromLibrary').hidden = false
|
||||||
}else{
|
} else {
|
||||||
menus.normal.items.find(x => x.id == 'addToLibrary').disabled = false
|
menus.normal.items.find(x => x.id == 'addToLibrary').disabled = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"electronVersion": "18.0.4",
|
"electronVersion": "18.2.0",
|
||||||
"electronDownload": {
|
"electronDownload": {
|
||||||
"version": "18.0.4+wvcus",
|
"version": "18.2.0+wvcus",
|
||||||
"mirror": "https://github.com/castlabs/electron-releases/releases/download/v"
|
"mirror": "https://github.com/castlabs/electron-releases/releases/download/v"
|
||||||
},
|
},
|
||||||
"appId": "cider",
|
"appId": "cider",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue