Merge branch 'ciderapp:develop' into develop

This commit is contained in:
Bill Zhang 2022-02-15 00:43:55 +08:00 committed by GitHub
commit f43b467068
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 10024 additions and 3163 deletions

View file

@ -29,7 +29,7 @@ jobs:
runs-on: macos-11
permissions:
actions: read
contents: read
contents: write
security-events: write
strategy:
@ -100,6 +100,25 @@ jobs:
- name: Add license to dmg
run: |
npx dmg-license resources/license.json dist/*.dmg
- name: Import
uses: apple-actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.CSC_LINK }}
p12-password: ${{ secrets.CSC_KEY_PASSWORD }}
- name: Create PKG manually
env:
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
APPLEID: ${{ secrets.APPLEID }}
APPLEIDPASS: ${{ secrets.APPLEIDPASS }}
run: |
pkgbuild --component dist/mac-universal/Cider.app --install-location /Applications dist/Cider.pkg --sign ${{ secrets.PSC_NAME }}
xcrun altool --notarize-app --primary-bundle-id com.ciderapp.cider -f dist/Cider.pkg --username ${{ secrets.APPLEID }} --password ${{ secrets.APPLEIDPASS }}
sleep 5m
xcrun stapler staple dist/Cider.pkg || true
mv dist/*.dmg dist/Cider.dmg
- name: Upload a Build Artifact
uses: actions/upload-artifact@v2.2.3
@ -107,5 +126,20 @@ jobs:
# Artifact name
name: macOS
# A file, directory or wildcard pattern that describes what to upload
path: dist/*.dmg
path: |
dist/*.dmg
dist/*.pkg
# The desired behavior if no files are found using the provided path.
- name: Release
uses: softprops/action-gh-release@v1
with:
files: |
dist/Cider.dmg
dist/Cider.pkg
body: signed Develop MacOS Builds
name: macOS builds
tag_name: macos-beta
prerelease : true
generate_release_notes: true
append_body : false
fail_on_unmatched_files: false

View file

@ -46,7 +46,7 @@
"get-port": "^5.1.1",
"jsonc": "^2.0.0",
"lastfmapi": "^0.1.1",
"mdns-js": "git+https://github.com/bitfocus/node-mdns-js.git",
"mdns-js": "git+https://github.com/ciderapp/node-mdns-js.git",
"mpris-service": "^2.1.2",
"music-metadata": "^7.11.4",
"node-gyp": "^8.4.1",

View file

@ -4,7 +4,7 @@
"i18n.languageName": "Deutsch", // name of language in native language
"i18n.languageNameEnglish": "German", // name of language in English
"i18n.category": "main", // main = real language, fun = fun community languages
"i18n.authors": "@motz0815", // Authors, if you contribute to this file feel free to add your name seperated with a space
"i18n.authors": "@motz0815 @n0chteil", // Authors, if you contribute to this file feel free to add your name seperated with a space
// App info
"app.name": "Cider",
@ -46,7 +46,12 @@
"term.podcasts": "Podcasts",
"term.playlists": "Playlists",
"term.playlist": "Playlist",
"term.play": "Play",
"term.newPlaylist": "Neue Playlist",
"term.newPlaylistFolder": "Neuer Playlist-Ordner",
"term.createNewPlaylist": "Neue Playlist erstellen",
"term.createNewPlaylistFolder": "Neuen Playlist-Ordner erstellen",
"term.deletePlaylist": "Bist du sicher, dass du diese Playlist löschen willst?",
"term.play": "Wiedergabe",
"term.pause": "Pause",
"term.previous": "Zurück",
"term.next": "Weiter",
@ -56,6 +61,7 @@
"term.mute": "Stummschalten",
"term.unmute": "Stummschaltung aufheben",
"term.share": "Teilen",
"term.share.success": "In die Zwischenablage kopiert",
"term.settings": "Einstellungen",
"term.seeAll": "Alle Sehen",
"term.sortBy": "Sortieren nach",
@ -65,6 +71,7 @@
"term.sortBy.genre": "Genre",
"term.sortBy.releaseDate": "Veröffentlichungsdatum",
"term.sortBy.duration": "Länge",
"term.sortBy.dateAdded": "Hinzugefügt am",
"term.sortOrder": "A-Z",
"term.sortOrder.ascending": "Aufsteigend",
"term.sortOrder.descending": "Absteigend",
@ -82,12 +89,12 @@
"term.connecting": "Verbindet",
"term.disconnect": "Trennen",
"term.authed": "Autorisiert",
"term.confirm": "Bestätigen ?",
"term.confirm": "Bestätigen?",
"term.more": "Mehr",
"term.less": "Weniger",
"term.showMore": "Zeige mehr",
"term.showLess": "Zeige weniger",
"term.topSongs" : "Top Songs",
"term.showMore": "Mehr anzeigen",
"term.showLess": "Weniger anzeigen",
"term.topSongs": "Top Songs",
"term.latestReleases": "Letzte Veröffentlichungen",
"term.time.added": "Hinzugefügt",
"term.time.released": "Veröffentlicht",
@ -100,24 +107,48 @@
"term.time.second": "Sekunde",
"term.fullscreenView": "Vollbildansicht",
"term.defaultView": "Normale Ansicht",
"term.audioSettings": "Audio-Einstellungen",
"term.spacializedAudioSetting": "Räumliches Audio",
"term.clearAll": "Alle löschen",
"term.recentStations": "Letzte Stationen",
"term.recentStations": "Letzte Sender",
"term.language": "Sprache",
"term.funLanguages": "Spaß",
"term.noLyrics": "Lädt... / Liedtext nicht gefunden./ Instrumental.",
"term.noLyrics": "Lädt... / Lyrik nicht gefunden./ Instrumental.",
"term.copyright": "Copyright",
"term.rightsReserved": "All Rights Reserved.",
"term.rightsReserved": "Alle Rechte vorbehalten.",
"term.sponsor": "Unterstütze dieses Projekt",
"term.ciderTeam": "Cider Team",
"term.developer": "Entwickler",
"term.socialTeam": "Social Team",
"term.socials": "Soziale Medien",
"term.contributors": "Mithelfer",
"term.equalizer": "Equalizer",
"term.reset": "Zurücksetzen",
"term.tracks": "Lieder", // Assume x amount of tracks. e.g. 50 tracks
"term.videos": "Videos",
"term.menu": "Menü",
"term.check": "Nach Updates suchen",
"term.aboutArtist": "Über {{artistName}}", // e.g. 'About Doja Cat'
"term.topResult": "Bestes Ergebnis", // Search Results
"term.sharedPlaylists": "Geteilte Playlists", // Search Results
"term.people": "Personen", // Search Results
"term.newpreset.name": "Neuer EQ-Preset Name", // Equalizer Preset
"term.addedpreset": "Preset erstellt",
"term.deletepreset.warn": "Bist du sicher, dass du dieses Preset löschen willst?",
"term.deletedpreset": "Preset gelöscht",
"term.defaultPresets": "Standard-Presets",
"term.userPresets": "Nutzer-Presets",
"term.requestError": "Es gab ein Problem bei der Anfrage.",
"term.song.link.generate": "song.link URL wird gesucht...",
"term.musicVideos": "Musikvideos", // Search page friendlyTypes
"term.stations": "Radiosender",
"term.curators": "Kuratoren",
"term.appleCurators": "Apple-Kuratoren",
"term.radioShows": "Radiosendungen",
"term.recordLabels": "Plattenfirma",
"term.videoExtras": "Video-Extras",
"term.top": "Beste",
"term.version": "Version",
// Home
"home.title": "Home",
@ -131,7 +162,7 @@
// Errors
"error.appleMusicSubRequired": "Apple Music benötigt ein Abonnement.",
"error.connectionError": "Es ist ein Fehler aufgetreten, während sich mit Apple Music verbunden wurde.",
"error.connectionError": "Es gab ein Problem beim Verbinden mit Apple Music.",
"error.noResults": "Keine Ergebnisse.",
"error.noResults.description": "Versuche einen anderen Suchbegriff.",
@ -157,6 +188,7 @@
"action.removeFromQueue": "Aus Warteschlange entfernen",
"action.removeFromQueue.success": "Aus Warteschlange entfernt",
"action.removeFromQueue.error": "Fehler beim Entfernen aus der Warteschlange",
"action.createPlaylist": "Neue Playlist erstellen",
"action.addToPlaylist": "Zur Playlist hinzufügen",
"action.removeFromPlaylist": "Aus Playlist entfernen",
"action.addToFavorites": "Zu Favoriten hinzufügen",
@ -184,7 +216,14 @@
"action.removeTracks": "Entferne ${self.selectedItems.length} Lieder aus der Warteschlange",
"action.import": "Importieren",
"action.export": "Exportieren",
"action.showAlbum": "Zeige ganzes Album",
"action.showAlbum": "Ganzes Album anzeigen",
"action.tray.minimize": "Zu Tray minimieren",
"action.tray.quit": "Beenden",
"action.tray.show": "{appName} anzeigen",
"action.update": "Update",
"action.copy": "Kopieren",
"action.newpreset": "Neues Preset", // Equalizer Preset
"action.deletepreset": "Preset löschen",
// Settings - General
"settings.header.general": "Allgemein",
@ -197,21 +236,37 @@
"settings.option.general.language.unsorted": "Unsortiert",
// Update Cider
"settings.option.general.updateCider": "Cider updaten", // Button. Refer to term.check for the check button
"settings.option.general.updateCider.branch": "Update-Branch", // Dropdown
"settings.option.general.updateCider.branch.description": "Der Branch, von welchem Cider geupdatet werden soll",
"settings.option.general.updateCider.branch.main": "Stabil",
"settings.option.general.updateCider.branch.develop": "Entwicklung",
// Settings - Audio
"settings.header.audio": "Audio",
"settings.header.audio.description": "Passe die Audio-Einstellungen für Cider an.",
"settings.option.audio.quality": "Audioqualität", // Dropdown
"settings.header.audio.quality.hireslossless": "Hi-Res Lossless",
"settings.header.audio.quality.hireslossless.description": "bis zu 24-bit/192 kHz",
"settings.header.audio.quality.lossless": "Lossless",
"settings.header.audio.quality.lossless.description": "bis zu 24-bit/48 kHz",
"settings.header.audio.quality.high": "Hoch",
"settings.header.audio.quality.low": "Niedrig",
"settings.header.audio.quality.auto": "Auto",
"settings.header.audio.quality.standard": "Standard",
"settings.option.audio.seamlessTransition": "Nahtloser Audioübergang", // Toggle
"settings.option.audio.enableAdvancedFunctionality": "Akiviere erweiterte Funktionalität", // Toggle
"settings.option.audio.enableAdvancedFunctionality.description": "Das Aktivieren der erweiterten Funktionalität ermöglicht spezielle Features wie Audio-Normalisierung, Equalizer und Visualizer, jedoch könnte dies auf einigen Systemen zu Aussetzern in der Musik führen.",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider Adrenaline Processor™", // Toggle
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "Psychoakustische Verbesserungen die die Musik lebensechter erscheinen lassen | Designed by Maikiwi.",
"settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility": "CAP ist nicht mit räumlichem Audio kompatibel. Bitte deaktiviere räumliches Audio zuerst.",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength": "CAP-Stärke", // Toggle
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.description": "Ändert die Stärke der Nachbearbeitung. (Aggressiv könnte zu ungewünschten Änderungen führen)",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.standard": "Standard",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.aggressive": "Aggressiv",
"settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Audio-Normalisierung", // Toggle
"settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Normalisiert die Lautstärke aller Lieder, um die Hörerfahrung einheitlicher zu machen.",
"settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Räumliches Audio", // Toggle
"settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Macht die Musik räumlicher (3D-Effekt) (Beachte: Dies ist kein Dolby Atmos)",
"settings.warn.audio.enableAdvancedFunctionality.audioSpatialization.compatibility": "Räumliches Audio ist nicht mit CAP kompatibel. Bitte deaktiviere CAP zuerst.",
// Settings - Visual
"settings.header.visual": "Visuell",
@ -235,8 +290,15 @@
"settings.option.visual.hardwareAcceleration.description": "Erfordert Neustart der Anwendung",
"settings.header.visual.hardwareAcceleration.default": "Normal",
"settings.header.visual.hardwareAcceleration.webGPU": "WebGPU",
"settings.header.visual.theme": "Theme",
"settings.option.visual.theme.github.download": "Von GitHub URL installieren",
"settings.prompt.visual.theme.github.URL": "Gib die URL des Themes ein, welches du installieren möchtest",
"settings.notyf.visual.theme.install.success": "Theme erfolgreich installiert",
"settings.notyf.visual.theme.install.error": "Theme-Installation fehlgeschlagen",
// Settings - Visual - Theme name
"settings.option.visual.theme.default": "Cider",
"settings.option.visual.theme.dark": "Dunkel",
// Refer to term.disabled for the disabled option
"settings.option.visual.showPersonalInfo": "Persönliche Daten anzeigen", // Toggle
@ -255,8 +317,8 @@
"settings.option.connectivity.discordRPC": "Discord Rich Presence", // Dropdown
"settings.option.connectivity.playbackNotifications": "Wiedergabe-Benachrichtigungen", // Toggle
// Refer to term.disabled for the disabled option
"settings.header.connectivity.discordRPC.cider": "Zeige als 'Cider'",
"settings.header.connectivity.discordRPC.appleMusic": "Zeige als 'Apple Music'",
"settings.header.connectivity.discordRPC.cider": "'Cider' anzeigen",
"settings.header.connectivity.discordRPC.appleMusic": "'Apple Music' anzeigen",
"settings.option.connectivity.discordRPC.clearOnPause": "Leere Discord Rich Presence wenn pausiert", // Toggle
"settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling", // Option to Connect
"settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble Delay (%)",
@ -269,34 +331,34 @@
"settings.header.experimental": "Experimentell",
"settings.header.experimental.description": "Passe die experimentellen Einstellungen für Cider an.",
"settings.option.experimental.compactUI": "Kompaktes UI", // Toggle
"settings.option.experimental.closeButtonBehaviour": "Verhalten der Schließtaste",
"settings.option.experimental.closeButtonBehaviour.quit": "Cider Schließen",
"settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "In Taskleiste minimieren",
"settings.option.experimental.closeButtonBehaviour.minimizeTray": "In den Tray minimieren",
"settings.option.experimental.close_button_hide": "Schließtaste soll die App verbergen",
"settings.option.experimental.copy_log": "Kopiere Logs in die Zwischenablage",
"settings.option.experimental.inline_playlists": "Inline Playlists und Alben",
// Refer to term.disabled & term.enabled
// Spatialization Menu
"spatial.spatialProperties" : "Räumliche Einstellungen",
"spatial.width" : "Breite",
"spatial.height" : "Höhe",
"spatial.depth" : "Tiefe",
"spatial.gain" : "Gain",
"spatial.roomMaterials" : "Raummaterialien",
"spatial.roomDimensions" : "Raumabmessungen",
"spatial.roomPositions" : "Raumpositionen",
"spatial.setDimensions" : "Setze Abmessungen",
"spatial.setPositions" : "Setze Positionen",
"spatial.up" : "Oben",
"spatial.front" : "Vorne",
"spatial.left" : "Links",
"spatial.right" : "Rechts",
"spatial.back" : "Hinten",
"spatial.down" : "Unten",
"spatial.listener" : "Hörer*in",
"spatial.audioSource" : "Audioquelle",
"spatial.notTurnedOn": "Die Audio-Spatialisierung ist deaktiviert. Um sie zu verwenden, musst du diese zuerst aktivieren.",
"spatial.spatialProperties": "Räumliche Einstellungen",
"spatial.width": "Breite",
"spatial.height": "Höhe",
"spatial.depth": "Tiefe",
"spatial.gain": "Gain",
"spatial.roomMaterials": "Raummaterialien",
"spatial.roomDimensions": "Raumabmessungen",
"spatial.roomPositions": "Raumpositionen",
"spatial.setDimensions": "Setze Abmessungen",
"spatial.setPositions": "Setze Positionen",
"spatial.up": "Oben",
"spatial.front": "Vorne",
"spatial.left": "Links",
"spatial.right": "Rechts",
"spatial.back": "Hinten",
"spatial.down": "Unten",
"spatial.listener": "Hörer*in",
"spatial.audioSource": "Audioquelle",
// Settings - Unfinished
"settings.header.unfinished": "Unfertig",
"settings.header.unfinished": "Unvollendet",
// Web Remote
"remote.web.title": "Cider Remote",

View file

@ -124,7 +124,12 @@
"term.contributors": "more pisseneers",
"term.equalizer": "advanced piss configuration",
"term.reset": "repiss",
"term.tracks": "pisses", // Assume x amount of tracks. e.g. 50 tracks
// Example for multiple plural forms : look up the key for your language in https://github.com/prantlf/fast-plural-rules/blob/master/docs/languages.md#supported-languages
"term.track": {
"one" : "piss",
"other" : "pisses"
},
// "term.tracks": "pisses", // Assume x amount of tracks. e.g. 50 tracks
"term.videos": "piss videos",
"term.menu": "piss menu",
"term.check": "piss!",
@ -136,6 +141,8 @@
"term.addedpreset": "obtained prepiss",
"term.deletepreset.warn": "are you sure you want to obliterate this prepiss?",
"term.deletedpreset": "obliterated prepiss",
"term.defaultPresets": "default prepisses",
"term.userPresets": "your prepisses",
"term.requestError": "the request got pissed on",
"term.song.link.generate": "pissing on piss.link…",
"term.musicVideos": "piss videos", // Search page friendlyTypes
@ -146,6 +153,7 @@
"term.recordLabels": "piss labels",
"term.videoExtras": "extra piss videos",
"term.top": "topiss",
"term.version": "pission",
// Home
"home.title": "piss central",
@ -290,6 +298,10 @@
"settings.header.visual.hardwareAcceleration.default": "default piss",
"settings.header.visual.hardwareAcceleration.webGPU": "WebPISS",
"settings.header.visual.theme": "colored piss",
"settings.option.visual.theme.github.download": "piss from PissHub URL",
"settings.prompt.visual.theme.github.URL": "piss on the URL for your colorful piss",
"settings.notyf.visual.theme.install.success": "colored piss obtained",
"settings.notyf.visual.theme.install.error": "colored piss got pissed on…",
// Settings - Visual - Theme name
"settings.option.visual.theme.default": "same old piss",

View file

@ -299,6 +299,8 @@
"settings.header.visual.hardwareAcceleration.webGPU": "WebGPU",
"settings.header.visual.theme": "Theme",
"settings.option.visual.theme.github.download": "Install from GitHub URL",
"settings.option.visual.theme.github.explore": "Explore GitHub Themes",
"settings.option.visual.theme.github.install.confirm": "Are you sure you want to install {{ repo }}?",
"settings.prompt.visual.theme.github.URL": "Enter the URL of the theme you want to install",
"settings.notyf.visual.theme.install.success": "Theme installed successfully",
"settings.notyf.visual.theme.install.error": "Theme installation failed",

View file

@ -64,6 +64,7 @@
"term.sortBy.genre": "ジャンル",
"term.sortBy.releaseDate": "配信開始日",
"term.sortBy.duration": "時間",
"term.sortBy.dateAdded": "追加日",
"term.sortOrder": "並べ替え",
"term.sortOrder.ascending": "昇順",
"term.sortOrder.descending": "降順",
@ -114,12 +115,17 @@
"term.contributors": "貢献者",
"term.equalizer": "イコライザー",
"term.reset": "リセット",
"term.tracks": "曲", // Assume x amount of tracks. e.g. 50 tracks
"term.track": {
"one" : "曲",
"other" : "曲"
},
"term.tracks": "曲",
"term.videos": "ビデオ",
"term.menu": "メニュー",
"term.check": "確認",
"term.aboutArtist": "{{artistName}}について", // e.g. 'About Doja Cat'
"term.version": "バージョン",
// Home
"home.title": "ホーム",
"home.recentlyPlayed": "最近の再生",
@ -199,6 +205,9 @@
"settings.header.general.description": "Ciderの一般設定",
// Language optgroups
"settings.option.general.language.main": "メイン",
"settings.option.general.language.fun": "荒らし",
"settings.option.general.language.unsorted": "未分類",
// Update Cider
"settings.option.general.updateCider": "Cider 更新", // Button
@ -250,8 +259,11 @@
"settings.option.visual.hardwareAcceleration.description": "アプリを再起動する必要があります",
"settings.header.visual.hardwareAcceleration.default": "既定",
"settings.header.visual.hardwareAcceleration.webGPU": "WebGPU",
"settings.header.visual.theme": "テーマ",
// Settings - Visual - Theme name
"settings.option.visual.theme.default": "Cider",
"settings.option.visual.theme.dark": "ダーク",
// Refer to term.disabled for the disabled option
"settings.option.visual.showPersonalInfo": "プロフィールを表示", // Toggle
@ -284,7 +296,9 @@
"settings.header.experimental.description": "開発中の実験的な機能は不完全で不安定である可能性があります",
"settings.option.experimental.compactUI": "コンパクトインターフェース", // Toggle
"settings.option.experimental.close_button_hide": "「閉じる」ボタンでアプリを隠します", // Dropdown
"settings.option.experimental.copy_log": "ログをコピーする",
"settings.option.experimental.inline_playlists": "プレイリストをインラインで表示", // Toggle
// Refer to term.disabled & term.enabled
// Spatialization Menu
"spatial.spatialProperties": "空間化のプロパティ",

386
src/i18n/ru_RU.jsonc Normal file
View file

@ -0,0 +1,386 @@
{ // Base File
// i18n Info
"i18n.languageName": "Русский (RU)", // name of language in native language
"i18n.languageNameEnglish": "Russian (RU)", // name of language in English
"i18n.category": "main", // main = real language, fun = fun community languages
"i18n.authors": "@h0ckerman", // Authors, if you contribute to this file feel free to add your name seperated with a space
// App info
"app.name": "Cider",
"date.format": "${d} ${m}, ${y}",
// Dialogs
"dialog.cancel": "Отмена",
"dialog.ok": "OK",
// Notification
"notification.updatingLibrarySongs": "Обновление медиатеки песен...",
"notification.updatingLibraryAlbums": "Обновление медиатеки альбомов...",
"notification.updatingLibraryArtists": "Обновление медиатеки артистов...",
// Terms
"term.appleInc": "Apple Inc.",
"term.appleMusic": "Apple Music",
"term.applePodcasts": "Подкасты Apple",
"term.itunes": "iTunes",
"term.github": "GitHub",
"term.discord": "Discord",
"term.learnMore": "Узнать больше",
"term.accountSettings": "Настройки аккаунта",
"term.logout": "Выйти",
"term.login": "Войти",
"term.about": "О Cider",
"term.privateSession": "Частная сессия",
"term.queue": "Очередь",
"term.history": "История",
"term.search": "Поиск",
"term.library": "Медиатека", // FROM APPLE WEB
"term.listenNow": "Слушайте сейчас", // FROM APPLE MUSIC WEB
"term.browse": "Обзор", // WEB
"term.radio": "Радио",
"term.recentlyAdded": "Недавно добавлено", // FROM APPLE MUSIC WEB
"term.songs": "Песни",
"term.albums": "Альбомы",
"term.artists": "Артисты",
"term.podcasts": "Подкасты",
"term.playlists": "Плейлисты",
"term.playlist": "Плейлист",
"term.newPlaylist": "Новый Плейлист",
"term.newPlaylistFolder": "Новая Папка Плейлиста",
"term.createNewPlaylist": "Создать новый плейлист", // FROM ITUNES
"term.createNewPlaylistFolder": "Создать новую папку",
"term.deletePlaylist": "Вы уверены, что хотите удалить плейлист?",
"term.play": "Воспроизвести", // FROM ITUNES
"term.pause": "Пауза",
"term.previous": "Предыдущий",
"term.next": "Следующий",
"term.shuffle": "Перемешать",
"term.repeat": "Повторять",
"term.volume": "Громкость",
"term.mute": "Заглушить",
"term.unmute": "Включить звук",
"term.share": "Поделиться",
"term.share.success": "Скопировано в буфер обмена",
"term.settings": "Настройки",
"term.seeAll": "Смотреть все",
"term.sortBy": "Сортировать по",
"term.sortBy.album": "Альбом",
"term.sortBy.artist": "Артист",
"term.sortBy.name": "Имя",
"term.sortBy.genre": "Жанр",
"term.sortBy.releaseDate": "Дата выхода",
"term.sortBy.duration": "Длительность",
"term.sortBy.dateAdded": "Дата добавления",
"term.sortOrder": "А-Я",
"term.sortOrder.ascending": "По возрастанию",
"term.sortOrder.descending": "По убыванию",
"term.viewAs": "Показывать",
"term.viewAs.coverArt": "Обложки",
"term.viewAs.list": "Список",
"term.size": "Размер",
"term.size.normal": "Обычный",
"term.size.compact": "Компактный",
"term.enable": "Включить",
"term.disable": "Выключить",
"term.enabled": "Включено",
"term.disabled": "Выключено",
"term.connect": "Подключить",
"term.connecting": "Подключение",
"term.disconnect": "Отключить",
"term.authed": "Авторизовано",
"term.confirm": "Подтвердить?",
"term.more": "Больше",
"term.less": "Меньше",
"term.showMore": "Показать больше",
"term.showLess": "Показать меньше",
"term.topSongs": "Лучшие песни",
"term.latestReleases": "Последние релизы",
"term.time.added": "Добавлено",
"term.time.released": "Релиз: ", // From itunes
"term.time.updated": "Обновлено",
"term.time.hour": {
"one": "час",
"few": "часа",
"other": "часов"
},
// "term.time.hour": "час",
"term.time.minute": {
"one": "минута",
"few": "минуты",
"other": "минут"
},
// "term.time.minute": "минута",
"term.time.second": {
"one": "секунд",
"few": "секунды",
"other": "секунд"
},
// "term.time.second": "секунда",
"term.fullscreenView": "Полноэкранное отображение",
"term.defaultView": "Стандартное отображение",
"term.audioSettings": "Настройки звука",
"term.clearAll": "Очистить",
"term.recentStations": "Вы недавно слушали", // FROM ITUNES
"term.language": "Язык",
"term.funLanguages": "Забавные",
"term.noLyrics": "Загрузка... / Текст песни не найден./ Инструментал.",
"term.copyright": "Авторское право",
"term.rightsReserved": "Все права защищены.",
"term.sponsor": "Поддержать проект",
"term.ciderTeam": "Команда Cider",
"term.developer": "Разработчик",
"term.socialTeam": "Социальная команда",
"term.socials": "Социальные сети",
"term.contributors": "Внесли вклад",
"term.equalizer": "Эквалайзер",
"term.reset": "Сбросить",
"term.tracks": {
"one" : "песня",
"few": "песни",
"other" : "песен"
}, // Assume x amount of tracks. e.g. 50 tracks
"term.videos": "Видео",
"term.menu": "Меню",
"term.check": "Проверить",
"term.aboutArtist": "О {{artistName}}", // e.g. 'About Doja Cat'
"term.topResult": "Топ результатов", // Search Results, FROM ITUNES
"term.sharedPlaylists": "Общие плейлисты", // Search Results NOT SURE
"term.people": "Люди", // Search Results NOT SURE
"term.newpreset.name": "Название нового пресета эквалайзера", // Equalizer Preset
"term.addedpreset": "Пресет добавлен",
"term.deletepreset.warn": "Вы уверены, что хотите удалить пресет?",
"term.deletedpreset": "Пресет удален",
"term.defaultPresets": "Предустановки по умолчанию",
"term.userPresets": "Предустановки пользователя",
"term.requestError": "Возникла проблема с запросом.",
"term.song.link.generate": "Получение ссылки с song.link...",
"term.musicVideos": "Музыкальные видео", // Search page friendlyTypes FROM ITUNES
"term.stations": "Станции", // FROM ITUNES
"term.curators": "Кураторы", // FROM ITUNES
"term.appleCurators": "Кураторы Apple",
"term.radioShows": "Радиошоу", // FROM ITUNES
"term.recordLabels": "Лейблы звукозаписи",
"term.videoExtras": "Ещё", // FROM ITUNES
"term.top": "Top", // NOT SURE WHAT IT IS, NOT TRANSLATED
"term.version": "Версия",
// Home
"home.title": "Главная",
"home.recentlyPlayed": "Недавно прослушанные",
"home.recentlyAdded": "Недавно добавленные",
"home.artistsFeed": "Лента исполнителей",
"home.artistsFeed.noArtist": "Подпишитесь на некоторых артистов, и их последние релизы будут здесь",
"home.madeForYou": "Специально для вас", // FROM APPLE MUSIC WEB
"home.friendsListeningTo": "Что слушают друзья",
"home.followedArtists": "Отслеживаемые артисты",
// Errors
"error.appleMusicSubRequired": "Для прослушивания Apple Music требуется подписка.",
"error.connectionError": "Возникла проблема с подключением к Apple Music.",
"error.noResults": "Нет результатов.",
"error.noResults.description": "Попробуйте ещё раз.",
// Podcasts
"podcast.followOnCider": "Отслеживать в Cider",
"podcast.followedOnCider": "Отслеживаемые в Cider",
"podcast.subscribeOnItunes": "Подписаться в iTunes",
"podcast.subscribedOnItunes": "Подписан в iTunes",
"podcast.itunesStore": "iTunes Store",
"podcast.episodes": "Выпуски радиошоу", // FROM APPLE MUSIC WEB
"podcast.playEpisode": "Воспроизвести",
"podcast.website": "Веб-сайт", // FROM ITUNES
// Actions
"action.addToLibrary": "Добавить в медиатеку",
"action.addToLibrary.success": "Добавлено в медиатеку",
"action.addToLibrary.error": "Ошибка Добавления в медиатику",
"action.removeFromLibrary": "Убрать из медиатеки",
"action.removeFromLibrary.success": "Удалено из медиатеки",
"action.addToQueue": "Воспроизвести далее", // FROM WEB
"action.addToQueue.success": "Добавлено в очередь",
"action.addToQueue.error": "Ошибка добавления в очередь",
"action.removeFromQueue": "Убрать из очереди",
"action.removeFromQueue.success": "Удалено из очереди",
"action.removeFromQueue.error": "Ошибка удаления из очереди",
"action.createPlaylist": "Создать новый плейлист",
"action.addToPlaylist": "Добавить в плейлист", // FROM ITUNES
"action.removeFromPlaylist": "Удалить из плейлиста",
"action.addToFavorites": "Добавить в избранное",
"action.follow": "Отслеживать",
"action.follow.success": "В отслеживаемых",
"action.follow.error": "Ошибка отслеживания",
"action.unfollow": "Отписаться",
"action.unfollow.success": "Отписан",
"action.unfollow.error": "Ошибка отписки",
"action.playNext": "Воспроизвести далее",
"action.playLater": "Воспроизвести позже",
"action.startRadio": "Создать станцию",
"action.goToArtist": "Перейти к артисту",
"action.goToAlbum": "Перейти к альбому",
"action.moveToTop": "Переместить наверх",
"action.share": "Поделиться",
"action.rename": "Переименовать",
"action.love": "Нравится", // FROM WEB
"action.unlove": "Больше не нравится", // FROM WEB
"action.dislike": "Меньше подобных рекомендаций", // FROM WEB
"action.undoDislike": "Вернуть подобные рекомендации", // FROM WEB
"action.showWebRemoteQR": "Веб-интерфейс",
"action.playTracksNext": "Воспроизвести ${app.selectedMediaItems.length} песен следующими",
"action.playTracksLater": "Воспроизвести ${app.selectedMediaItems.length} песен позже",
"action.removeTracks": "Удалить ${self.selectedItems.length} песен из очереди",
"action.import": "Импорт",
"action.export": "Экспорт",
"action.showAlbum": "Показать весь альбом", // FROM WEB
"action.tray.minimize": "Свернуть в трей",
"action.tray.quit": "Выйти",
"action.tray.show": "Показать",
"action.update": "Обновить",
"action.copy": "Скопировать",
"action.newpreset": "Новый пресет...", // Equalizer Preset
"action.deletepreset": "Удалить пресет",
// Settings - General
"settings.header.general": "Общие",
"settings.header.general.description": "Настройка общих параметров Cider.",
"settings.option.general.language": "Язык",
// Language optgroups
"settings.option.general.language.main": "Языки",
"settings.option.general.language.fun": "Забавные языки",
"settings.option.general.language.unsorted": "Неотсортированные",
// Update Cider
"settings.option.general.updateCider": "Обновить Cider", // Button. Refer to term.check for the check button
"settings.option.general.updateCider.branch": "Ветка обновления Cider", // Dropdown
"settings.option.general.updateCider.branch.description": "Выберите ветку обновления Cider",
"settings.option.general.updateCider.branch.main": "Стабильная",
"settings.option.general.updateCider.branch.develop": "Нестабильная",
// Settings - Audio
"settings.header.audio": "Звук",
"settings.header.audio.description": "Настройка звука Cider.",
"settings.option.audio.quality": "Качество звука", // Dropdown FROM IOS
"settings.header.audio.quality.hireslossless": "Высокое разрешение, без потерь", // FROM IOS
"settings.header.audio.quality.hireslossless.description": "ALAC до 24 бит/192 кГц", // FROM IOS
"settings.header.audio.quality.lossless": "Без потерь", // FROM IOS
"settings.header.audio.quality.lossless.description": "ALAC до 24 бит/48 кГц", // FROM IOS
"settings.header.audio.quality.high": "Высокое качество", // FROM IOS
"settings.header.audio.quality.high.description": "AAC 256 кб/с", // FROM IOS
"settings.header.audio.quality.standard": "Высокая эффективность", // FROM IOS
"settings.header.audio.quality.standard.description": "НЕ-ААС для экономии трафика(64 кб/с)", // FROM IOS
"settings.option.audio.seamlessTransition": "Плавный переход между песнями", // Toggle
"settings.option.audio.enableAdvancedFunctionality": "Включить расширенный функционал", // Toggle
"settings.option.audio.enableAdvancedFunctionality.description": "Включение функции AudioContext позволит использовать расширенные функции звука, такие как нормализация звука, эквалайзеры и визуализаторы, однако в некоторых системах это может вызвать заикание звуковых дорожек.",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider Adrenaline Processor™", // Toggle
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "Психоакустические улучшения, благодаря которым все звучит богаче и живее | Разработано Maikiwi.",
"settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility": "CAP не совместим с пространственным звучанием. Пожалуйста, отключите пространственное звучание, чтобы продолжить.",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength": "Режим CAP", // Toggle
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.description": "Изменяет режим обработки звука. (Режим агрессии может привести к нежелаемым результатам)",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.standard": "Стандартный",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.aggressive": "Агрессивный",
"settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Нормализация звука", // Toggle
"settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Нормализует пиковую громкость для отдельных треков, чтобы создать более однородное впечатление от прослушивания.",
"settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Пространственное звучание", // Toggle
"settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Пространственное аудио; сделать звук более трехмерным (примечание: это не Dolby Atmos)",
"settings.warn.audio.enableAdvancedFunctionality.audioSpatialization.compatibility": "Пространственная обработка несовместима с CAP. Пожалуйста, отключите CAP, чтобы продолжить.",
// Settings - Visual
"settings.header.visual": "Внешний вид",
"settings.header.visual.description": "Настройка внешнего вида Cider.",
"settings.option.visual.windowBackgroundStyle": "Стиль фона Cider", // Toggle
"settings.header.visual.windowBackgroundStyle.none": "Отсутствует",
"settings.header.visual.windowBackgroundStyle.artwork": "Обложка",
"settings.header.visual.windowBackgroundStyle.image": "Изображение",
"settings.option.visual.animatedArtwork": "Анимированная обложка", // Dropdown
"settings.header.visual.animatedArtwork.always": "Всегда",
"settings.header.visual.animatedArtwork.limited": "Ограничено специальными страницами",
"settings.header.visual.animatedArtwork.disable": "Выключено везде",
"settings.option.visual.animatedArtworkQuality": "Качество анимированной обложки", // Dropdown
"settings.header.visual.animatedArtworkQuality.low": "Низкое",
"settings.header.visual.animatedArtworkQuality.medium": "Среднее",
"settings.header.visual.animatedArtworkQuality.high": "Высокое",
"settings.header.visual.animatedArtworkQuality.veryHigh": "Очень высокое",
"settings.header.visual.animatedArtworkQuality.extreme": "Наивысшее",
"settings.option.visual.animatedWindowBackground": "Анимированный фон окна Cider", // Toggle
"settings.option.visual.hardwareAcceleration": "Аппаратное ускорение", // Dropdown
"settings.option.visual.hardwareAcceleration.description": "Требует перезагрузки приложения",
"settings.header.visual.hardwareAcceleration.default": "По умолчанию",
"settings.header.visual.hardwareAcceleration.webGPU": "WebGPU",
"settings.header.visual.theme": "Тема",
"settings.option.visual.theme.github.download": "Установить с GitHub",
"settings.prompt.visual.theme.github.URL": "Введите URL темы, которую хотите установить",
"settings.notyf.visual.theme.install.success": "Тема успешно установлена",
"settings.notyf.visual.theme.install.error": "Не удалось установить тему",
// Settings - Visual - Theme name
"settings.option.visual.theme.default": "Cider",
"settings.option.visual.theme.dark": "Тёмная",
// Refer to term.disabled for the disabled option
"settings.option.visual.showPersonalInfo": "Показать личную информацию", // Toggle
// Settings - Lyrics
"settings.header.lyrics": "Текст песни",
"settings.header.lyrics.description": "Настройка текста песен.",
"settings.option.lyrics.enableMusixmatch": "Получать текст песен из Musixmatch", // Toggle
"settings.option.lyrics.enableMusixmatchKaraoke": "Включить режим караоке (только с Musixmatch)", // Toggle
"settings.option.lyrics.musixmatchPreferredLanguage": "Предпочтительный язык перевода Musixmatch", // Dropdown
"settings.option.lyrics.enableYoutubeLyrics": "Включить Youtube Lyrics для музыкальных клипов", // Toggle
// Settings - Connectivity
"settings.header.connectivity": "Прочее",
"settings.header.connectivity.description": "Настройка прочих параметров Cider.",
"settings.option.connectivity.discordRPC": "Discord Rich Presence", // Dropdown
"settings.option.connectivity.playbackNotifications": "Уведомления о воспроизведении", // Toggle
// Refer to term.disabled for the disabled option
"settings.header.connectivity.discordRPC.cider": "Отображать как 'Cider'",
"settings.header.connectivity.discordRPC.appleMusic": "Отображать как 'Apple Music'",
"settings.option.connectivity.discordRPC.clearOnPause": "Отключать Discord Rich Presence на паузе", // Toggle
"settings.option.connectivity.lastfmScrobble": "Last.fm cкробблинг", // Option to Connect
"settings.option.connectivity.lastfmScrobble.delay": "Частота скробблинга Last.fm (%)",
"settings.option.connectivity.lastfmScrobble.nowPlaying": "Включить Last.fm Сейчас играет",
"settings.option.connectivity.lastfmScrobble.removeFeatured": "Удалять фит-исполнителей из названия песни (Last.fm)",
"settings.option.connectivity.lastfmScrobble.filterLoop": "Фильтровать зацикленный трек (Last.fm)",
// Refer to term.connect for the connect button
// Settings - Experimental
"settings.header.experimental": "Экспериментальные",
"settings.header.experimental.description": "Настройка экспериментальных функций Cider.",
"settings.option.experimental.compactUI": "Компактный интерфейс", // Toggle
"settings.option.experimental.close_button_hide": "Кнопка «Закрыть» скрывает приложение",
"settings.option.experimental.copy_log": "Скопировать логи в буфер обмена",
"settings.option.experimental.inline_playlists": "Встроенные плейлисты и альбомы", // NOT SURE
// Refer to term.disabled & term.enabled
// Spatialization Menu
"spatial.notTurnedOn": "Пространственное аудио отключено. Чтобы использовать, сначала включите его.",
"spatial.spatialProperties": "Настройка пространственного аудио",
"spatial.width": "Ширина",
"spatial.height": "Высота",
"spatial.depth": "Глубина",
"spatial.gain": "Усиление",
"spatial.roomMaterials": "Материалы комнаты",
"spatial.roomDimensions": "Размеры комнаты",
"spatial.roomPositions": "Позиции комнаты",
"spatial.setDimensions": "Установить размеры",
"spatial.setPositions": "Установить позиции",
"spatial.up": "Сверху",
"spatial.front": "Спереди",
"spatial.left": "Слева",
"spatial.right": "Справа",
"spatial.back": "Сзади",
"spatial.down": "Снизу",
"spatial.listener": "Слушатель",
"spatial.audioSource": "Источник звука",
// Settings - Unfinished
"settings.header.unfinished": "Не завершено",
// Web Remote
"remote.web.title": "Веб-интерфейс",
"remote.web.description": "Отсканируйте QR-код, чтобы подключить телефон к Cider Remote",
// About
"about.thanks": "Большое спасибо команде Cider Collective и всем нашим вкладчикам."
}

View file

@ -123,11 +123,17 @@
"term.contributors": "貢獻者",
"term.equalizer": "等化器",
"term.reset": "重設",
"term.tracks": "首歌曲", // Assume x amount of tracks. e.g. 50 tracks
"term.track": {
"one" : "首歌曲",
"other" : "首歌曲"
},
"term.tracks": "首歌曲",
"term.videos": "影片",
"term.menu": "選單",
"term.check": "檢查",
"term.aboutArtist": "關於{{artistName}}", // e.g. 'About Doja Cat'
"term.requestError": "請求發生錯誤。",
"term.song.link.generate": "正在取得 song.link 的分享網址...",
"term.version": "版本",
// Home
@ -269,6 +275,10 @@
"settings.header.visual.hardwareAcceleration.default": "預設",
"settings.header.visual.hardwareAcceleration.webGPU": "WebGPU",
"settings.header.visual.theme": "主題",
"settings.option.visual.theme.github.download" : "從 GitHub 網址安裝" ,
"settings.prompt.visual.theme.github.URL" : "輸入你要安裝的主題網址" ,
"settings.notyf.visual.theme.install.success" : "主題成功安裝" ,
"settings.notyf.visual.theme.install.error" : "主題安裝失敗" ,
// Settings - Visual - Theme name
"settings.option.visual.theme.default": "Cider",

View file

@ -46,6 +46,7 @@ export class BrowserWindow {
"pages/about",
"pages/library-videos",
"pages/remote-pair",
"pages/themes-github",
"components/mediaitem-artwork",
"components/artwork-material",
"components/menu-panel",
@ -217,11 +218,11 @@ export class BrowserWindow {
res.send("Stopped")
break;
case "next":
BrowserWindow.win.webContents.executeJavaScript("MusicKit.getInstance().skipToNextItem()")
BrowserWindow.win.webContents.executeJavaScript("if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null) {MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex);}")
res.send("Next")
break;
case "previous":
BrowserWindow.win.webContents.executeJavaScript("MusicKit.getInstance().skipToPreviousItem()")
BrowserWindow.win.webContents.executeJavaScript("if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null) {MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex);}")
res.send("Previous")
break;
default: {
@ -430,7 +431,7 @@ export class BrowserWindow {
description: themeJson.description || themeDescription,
path: themePath,
file: theme,
test: join(themePath, "theme.json")
github_repo: themeJson.github_repo || ""
});
} else {
themeObjects.push({
@ -438,7 +439,7 @@ export class BrowserWindow {
description: themeDescription,
path: themePath,
file: theme,
test: join(themePath, "theme.json")
github_repo: ""
});
}
}

View file

@ -182,11 +182,12 @@ export class wsapi {
response.message = "Unmuted";
break;
case "next":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().skipToNextItem()`);
this._win.webContents.executeJavaScript(`if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null) {
MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex);}`);
response.message = "Next";
break;
case "previous":
this._win.webContents.executeJavaScript(`MusicKit.getInstance().skipToPreviousItem()`);
this._win.webContents.executeJavaScript(`if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null) {MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex)}`);
response.message = "Previous";
break;
case "musickit-api":

View file

@ -9,6 +9,7 @@ export default class DiscordRichPresence {
*/
private static _store: any;
private _app : any;
private _attributes : any;
private static _connection: boolean = false;
/**
@ -148,7 +149,7 @@ export default class DiscordRichPresence {
state: `${attributes.artistName ? `by ${attributes.artistName}` : ''}`,
startTimestamp: attributes.startTime,
endTimestamp: attributes.endTime,
largeImageKey: attributes.artwork.url.replace('{w}', '1024').replace('{h}', '1024'),
largeImageKey: attributes?.artwork?.url?.replace('{w}', '1024').replace('{h}', '1024'),
largeImageText: attributes.albumName,
instance: false, // Whether the activity is in a game session
buttons: [
@ -217,9 +218,8 @@ export default class DiscordRichPresence {
})
.then(res => res.json())
.then(function(json){
self._activity['largeImageKey'] = json.url
console.log(json.url)
self._client.setActivity(self._activity);
self._attributes["artwork"]["url"] = json.url
self.updateActivity(self._attributes)
})
})
@ -237,6 +237,7 @@ export default class DiscordRichPresence {
* @param attributes Music Attributes (attributes.status = current state)
*/
onPlaybackStateDidChange(attributes: object): void {
this._attributes = attributes
this.updateActivity(attributes)
}
@ -245,6 +246,7 @@ export default class DiscordRichPresence {
* @param attributes Music Attributes
*/
onNowPlayingItemDidChange(attributes: object): void {
this._attributes = attributes
this.updateActivity(attributes)
}
}

View file

@ -81,7 +81,7 @@ export default class LastFMPlugin {
private scrobbleSong(attributes: any) {
if(this._timer) clearTimeout(this._timer);
var self = this;
this._timer = setTimeout(() => {
this._timer = setTimeout(async () => {
const currentAttributes = attributes;
if (!self._lastfm || self._lastfm.cachedAttributes === attributes) {
@ -92,15 +92,17 @@ export default class LastFMPlugin {
if (self._lastfm.cachedAttributes.playParams.id === attributes.playParams.id) return;
}
const artist = await this.getPrimaryArtist(attributes)
if (currentAttributes.status && currentAttributes === attributes) {
if (fs.existsSync(this.sessionPath)) {
// Scrobble playing song.
if (attributes.status === true) {
self._lastfm.track.scrobble({
'artist': this.filterArtistName(attributes.artistName),
'artist': artist,
'track': attributes.name,
'album': attributes.albumName,
'albumArtist': self.filterArtistName(attributes.artistName),
'albumArtist': artist,
'timestamp': new Date().getTime() / 1000
}, function (err: any, scrobbled: any) {
if (err) {
@ -115,29 +117,11 @@ export default class LastFMPlugin {
self.authenticate();
}
} else {
return console.log('[LastFM] Did not add ', attributes.name, '—', self.filterArtistName(attributes.artistName), 'because now playing a other song.');
return console.log('[LastFM] Did not add ', attributes.name, '—', artist, 'because now playing a other song.');
}},Math.round(attributes.durationInMillis * (self._store.lastfm.scrobble_after / 100)));
}
private filterArtistName(artist: any) {
if (!this._store.lastfm.enabledRemoveFeaturingArtists) return artist;
artist = artist.split(' ');
if (artist.includes('&')) {
artist.length = artist.indexOf('&');
}
if (artist.includes('and')) {
artist.length = artist.indexOf('and');
}
artist = artist.join(' ');
if (artist.includes(',')) {
artist = artist.split(',')
artist = artist[0]
}
return artist.charAt(0).toUpperCase() + artist.slice(1);
}
private updateNowPlayingSong(attributes: any) {
private async updateNowPlayingSong(attributes: any) {
if (!this._lastfm || this._lastfm.cachedNowPlayingAttributes === attributes || !this._store.lastfm.NowPlaying) {
return
}
@ -147,13 +131,15 @@ export default class LastFMPlugin {
}
if (fs.existsSync(this.sessionPath)) {
const artist = await this.getPrimaryArtist(attributes)
// update Now Playing
if (attributes.status === true) {
this._lastfm.track.updateNowPlaying({
'artist': this.filterArtistName(attributes.artistName),
'artist': artist,
'track': attributes.name,
'album': attributes.albumName,
'albumArtist': this.filterArtistName(attributes.artistName)
'albumArtist': artist
}, function (err: any, nowPlaying: any) {
if (err) {
return console.error('[LastFM] An error occurred while updating nowPlayingSong', err);
@ -169,6 +155,40 @@ export default class LastFMPlugin {
}
}
private async getPrimaryArtist (attributes: any) {
const songId = attributes.playParams.catalogId || attributes.playParams.id
if (!this._store.lastfm.enabledRemoveFeaturingArtists || !songId) return attributes.artistName;
const res = await this._win.webContents.executeJavaScript(`
(async () => {
const subMk = await MusicKit.getInstance().api.v3.music("/v1/catalog/" + MusicKit.getInstance().storefrontId + "/songs/${songId}", {
include: {
songs: ["artists"]
}
})
if (!subMk) console.error('[LastFM] Request failed: /v1/catalog/us/songs/${songId}')
return subMk.data
})()
`).catch(console.error)
if (!res) return attributes.artistName
const data = res.data
if (!data.length) {
console.error(`[LastFM] Unable to locate song with id of ${songId}`)
return attributes.artistName;
}
const artists = res.data[0].relationships.artists.data
if (!artists.length) {
console.error(`[LastFM] Unable to find artists related to the song with id of ${songId}`)
return attributes.artistName;
}
const primaryArtist = artists[0]
return primaryArtist.attributes.name
}
/**
* Base Plugin Details (Eventually implemented into a GUI in settings)
*/
@ -253,4 +273,4 @@ export default class LastFMPlugin {
this.scrobbleSong(attributes)
}
}
}

View file

@ -23,7 +23,7 @@ const MusicKitInterop = {
/** wsapi */
MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, async () => {
await MusicKitInterop.modifyNamesOnLocale();
// await MusicKitInterop.modifyNamesOnLocale();
if (MusicKitInterop.filterTrack(MusicKitInterop.getAttributes(), false, true) || !app.cfg.lastfm.filterLoop) {
global.ipcRenderer.send('nowPlayingItemDidChange', MusicKitInterop.getAttributes());
}
@ -127,11 +127,14 @@ const MusicKitInterop = {
},
next: () => {
MusicKit.getInstance().skipToNextItem().then(r => console.log(`[MusicKitInterop.next] Skipping to Next ${r}`));
if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null)
MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex);
// MusicKit.getInstance().skipToNextItem().then(r => console.log(`[MusicKitInterop.next] Skipping to Next ${r}`));
},
previous: () => {
MusicKit.getInstance().skipToPreviousItem().then(r => console.log(`[MusicKitInterop.previous] Skipping to Previous ${r}`));
if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null)
MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex);
}
}

View file

@ -6,7 +6,6 @@ var CiderAudio = {
spatialNode : null,
spatialInput: null,
audioBands : null,
preampNode : null,
vibrantbassNode: null,
llpw: null,
llpwEnabled: null
@ -30,7 +29,6 @@ var CiderAudio = {
CiderAudio.audioNodes.gainNode.disconnect(); } catch(e){}
try{ CiderAudio.audioNodes.spatialNode.disconnect();} catch(e){}
try{
// CiderAudio.audioNodes.preampNode.disconnect();
for (var i of CiderAudio.audioNodes.llpw){
i.disconnect();
}
@ -47,8 +45,9 @@ var CiderAudio = {
spatialNode : null,
spatialInput: null,
audioBands : null,
preampNode : null,
vibrantbassNode: null,
llpw: null,
llpwEnabled: null
}
} catch (e) {}
CiderAudio.source.connect(CiderAudio.context.destination);} catch(e){}
@ -76,10 +75,8 @@ var CiderAudio = {
CiderAudio.audioNodes.gainNode.gain.setTargetAtTime(1, CiderAudio.context.currentTime+ 1, 0.5);
},
spatialOn: function (){
try{
CiderAudio.audioNodes.gainNode.disconnect(CiderAudio.context.destination);} catch(e){}
CiderAudio.audioNodes.spatialNode = new ResonanceAudio(CiderAudio.context);
CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.context.destination);
//CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.context.destination);
let roomDimensions = {
width: 32,
height: 12,
@ -96,13 +93,10 @@ var CiderAudio = {
};
CiderAudio.audioNodes.spatialNode.setRoomProperties(roomDimensions, roomMaterials);
CiderAudio.audioNodes.spatialInput = CiderAudio.audioNodes.spatialNode.createSource();
CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.spatialInput.input);
CiderAudio.hierarchical_loading();
},
spatialOff: function (){
try{
CiderAudio.audioNodes.spatialNode.output.disconnect(CiderAudio.context.destination);
CiderAudio.audioNodes.gainNode.disconnect(CiderAudio.audioNodes.spatialInput.input);} catch(e){}
CiderAudio.audioNodes.gainNode.connect(CiderAudio.context.destination);
CiderAudio.hierarchical_loading();
},
sendAudio: function (){
var options = {
@ -119,17 +113,119 @@ var CiderAudio = {
);
}
},
equalizer: function (){
let BANDS = app.cfg.audio.equalizer.frequencies;
let GAIN = app.cfg.audio.equalizer.gain;
let Q = app.cfg.audio.equalizer.Q;
let VIBRANTBASSBANDS = app.cfg.audio.vibrantBass.frequencies;
let VIBRANTBASSGAIN = app.cfg.audio.vibrantBass.gain;
let VIBRANTBASSQ = app.cfg.audio.vibrantBass.Q;
llpw_h2_2: function (status, hierarchy){
if (status === true) {
let LLPW_Q = [5, 1, 3.536, 1.25, 8.409, 1.25, 14.14, 7.071, 5, 0.625, 16.82, 20, 20, 20, 28.28, 28.28, 28.28, 20, 33.64, 33.64, 10, 28.28, 7.071, 3.856];
let LLPW_GAIN = [0.38, -1.81, -0.23, -0.51, 0.4, 0.84, 0.36, -0.34, 0.27, -1.2, -0.42, -0.67, 0.81, 1.31, -0.71, 0.68, -1.04, 0.79, -0.73, -1.33, 1.17, 0.57, 0.35, 6.33];
let LLPW_FREQUENCIES = [16.452, 24.636, 37.134, 74.483, 159.54, 308.18, 670.21, 915.81, 1200.7, 2766.4, 2930.6, 4050.6, 4409.1, 5395.2, 5901.6, 6455.5, 7164.1, 7724.1, 8449, 10573, 12368, 14198, 17910, 18916];
CiderAudio.audioNodes.audioBands = []; CiderAudio.audioNodes.vibrantbassNode = []; CiderAudio.audioNodes.llpw = [];
CiderAudio.audioNodes.llpw = []
for (i = 0; i < LLPW_FREQUENCIES.length; i++) {
CiderAudio.audioNodes.llpw[i] = CiderAudio.context.createBiquadFilter();
CiderAudio.audioNodes.llpw[i].type = 'peaking'; // 'peaking';
CiderAudio.audioNodes.llpw[i].frequency.value = LLPW_FREQUENCIES[i];
CiderAudio.audioNodes.llpw[i].Q.value = LLPW_Q[i];
CiderAudio.audioNodes.llpw[i].gain.value = LLPW_GAIN[i] * app.cfg.audio.ciderPPE_value;
}
for (i = 1; i < LLPW_FREQUENCIES.length; i ++) {
CiderAudio.audioNodes.llpw[i-1].connect(CiderAudio.audioNodes.llpw[i]);
}
if (hierarchy === 2) {
try{
CiderAudio.audioNodes.llpw[LLPW_FREQUENCIES.length-1].connect(CiderAudio.audioNodes.vibrantbassNode[0]);} catch(e){}}
else if (hierarchy === 1) {
try{
CiderAudio.audioNodes.llpw[LLPW_FREQUENCIES.length-1].connect(CiderAudio.audioNodes.audioBands[0]);} catch(e){}}
}
},
vibrantbass_h2_1: function (status){
if (status === true) {
let VIBRANTBASSBANDS = app.cfg.audio.vibrantBass.frequencies;
let VIBRANTBASSGAIN = app.cfg.audio.vibrantBass.gain;
let VIBRANTBASSQ = app.cfg.audio.vibrantBass.Q;
CiderAudio.audioNodes.vibrantbassNode = []
for (i = 0; i < VIBRANTBASSBANDS.length; i++) {
CiderAudio.audioNodes.vibrantbassNode[i] = CiderAudio.context.createBiquadFilter();
CiderAudio.audioNodes.vibrantbassNode[i].type = 'peaking'; // 'peaking';
CiderAudio.audioNodes.vibrantbassNode[i].frequency.value = VIBRANTBASSBANDS[i];
CiderAudio.audioNodes.vibrantbassNode[i].Q.value = VIBRANTBASSQ[i];
CiderAudio.audioNodes.vibrantbassNode[i].gain.value = VIBRANTBASSGAIN[i] * app.cfg.audio.vibrantBass.multiplier;
}
for (i = 1; i < VIBRANTBASSBANDS.length; i ++) {
CiderAudio.audioNodes.vibrantbassNode[i-1].connect(CiderAudio.audioNodes.vibrantbassNode[i]);
}
CiderAudio.audioNodes.vibrantbassNode[VIBRANTBASSBANDS.length-1].connect(CiderAudio.audioNodes.audioBands[0]);
}
},
hierarchical_unloading: function (){
try {CiderAudio.audioNodes.spatialNode.output.disconnect();} catch(e){}
try {CiderAudio.audioNodes.gainNode.disconnect();} catch(e){}
try {for (var i of CiderAudio.audioNodes.llpw){i.disconnect();} CiderAudio.audioNodes.llpw = []} catch(e){}
try {for (var i of CiderAudio.audioNodes.vibrantbassNode){i.disconnect();} CiderAudio.audioNodes.vibrantbassNode = []} catch(e){}
console.log("[Cider][Audio] Finished hierarchical unloading");
},
hierarchical_loading: function (){
CiderAudio.hierarchical_unloading();
if (app.cfg.audio.vibrantBass.multiplier !== 0) { // If vibrant bass is enabled
if (app.cfg.advanced.ciderPPE) { // If CAP & vibrant bass is enabled
CiderAudio.vibrantbass_h2_1(true)
if (app.cfg.audio.spatial) {
app.cfg.advanced.ciderPPE = false;
notyf.error(app.getLz('settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility'));
CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.spatialInput.input);
CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.audioNodes.vibrantbassNode[0]);
}
else {CiderAudio.llpw_h2_2(true, 2); CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.llpw[0]);}
}
else { // If only vibrant bass is enabled
CiderAudio.vibrantbass_h2_1(true)
//CiderAudio.llpw_h2_2(false, 0)
if (app.cfg.audio.spatial) {
CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.spatialInput.input);
CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.audioNodes.vibrantbassNode[0]);}
else {CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.vibrantbassNode[0]);}
}
}
else { // If vibrant bass is disabled
if (app.cfg.advanced.ciderPPE) { // If CAP is enabled & vibrant bass is disabled
//CiderAudio.vibrantbass_h2_1(false)
if (app.cfg.audio.spatial) {
app.cfg.advanced.ciderPPE = false;
notyf.error(app.getLz('settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility'));
CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.spatialInput.input);
CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.audioNodes.audioBands[0]);
}
else {CiderAudio.llpw_h2_2(true, 1); CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.llpw[0]);}
}
else { // If CAP & vibrant bass is disabled
//CiderAudio.vibrantbass_h2_1(false)
//CiderAudio.llpw_h2_2(false, 0)
if (app.cfg.audio.spatial) {
CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.spatialInput.input);
CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.audioNodes.audioBands[0]);}
else {CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.audioBands[0]);}
}
}
console.log("[Cider][Audio] Finished hierarchical loading");
},
equalizer: function (){ // h1_1
let BANDS = app.cfg.audio.equalizer.frequencies;
let GAIN = app.cfg.audio.equalizer.gain;
let Q = app.cfg.audio.equalizer.Q;
CiderAudio.audioNodes.audioBands = [];
for (i = 0; i < BANDS.length; i++) {
CiderAudio.audioNodes.audioBands[i] = CiderAudio.context.createBiquadFilter();
@ -139,50 +235,8 @@ var CiderAudio = {
CiderAudio.audioNodes.audioBands[i].gain.value = GAIN[i] * app.cfg.audio.equalizer.mix;
}
for (i = 0; i < LLPW_FREQUENCIES.length; i++) {
CiderAudio.audioNodes.llpw[i] = CiderAudio.context.createBiquadFilter();
CiderAudio.audioNodes.llpw[i].type = 'peaking'; // 'peaking';
CiderAudio.audioNodes.llpw[i].frequency.value = LLPW_FREQUENCIES[i];
CiderAudio.audioNodes.llpw[i].Q.value = LLPW_Q[i];
CiderAudio.audioNodes.llpw[i].gain.value = LLPW_GAIN[i] * app.cfg.audio.ciderPPE_value * CiderAudio.audioNodes.llpwEnabled;
}
/**
CiderAudio.audioNodes.preampNode = CiderAudio.context.createBiquadFilter();
CiderAudio.audioNodes.preampNode.type = 'highshelf';
CiderAudio.audioNodes.preampNode.frequency.value = 0; // Passthrough
CiderAudio.audioNodes.preampNode.gain.value = 0;
/** if (CiderAudio.audioNodes.llpwEnabled === 1) {CiderAudio.audioNodes.preampNode.gain.value = (-Math.max(...app.cfg.audio.equalizer.gain.concat(CiderAudio.audioNodes.llpw[23].gain.value)));}
else {CiderAudio.audioNodes.preampNode.gain.value = (-Math.max(...app.cfg.audio.equalizer.gain));}*/
for (i = 0; i < VIBRANTBASSBANDS.length; i++) {
CiderAudio.audioNodes.vibrantbassNode[i] = CiderAudio.context.createBiquadFilter();
CiderAudio.audioNodes.vibrantbassNode[i].type = 'peaking'; // 'peaking';
CiderAudio.audioNodes.vibrantbassNode[i].frequency.value = VIBRANTBASSBANDS[i];
CiderAudio.audioNodes.vibrantbassNode[i].Q.value = VIBRANTBASSQ[i];
CiderAudio.audioNodes.vibrantbassNode[i].gain.value = VIBRANTBASSGAIN[i] * app.cfg.audio.vibrantBass.multiplier;}
if (app.cfg.audio.spatial) {
try{
CiderAudio.audioNodes.spatialNode.output.disconnect(CiderAudio.context.destination); } catch(e){}
CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.audioNodes.llpw[0]);
} else {
try{
CiderAudio.audioNodes.gainNode.disconnect(CiderAudio.context.destination);} catch(e){}
CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.llpw[0]);
}
// CiderAudio.audioNodes.preampNode.connect(CiderAudio.audioNodes.llpw[0]);
for (i = 1; i < LLPW_FREQUENCIES.length; i ++) {
CiderAudio.audioNodes.llpw[i-1].connect(CiderAudio.audioNodes.llpw[i]);
}
CiderAudio.audioNodes.llpw[LLPW_FREQUENCIES.length-1].connect(CiderAudio.audioNodes.vibrantbassNode[0]);
for (i = 1; i < VIBRANTBASSBANDS.length; i ++) {
CiderAudio.audioNodes.vibrantbassNode[i-1].connect(CiderAudio.audioNodes.vibrantbassNode[i]);
}
CiderAudio.audioNodes.vibrantbassNode[VIBRANTBASSBANDS.length-1].connect(CiderAudio.audioNodes.audioBands[0]);
// Dynamic-ish loading
CiderAudio.hierarchical_loading();
for (i = 1; i < BANDS.length; i ++) {
CiderAudio.audioNodes.audioBands[i-1].connect(CiderAudio.audioNodes.audioBands[i]);

View file

@ -597,6 +597,8 @@ const app = new Vue({
} catch (err) {
}
this.mk._bag.features['seamless-audio-transitions'] = this.cfg.audio.seamless_audio
// API Fallback
if (!this.chrome.userinfo) {
this.chrome.userinfo = {
@ -782,7 +784,6 @@ const app = new Vue({
// app.getNowPlayingArtwork(42);
app.getNowPlayingArtworkBG(32);
app.loadLyrics();
app.losslessBadge();
// Playback Notifications
if (this.cfg.general.playbackNotifications && !document.hasFocus() && a.artistName && a.artwork && a.name) {
@ -1348,7 +1349,7 @@ const app = new Vue({
app.mk.seekToTime(0);
} else {
app.prevButtonBackIndicator = false;
app.mk.skipToPreviousItem()
app.skipToPreviousItem()
}
},
async getNowPlayingItemDetailed(target) {
@ -2346,25 +2347,6 @@ const app = new Vue({
})
notyf.success(app.getLz('action.removeFromLibrary.success'))
},
async losslessBadge() {
const songID = (this.mk.nowPlayingItem != null) ? this.mk.nowPlayingItem["_songId"] ?? (this.mk.nowPlayingItem["songId"] ?? -1) : -1;
if (app.cfg.advanced.ciderPPE && songID != -1) {
/**let extendedAssets = await app.mk.api.song(songID, {extend : 'extendedAssetUrls'})
if (extendedAssets.attributes.audioTraits.includes('lossless')) {*/
app.mk.nowPlayingItem['attributes']['lossless'] = true
CiderAudio.audioNodes.llpwEnabled = 1
console.log("[Cider][Enhanced] Audio being processed by PPE")
/**}
else {
CiderAudio.audioNodes.llpwEnabled = 0
} */
}
else {
CiderAudio.audioNodes.llpwEnabled = 0
}
},
async loadYTLyrics() {
const track = (this.mk.nowPlayingItem != null) ? this.mk.nowPlayingItem.title ?? '' : '';
const artist = (this.mk.nowPlayingItem != null) ? this.mk.nowPlayingItem.artistName ?? '' : '';
@ -2801,17 +2783,17 @@ const app = new Vue({
})
})
} else {
this.mk.clearQueue().then(function (_) {
if (app.mk.shuffleMode == 1) {
shuffleArray(query)
}
app.mk.queue.append(query)
if (childIndex != -1) {
app.mk.changeToMediaAtIndex(childIndex)
} else {
app.mk.play()
}
})
app.mk.queue.splice(0, app.mk.queue._itemIDs.length)
if (app.mk.shuffleMode == 1) {
shuffleArray(query)
}
app.mk.queue.append(query)
if (childIndex != -1) {
app.mk.changeToMediaAtIndex(childIndex)
} else {
app.mk.play()
}
}
})
} else if (parent.startsWith('listitem-hr')) {
@ -2821,7 +2803,7 @@ const app = new Vue({
[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id
}).then(function () {
app.mk.play().then(() => {
const data = JSON.parse(parent.split('listitem-hr')[1] ?? '[]')
let data = JSON.parse(parent.split('listitem-hr')[1] ?? '[]')
let itemsToPlay = {}
let u = data.map(x => x.id)
try {
@ -2846,9 +2828,8 @@ const app = new Vue({
})
})
} else {
const data = JSON.parse(parent.split('listitem-hr')[1] ?? '[]')
let data = JSON.parse(parent.split('listitem-hr')[1] ?? '[]')
let itemsToPlay = {}
let u = data.map(x => x.id)
data.forEach(item => {
if (!itemsToPlay[item.kind]) {
itemsToPlay[item.kind] = []
@ -2856,20 +2837,30 @@ const app = new Vue({
itemsToPlay[item.kind].push(item.id)
})
// loop through itemsToPlay
app.mk.queue.splice(0, app.mk.queue._itemIDs.length)
let ind = 0;
for (let kind in itemsToPlay) {
let ids = itemsToPlay[kind]
app.mk.clearQueue().then(function () {
if (ids.length > 0) {
app.mk.playLater({ [kind + "s"]: itemsToPlay[kind] }).then(function() {
if (ids.length > 0) {
if (app.mk.queue._itemIDs.length > 0) {
app.mk.playLater({ [kind + "s"]: itemsToPlay[kind] }).then(function () {
ind += 1;
console.log(ind, Object.keys(itemsToPlay).length)
if (ind >= Object.keys(itemsToPlay).length) {
app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.attributes.playParams.id ?? item.id))
}
}
)} else {
app.mk.setQueue({ [kind + "s"]: itemsToPlay[kind] }).then(function () {
ind += 1;
console.log(ind , Object.keys(itemsToPlay).length)
if(ind >= Object.keys(itemsToPlay).length) {
console.log(ind, Object.keys(itemsToPlay).length)
if (ind >= Object.keys(itemsToPlay).length) {
app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.attributes.playParams.id ?? item.id))
}
}
)}
})
}
)}
}
}
}
})
@ -3729,6 +3720,16 @@ const app = new Vue({
if (sellang.startsWith("en") && this.mk.storefrontId != "us") sellang = "en-gb"
return await sellang
}
},
skipToNextItem(){
// app.mk.skipToNextItem() is buggy somehow so use this
if (this.mk.queue.nextPlayableItemIndex != -1 && this.mk.queue.nextPlayableItemIndex != null)
this.mk.changeToMediaAtIndex(this.mk.queue.nextPlayableItemIndex);
},
skipToPreviousItem(){
// app.mk.skipToPreviousItem() is buggy somehow so use this
if (this.mk.queue.previousPlayableItemIndex != -1 && this.mk.queue.previousPlayableItemIndex != null)
this.mk.changeToMediaAtIndex(this.mk.queue.previousPlayableItemIndex);
}
}
})
@ -4002,6 +4003,12 @@ webGPU().then()
let screenWidth = screen.width;
let screenHeight = screen.height;
window.onerror = function(error) {
console.log(error)
bootbox.alert("Error occured: " + error)
};
// Key bind to unjam MusicKit in case it fails: CTRL+F10
document.addEventListener('keydown', function (event) {
if (event.ctrlKey && event.keyCode == 121) {

5531
src/renderer/js/showdown.min.js vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,498 @@
// List Group
.list-group {
display: flex;
flex-direction: column;
padding-left: 0;
margin-bottom: 0;
border-radius: 0.25rem;
}
.list-group-numbered {
list-style-type: none;
counter-reset: section;
}
.list-group-numbered > li::before {
content: counters(section, ".") ". ";
counter-increment: section;
}
.list-group-item-action {
width: 100%;
color: #495057;
text-align: inherit;
}
.list-group-item-action:hover, .list-group-item-action:focus {
z-index: 1;
color: #495057;
text-decoration: none;
background-color: #f8f9fa;
}
.list-group-item-action:active {
color: #212529;
background-color: #e9ecef;
}
.list-group-item {
position: relative;
display: block;
padding: 0.5rem 1rem;
color: #212529;
text-decoration: none;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.125);
}
.list-group-item:first-child {
border-top-left-radius: inherit;
border-top-right-radius: inherit;
}
.list-group-item:last-child {
border-bottom-right-radius: inherit;
border-bottom-left-radius: inherit;
}
.list-group-item.disabled, .list-group-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: #fff;
}
.list-group-item.active {
z-index: 2;
color: #fff;
background-color: #0d6efd;
border-color: #0d6efd;
}
.list-group-item + .list-group-item {
border-top-width: 0;
}
.list-group-item + .list-group-item.active {
margin-top: -1px;
border-top-width: 1px;
}
.list-group-horizontal {
flex-direction: row;
}
.list-group-horizontal > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
.list-group-horizontal > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
.list-group-horizontal > .list-group-item.active {
margin-top: 0;
}
.list-group-horizontal > .list-group-item + .list-group-item {
border-top-width: 1px;
border-left-width: 0;
}
.list-group-horizontal > .list-group-item + .list-group-item.active {
margin-left: -1px;
border-left-width: 1px;
}
@media (min-width: 576px) {
.list-group-horizontal-sm {
flex-direction: row;
}
.list-group-horizontal-sm > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
.list-group-horizontal-sm > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
.list-group-horizontal-sm > .list-group-item.active {
margin-top: 0;
}
.list-group-horizontal-sm > .list-group-item + .list-group-item {
border-top-width: 1px;
border-left-width: 0;
}
.list-group-horizontal-sm > .list-group-item + .list-group-item.active {
margin-left: -1px;
border-left-width: 1px;
}
}
@media (min-width: 768px) {
.list-group-horizontal-md {
flex-direction: row;
}
.list-group-horizontal-md > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
.list-group-horizontal-md > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
.list-group-horizontal-md > .list-group-item.active {
margin-top: 0;
}
.list-group-horizontal-md > .list-group-item + .list-group-item {
border-top-width: 1px;
border-left-width: 0;
}
.list-group-horizontal-md > .list-group-item + .list-group-item.active {
margin-left: -1px;
border-left-width: 1px;
}
}
@media (min-width: 992px) {
.list-group-horizontal-lg {
flex-direction: row;
}
.list-group-horizontal-lg > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
.list-group-horizontal-lg > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
.list-group-horizontal-lg > .list-group-item.active {
margin-top: 0;
}
.list-group-horizontal-lg > .list-group-item + .list-group-item {
border-top-width: 1px;
border-left-width: 0;
}
.list-group-horizontal-lg > .list-group-item + .list-group-item.active {
margin-left: -1px;
border-left-width: 1px;
}
}
@media (min-width: 1200px) {
.list-group-horizontal-xl {
flex-direction: row;
}
.list-group-horizontal-xl > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
.list-group-horizontal-xl > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
.list-group-horizontal-xl > .list-group-item.active {
margin-top: 0;
}
.list-group-horizontal-xl > .list-group-item + .list-group-item {
border-top-width: 1px;
border-left-width: 0;
}
.list-group-horizontal-xl > .list-group-item + .list-group-item.active {
margin-left: -1px;
border-left-width: 1px;
}
}
@media (min-width: 1400px) {
.list-group-horizontal-xxl {
flex-direction: row;
}
.list-group-horizontal-xxl > .list-group-item:first-child {
border-bottom-left-radius: 0.25rem;
border-top-right-radius: 0;
}
.list-group-horizontal-xxl > .list-group-item:last-child {
border-top-right-radius: 0.25rem;
border-bottom-left-radius: 0;
}
.list-group-horizontal-xxl > .list-group-item.active {
margin-top: 0;
}
.list-group-horizontal-xxl > .list-group-item + .list-group-item {
border-top-width: 1px;
border-left-width: 0;
}
.list-group-horizontal-xxl > .list-group-item + .list-group-item.active {
margin-left: -1px;
border-left-width: 1px;
}
}
.list-group-flush {
border-radius: 0;
}
.list-group-flush > .list-group-item {
border-width: 0 0 1px;
}
.list-group-flush > .list-group-item:last-child {
border-bottom-width: 0;
}
.list-group-item-primary {
color: #084298;
background-color: #cfe2ff;
}
.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {
color: #084298;
background-color: #bacbe6;
}
.list-group-item-primary.list-group-item-action.active {
color: #fff;
background-color: #084298;
border-color: #084298;
}
.list-group-item-secondary {
color: #41464b;
background-color: #e2e3e5;
}
.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {
color: #41464b;
background-color: #cbccce;
}
.list-group-item-secondary.list-group-item-action.active {
color: #fff;
background-color: #41464b;
border-color: #41464b;
}
.list-group-item-success {
color: #0f5132;
background-color: #d1e7dd;
}
.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {
color: #0f5132;
background-color: #bcd0c7;
}
.list-group-item-success.list-group-item-action.active {
color: #fff;
background-color: #0f5132;
border-color: #0f5132;
}
.list-group-item-info {
color: #055160;
background-color: #cff4fc;
}
.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {
color: #055160;
background-color: #badce3;
}
.list-group-item-info.list-group-item-action.active {
color: #fff;
background-color: #055160;
border-color: #055160;
}
.list-group-item-warning {
color: #664d03;
background-color: #fff3cd;
}
.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {
color: #664d03;
background-color: #e6dbb9;
}
.list-group-item-warning.list-group-item-action.active {
color: #fff;
background-color: #664d03;
border-color: #664d03;
}
.list-group-item-danger {
color: #842029;
background-color: #f8d7da;
}
.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {
color: #842029;
background-color: #dfc2c4;
}
.list-group-item-danger.list-group-item-action.active {
color: #fff;
background-color: #842029;
border-color: #842029;
}
.list-group-item-light {
color: #636464;
background-color: #fefefe;
}
.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {
color: #636464;
background-color: #e5e5e5;
}
.list-group-item-light.list-group-item-action.active {
color: #fff;
background-color: #636464;
border-color: #636464;
}
.list-group-item-dark {
color: var(--textColor);
background-color: #333;
}
.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {
color: #141619;
background-color: #bebebf;
}
.list-group-item-dark.list-group-item-action.active {
color: #fff;
background-color: #141619;
border-color: #141619;
}
// Card
.card {
position: relative;
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #333;
background-clip: border-box;
border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 0.25rem;
}
.card > hr {
margin-right: 0;
margin-left: 0;
}
.card > .list-group {
border-top: inherit;
border-bottom: inherit;
}
.card > .list-group:first-child {
border-top-width: 0;
border-top-left-radius: calc(0.25rem - 1px);
border-top-right-radius: calc(0.25rem - 1px);
}
.card > .list-group:last-child {
border-bottom-width: 0;
border-bottom-right-radius: calc(0.25rem - 1px);
border-bottom-left-radius: calc(0.25rem - 1px);
}
.card > .card-header + .list-group,
.card > .list-group + .card-footer {
border-top: 0;
}
.card-body {
flex: 1 1 auto;
padding: 1rem 1rem;
}
.card-title {
margin-bottom: 0.5rem;
}
.card-subtitle {
margin-top: -0.25rem;
margin-bottom: 0;
}
.card-text:last-child {
margin-bottom: 0;
}
.card-link + .card-link {
margin-left: 1rem;
}
.card-header {
padding: 0.5rem 1rem;
margin-bottom: 0;
background-color: rgba(0, 0, 0, 0.03);
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
}
.card-header:first-child {
border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;
}
.card-footer {
padding: 0.5rem 1rem;
background-color: rgba(0, 0, 0, 0.03);
border-top: 1px solid rgba(0, 0, 0, 0.125);
}
.card-footer:last-child {
border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);
}
.card-header-tabs {
margin-right: -0.5rem;
margin-bottom: -0.5rem;
margin-left: -0.5rem;
border-bottom: 0;
}
.card-header-pills {
margin-right: -0.5rem;
margin-left: -0.5rem;
}
.card-img-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 1rem;
border-radius: calc(0.25rem - 1px);
}
.card-img,
.card-img-top,
.card-img-bottom {
width: 100%;
}
.card-img,
.card-img-top {
border-top-left-radius: calc(0.25rem - 1px);
border-top-right-radius: calc(0.25rem - 1px);
}
.card-img,
.card-img-bottom {
border-bottom-right-radius: calc(0.25rem - 1px);
border-bottom-left-radius: calc(0.25rem - 1px);
}
.card-group > .card {
margin-bottom: 0.75rem;
}
@media (min-width: 576px) {
.card-group {
display: flex;
flex-flow: row wrap;
}
.card-group > .card {
flex: 1 0 0%;
margin-bottom: 0;
}
.card-group > .card + .card {
margin-left: 0;
border-left: 0;
}
.card-group > .card:not(:last-child) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.card-group > .card:not(:last-child) .card-img-top,
.card-group > .card:not(:last-child) .card-header {
border-top-right-radius: 0;
}
.card-group > .card:not(:last-child) .card-img-bottom,
.card-group > .card:not(:last-child) .card-footer {
border-bottom-right-radius: 0;
}
.card-group > .card:not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.card-group > .card:not(:first-child) .card-img-top,
.card-group > .card:not(:first-child) .card-header {
border-top-left-radius: 0;
}
.card-group > .card:not(:first-child) .card-img-bottom,
.card-group > .card:not(:first-child) .card-footer {
border-bottom-left-radius: 0;
}
}
.modal {
position: fixed;
top: 0;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,396 @@
.modal-fullscreen {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
z-index: 1000;
.modal-window {
background: #333;
border-radius: 10px;
box-shadow: var(--mediaItemShadow-Shadow);
display: flex;
flex-flow: column;
max-height: 500px;
max-width: 360px;
background: #121212;
width: 100%;
position: relative;
&:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
box-shadow: var(--mediaItemShadow);
z-index: 1;
border-radius: inherit;
}
.modal-header {
width: 100%;
padding: 6px;
}
.modal-content {
width: 100%;
height: 100%;
overflow: hidden;
overflow-y: overlay;
}
.modal-footer {
}
}
}
.spatialproperties-panel {
.modal-window {
height: 700px;
max-height: 700px;
width: 800px;
max-width: 800px;
overflow: hidden;
.info-header {
padding-left: 12px;
}
.visual-container {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
.visual {
position: relative;
height: 250px;
width: 300px;
display: inline-flex;
align-items: flex-end;
justify-content: center;
filter: drop-shadow(2px 12px 6px rgb(0 0 0 / 25%));
margin: 0 auto;
.face {
position: absolute;
width: calc(12px * 6);
height: calc(12px * 6);
border-radius: 6px;
transform: rotateX(60deg) rotateZ(-45deg);
transition: transform 0.2s linear, width 0.2s linear, height 0.2s linear;
}
.listener {
position: absolute;
width: 32px;
height: 32px;
border-radius: 6px;
transform: rotateX(60deg) rotateZ(-45deg);
transition: transform 0.2s linear, width 0.2s linear, height 0.2s linear;
background: white;
color: black;
z-index: 2;
}
.audiosource {
position: absolute;
width: 32px;
height: 32px;
border-radius: 6px;
transform: rotateX(60deg) rotateZ(-45deg);
transition: transform 0.2s linear, width 0.2s linear, height 0.2s linear;
background: yellow;
z-index: 2;
}
.face:nth-of-type(1) {
background: linear-gradient(45deg, #28223a, #1f2038);
z-index: 1;
}
.face:nth-of-type(2) {
background: linear-gradient(45deg, #7d53ad, #5763ff);
transform: rotateX(60deg) rotateZ(-45deg) translateZ(30px);
opacity: 0.7;
z-index: 3;
}
}
.modal-header {
padding: 16px;
position: relative;
overflow: hidden;
.modal-title {
text-align: center;
}
.close-btn {
width: 50px;
height: 100%;
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;
&:hover {
background-color: rgb(196, 43, 28)
}
}
}
}
}
.addtoplaylist-panel {
.modal-window {
max-height: 600px;
max-width: 400px;
background: rgb(18 18 18 / 90%);
overflow: hidden;
backdrop-filter: blur(16px) saturate(180%);
.modal-header {
padding: 16px;
position: relative;
.modal-title {
text-align: center;
}
.close-btn {
width: 50px;
height: 100%;
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;
&:hover {
background-color: rgb(196, 43, 28)
}
}
}
.modal-search {
width: 100%;
padding: 0px 16px;
position: relative;
}
.playlist-item {
appearance: none;
border: 0px;
text-align: left;
width: 100%;
margin: 0;
display: flex;
background: rgba(32, 32, 32, 0.46);
color: #eee;
font-family: inherit;
font-size: 0.98em;
padding: 6px 12px;
align-items: center;
flex-flow: row;
.icon {
pointer-events: none;
width: 32px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
margin-right: 6px;
}
.name {
}
&:hover {
background: var(--selected);
}
&:active {
background: var(--selected-click);
}
&.focused {
background: var(--keyColor);
}
}
.playlist-item:last-child {
border-bottom: 0px;
}
}
}
.menu-panel {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 100001;
display: flex;
justify-content: center;
align-items: center;
-webkit-app-region: no-drag;
.menu-header-body {
padding: 6px;
display: flex;
background: rgb(200 200 200 / 10%);
.menu-option-header {
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
border-radius: var(--mediaItemRadius);
appearance: none;
border: 0;
background: transparent;
&.active {
.sidebar-icon > .svg-icon {
--color: var(--keyColor);
}
}
&:hover {
background: var(--selected);
}
&:active {
background: var(--selected-click);
}
}
}
.menu-panel-body {
display: flex;
flex-flow: column;
background: rgb(38 38 38);
position: relative;
min-width: 200px;
box-shadow: var(--ciderShadow-Generic);
border-radius: var(--mediaItemRadius);
overflow: hidden;
font-size: 14px;
.menu-option {
text-align: left;
display: flex;
width: 100%;
padding: 12px 16px;
appearance: none;
border: 0px;
font: inherit;
background: transparent;
color: inherit;
&:hover {
background: var(--selected);
}
&:active {
background: var(--selected-click);
}
}
}
.menu-header-text {
margin: 18px 6px;
.close-btn {
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;
&:hover {
background-color: rgb(196, 43, 28)
}
}
}
.menu-body {
overflow: overlay;
height: 100%;
}
.menu-footer {
width: 100%;
padding: 12px;
}
}
.queue-panel {
height: 100%;
width: 100%;
display: flex;
flex-flow: column;
.queue-header-text {
margin: 18px 6px;
}
.queue-body {
overflow: overlay;
height: 100%;
}
.queue-footer {
width: 100%;
padding: 12px;
}
.autoplay {
background: rgb(200 200 200 / 15%);
display: flex;
justify-content: center;
appearance: none;
border: 0;
border-radius: 6px;
height: 32px;
width: 32px;
}
.infinity {
content: url("./assets/infinity.svg");
margin: auto;
}
}

View file

@ -0,0 +1,821 @@
// Helpers
.content-inner {
position: absolute;
top: var(--navigationBarHeight);
left: 0;
padding: 32px;
width: 100%;
transition: zoom 1s;
zoom: 1;
}
.content-inner.centered {
height: 100%;
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
}
// End Helpers
// GitHub Themes
.github-themes-page {
display: flex;
flex-direction: column;
padding: 0px;
height: calc(100% - var(--navigationBarHeight));
.github-avatar {
height: 42px;
width: 42px;
margin: 6px;
border-radius: 32px;
}
.repo-name {
margin:0px;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.repo-url {
color: var(--textColor);
font-size: 0.8em;
}
.repo-preview-name {
margin:0px;
}
.repos-list {
height: 100%;
overflow-y: overlay;
width: 320px;
font-size: 14px;
>.list-group {
margin:0px;
}
.list-group-item {
padding: 12px 6px;
&:hover {
filter: brightness(1.2);
}
&:active {
filter: brightness(0.8);
}
}
}
.github-preview {
height: 100%;
flex: 1;
background: var(--color2);
padding: 16px 32px;
overflow-y:overlay;
}
.gh-content {
display: flex;
flex-direction: row;
flex: 1;
overflow: hidden;
}
.gh-header {
padding: 16px;
}
}
// Library - Songs page
.library-page {
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;
backdrop-filter: blur(32px);
background: rgba(0, 0, 0, 0.25);
top: var(--navigationBarHeight);
}
.well {
margin: 2em;
}
}
// Podcast Page
.content-inner.podcasts-page {
display: flex;
height: calc(100% - var(--navigationBarHeight));
padding: 0px;
.list-flat {
border-radius: 0px;
}
.podcast-artwork {
width: 200px;
margin: 16px auto;
height: 200px;
}
.podcasts-list {
height: 100%;
width: 280px;
background: rgb(200 200 200 / 10%);
overflow-y: overlay;
border-right: 1px solid var(--color2);
flex: none;
overflow-x: hidden;
.podcast-list-header {
border-bottom: 1px solid var(--color2);
font-size: 0.7em;
padding: 6px;
background: #ffffff17;
text-transform: uppercase;
font-weight: 600;
opacity: 0.5;
}
.podcasts-search {
padding: 10px;
position: sticky;
top: 0;
left: 0;
width: 100%;
border-bottom: 1px solid var(--color2);
z-index: 2;
background: #303030;
}
}
.episodes-list {
height: 100%;
width: 100%;
background: rgb(200 200 200 / 6%);
overflow-y: overlay;
overflow-x: hidden;
.episodes-inline-info {
padding: 14px 14px 0px 14px;
.podcast-show-info {
display: flex;
justify-content: center;
flex-direction: column;
}
.podcast-show-description {
margin: 32px 6px;
font-size: 0.8rem;
white-space: pre-wrap;
display: block;
}
.podcast-artwork {
width: 120px;
margin: 0px auto;
height: 120px;
}
}
.podcast-no-search-results {
text-align: center;
margin-top: 40px;
}
}
.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);
padding-bottom: 1em;
.meta-btn {
font-size: 0.75em;
}
.podcasts-details-header {
display: flex;
justify-content: end;
align-items: center;
position: sticky;
top: 0;
z-index: 2;
}
.close-btn {
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;
&:hover {
background-color: rgb(196, 43, 28)
}
}
.podcast-genre {
text-align: center;
margin: 6px;
font-size: 0.8em;
font-weight: 500;
opacity: 0.8;
}
.podcast-metainfo {
text-align: center;
font-size: 0.7em;
opacity: 0.8;
}
.podcast-header {
text-align: center;
}
.podcast-play-btn {
width: 50%;
display: block;
margin: 0 auto;
}
.podcast-description {
margin: 12px;
font-size: 0.75em;
white-space: pre-wrap;
display: block;
line-break: anywhere;
}
}
}
@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%;
border-radius: 10px;
box-shadow: var(--ciderShadow-Generic);
z-index: 2;
}
}
}
/* Album / Playlist Page */
.playlist-page {
--bgColor: transparent;
padding: 0px;
//background: linear-gradient(180deg, var(--bgColor) 32px, var(--bgColor) 18px, transparent 60px, transparent 100%);
top: 0;
padding-top: var(--navigationBarHeight);
.playlist-body {
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;
backdrop-filter: blur(32px);
background: rgba(0, 0, 0, 0.25);
top: var(--navigationBarHeight);
transition: opacity 0.1s var(--appleEase);
}
.playlist-display {
padding: var(--contentInnerPadding);
min-height: 300px;
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;
-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);
.artworkMaterial > img {
filter: brightness(100%) blur(80px) saturate(100%) contrast(1);
object-position: center;
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;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
> .row {
width: calc(100% - 32px);
}
.playlist-info {
flex-shrink: unset;
display: flex;
flex-flow: column;
justify-content: flex-end;
.playlist-name {
font-weight: 700;
font-size: 1.6rem;
margin-bottom: 6px;
margin-right: 6px;
flex-shrink: unset;
}
.nameEdit {
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;
}
.playlist-artist {
font-size: 20px;
margin-bottom: 6px;
margin-right: 6px;
flex-shrink: unset;
}
.playlist-desc {
box-sizing: border-box;
font-size: 14px;
flex-shrink: unset;
margin-right: 5px;
max-height: 100px;
position: relative;
.content {
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);
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;
}
}
.playlist-desc-expanded {
box-sizing: border-box;
font-size: 14px;
position: relative;
.more-btn {
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;
}
}
}
}
}
.friends-info {
display: flex;
flex-flow: column;
.badge-container {
display: flex;
flex-flow: wrap;
.socialBadge {
width: 40px;
height: 40px;
border-radius: 100%;
overflow: hidden;
box-shadow: var(--mediaItemShadow-ShadowSubtle);
transition: transform .2s var(--appleEase);
margin: 6px;
&:hover {
transform: scale(1.2);
}
}
}
.friends-name {
text-align: center;
font-size: 0.9em;
margin: 8px;
}
}
.playlist-time {
font-size: 0.9em;
margin: 6px;
opacity: 0.7;
}
&.inline-playlist {
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);
.floating-header {
opacity: 1;
top: 0px;
z-index: 6;
padding: 1em;
backdrop-filter: unset;
background: black;
h3 {
display: none;
}
}
.playlist-inner {
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;
margin-left: 16px;
z-index: 7;
}
}
}
}
@keyframes playlistArtworkFadeIn {
0% {
opacity: 0;
}
100% {
opacity: 0.7;
}
}
// Collection Page
.collection-page {
padding-bottom: 128px;
.top-fab {
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);
> svg {
height: 50%;
color: #eee;
pointer-events: none;
}
&:hover {
background: rgb(100 100 100);
}
&:active {
background: var(--keyColor);
}
}
.header-text {
margin-bottom: 32px;
}
}
/* Artist Page */
.artist-page {
padding: 0px;
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;
backdrop-filter: blur(32px);
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;
}
.artist-header {
//background: linear-gradient(45deg, var(--keyColor), #0e0e0e);
color: white;
display: flex;
align-items: center;
justify-content: space-between;
min-height: 400px;
position: relative;
pointer-events: none;
.header-content {
z-index: 1;
margin-top: -16px;
}
.artworkContainer {
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);
.artworkMaterial > img {
filter: brightness(100%) blur(80px) saturate(100%) contrast(1);
object-position: center;
object-fit: cover;
width: 100%;
height: 100%;
transform: unset;
}
}
.more-btn-round {
position: absolute;
bottom: 82px;
right: 28px;
}
.animated {
width: 100%;
height: 100%;
align-self: center;
position: absolute;
overflow: hidden;
box-shadow: rgb(0 0 0 / 50%) 0 0 0 1000000px inset;
video {
overflow: hidden;
height: 100%;
width: 100%;
min-height: 56.25vw;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.row .col.flex-center {
z-index: 4;
}
}
.artist-image {
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;
justify-content: center;
cursor: pointer;
appearance: none;
border: 0px;
padding: 0px;
&:hover {
opacity: 1;
}
&:active {
background: var(--selected-click);
}
> svg {
width: 70%;
}
}
}
.artist-play {
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;
&:hover {
filter: brightness(125%);
}
&:active {
filter: brightness(75%);
transform: scale(0.98);
transition: transform 0s var(--appleEase), box-shadow 0.2s var(--appleEase);
}
}
.artist-title {
.artist-play {
transform: translateY(3px);
margin: 14px;
}
&.artist-animation-on {
width: 100%;
flex: unset;
margin-left: 0.5em;
color: whitesmoke;
position: absolute;
bottom: 0;
.artist-play {
display: block;
}
}
}
.artist-body {
padding: 0px var(--contentInnerPadding) 0px var(--contentInnerPadding);
margin: -140px 20px;
}
&.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;
border-radius: 6px;
appearance: none;
color: var(--keyColor);
padding: 8px 12px;
cursor: pointer;
margin-top: 12px;
float: right;
}
.showmoreless:hover {
background: rgb(200 200 200 / 10%);
}
}
/* Artist Page End */
// Settings page
.settings-page {
padding: 0px;
.md-option-header {
padding: 1.25em 1.25em;
border-bottom: unset;
border-top: unset;
font-weight: 600;
font-size: 1.0em;
background: rgb(255 255 255 / 3%);
}
.settings-option-body {
margin: 16px;
}
}

File diff suppressed because it is too large Load diff

View file

@ -159,6 +159,12 @@
<cider-applecurator :data="appleCurator"></cider-applecurator>
</template>
</transition>
<!-- Github themes-->
<transition name="wpfade">
<template v-if="page == 'themes-github'">
<themes-github></themes-github>
</template>
</transition>
<!-- Library - Library Videos -->
<transition name="wpfade">
<template v-if="page == 'remote-pair'">

View file

@ -30,7 +30,7 @@
<button class="playback-button play" @click="mk.play()" v-else></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button next" @click="mk.skipToNextItem()"></button>
<button class="playback-button next" @click="skipToNextItem()"></button>
</div>
<div class="app-chrome-item display--large">
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0"
@ -57,7 +57,7 @@
v-if="mk.nowPlayingItem['attributes']['contentRating'] == 'explicit'"
style="display: inline-block"></div>
</div>
<div class="audio-type ppe-icon" v-if="cfg.advanced.ciderPPE == true"></div>
<div class="audio-type ppe-icon" v-if="cfg.advanced.ciderPPE === true"></div>
<div class="song-artist-album">
<div class="song-artist-album-content"
:class="[isElementOverflowing('#app-main > .app-chrome .app-chrome-item > .app-playback-controls > div >.song-artist-album > .song-artist-album-content') ? 'marquee' : '']"

View file

@ -1,17 +1,5 @@
<cider-menu-panel v-if="menuPanel.visible">
</cider-menu-panel>
<transition name="fsModeSwitch">
<div class="fullscreen-view-container" v-if="appMode == 'fullscreen'">
<fullscreen-view :image="currentArtUrl.replace('50x50', '600x600')" :time="lyriccurrenttime"
:lyrics="lyrics" :richlyrics="richlyrics"></fullscreen-view>
</div>
</transition>
<transition name="fsModeSwitch">
<div class="fullscreen-view-container" v-if="appMode == 'mini'">
<mini-view :image="currentArtUrl.replace('50x50', '600x600')" :time="lyriccurrenttime"
:lyrics="lyrics" :richlyrics="richlyrics"></mini-view>
</div>
</transition>
<transition name="wpfade">
<div class="bg-artwork-container" v-if="cfg.visual.window_background_style == 'artwork'"
:class="{noanimation: (!cfg.visual.bg_artwork_rotation || !animateBackground)}">

View file

@ -137,7 +137,7 @@
<button class="playback-button play" @click="mk.play()" v-else></button>
</div>
<div class="app-chrome-item">
<button class="playback-button next" @click="mk.skipToNextItem()"></button>
<button class="playback-button next" @click="skipToNextItem()"></button>
</div>
<div class="app-chrome-item">
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0"

View file

@ -6,10 +6,10 @@
<button class="close-btn" @click="close()"></button>
<div class="md-option-segment md-option-segment_auto">
<select class="md-select" style="width:220px;text-align:center;margin-right:245px" v-model="$root.cfg.audio.equalizer.preset" v-on:change="changePreset($root.cfg.audio.equalizer.preset)">
<optgroup :label="app.getLz('term.userPresets')">
<optgroup :label="$root.getLz('term.userPresets')">
<option v-for="preset in $root.cfg.audio.equalizer.presets" :value="preset.preset">{{preset.name}}</option>
</optgroup>
<optgroup :label="app.getLz('term.defaultPresets')">
<optgroup :label="$root.getLz('term.defaultPresets')">
<option v-for="preset in defaultPresets" :value="preset.preset">{{preset.name}}</option>
</optgroup>
</select>
@ -314,22 +314,19 @@
},
changeVibrantBass() {
app.cfg.audio.vibrantBass.multiplier = app.cfg.audio.equalizer.vibrantBass / 10
CiderAudio.hierarchical_loading();
if (app.cfg.audio.equalizer.vibrantBass != 0) {
for (var i = 0; i < 21; i++) {
CiderAudio.audioNodes.vibrantbassNode[i].gain.value = app.cfg.audio.vibrantBass.gain[i] * (app.cfg.audio.equalizer.vibrantBass / 10);
}
}}
},
changeMix() {
for (var i = 0; i < 10; i++) {
CiderAudio.audioNodes.audioBands[i].gain.value = app.cfg.audio.equalizer.gain[i] * app.cfg.audio.equalizer.mix
}
},
changePreamp() {
/** if (CiderAudio.audioNodes.llpwEnabled === 1) {CiderAudio.audioNodes.preampNode.gain.value = (-Math.max(...app.cfg.audio.equalizer.gain.concat(CiderAudio.audioNodes.llpw[23].gain.value)));}
else {CiderAudio.audioNodes.preampNode.gain.value = (-Math.max(...app.cfg.audio.equalizer.gain));} */
},
changeGain(i) {
CiderAudio.audioNodes.audioBands[i].gain.value = app.cfg.audio.equalizer.gain[i] * app.cfg.audio.equalizer.mix
this.changePreamp()
},
changeFreq(i) {
CiderAudio.audioNodes.audioBands[i].frequency.value = app.cfg.audio.equalizer.frequencies[i]
@ -345,7 +342,6 @@
'mix': 1,
'vibrantBass': 0,
})
CiderAudio.audioNodes.preampNode.gain.value = 0;
if (app.cfg.audio.equalizer.userGenerated) {
this.saveSelectedPreset()
}

View file

@ -66,7 +66,7 @@
<button class="playback-button play" @click="app.mk.play()" v-else></button>
</div>
<div class="app-chrome-item">
<button class="playback-button next" @click="app.mk.skipToNextItem()"></button>
<button class="playback-button next" @click="app.skipToNextItem()"></button>
</div>
<div class="app-chrome-item">
<button class="playback-button--small repeat" v-if="app.mk.repeatMode == 0"

View file

@ -73,7 +73,7 @@
<button class="playback-button play" @click="app.mk.play()" v-else></button>
</div>
<div class="app-chrome-item">
<button class="playback-button next" @click="app.mk.skipToNextItem()"></button>
<button class="playback-button next" @click="app.skipToNextItem()"></button>
</div>
<div class="app-chrome-item">
<button class="playback-button--small repeat" v-if="app.mk.repeatMode == 0"

View file

@ -33,6 +33,7 @@
<script src="./js/bootstrap.min.js"></script>
<script src="./js/bootbox.min.js"></script>
<script src="./js/notyf.min.js"></script>
<script src="./js/showdown.min.js"></script>
</head>
<body oncontextmenu="return false;" loading="1" platform="<%= env.platform %>">
@ -43,6 +44,18 @@
<%- include('app/app-navigation'); %>
</div>
</transition>
<transition name="fsModeSwitch">
<div class="fullscreen-view-container" v-if="appMode == 'fullscreen'">
<fullscreen-view :image="currentArtUrl.replace('50x50', '600x600')" :time="lyriccurrenttime"
:lyrics="lyrics" :richlyrics="richlyrics"></fullscreen-view>
</div>
</transition>
<transition name="fsModeSwitch">
<div class="fullscreen-view-container" v-if="appMode == 'mini'">
<mini-view :image="currentArtUrl.replace('50x50', '600x600')" :time="lyriccurrenttime"
:lyrics="lyrics" :richlyrics="richlyrics"></mini-view>
</div>
</transition>
<%- include('app/panels'); %>
</div>

View file

@ -1,6 +1,6 @@
<script type="text/x-template" id="remote-pair">
<div style="display:flex;width:100%;height:100%;padding-top: var(--navigationBarHeight);position:absolute;top:0;left:0;">
<webview id="foo" src="https://music.apple.com/includes/commerce/account/settings?product=music&isFullscreen=true&isModal=false" style="display:inline-flex; width:100%;"></webview>
<webview id="foo" src="https://cider.sh" style="display:inline-flex; width:100%;"></webview>
</div>
</script>
<script>

View file

@ -47,7 +47,7 @@
{{$root.getLz('settings.option.audio.seamlessTransition')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<input type="checkbox" v-model="app.cfg.audio.seamless_audio" switch/>
<input type="checkbox" v-model="app.cfg.audio.seamless_audio" v-on:change="app.mk._bag.features['seamless-audio-transitions'] = app.cfg.audio.seamless_audio" switch/>
</div>
</div>
<div class="md-option-line">
@ -68,7 +68,7 @@
<small>{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPE.description')}}</small>
</div>
<div class="md-option-segment md-option-segment_auto">
<input type="checkbox" v-model="app.cfg.advanced.ciderPPE" v-on:change="ciderPPE" switch/>
<input type="checkbox" v-model="app.cfg.advanced.ciderPPE" v-on:change="CiderAudio.hierarchical_loading();" switch/>
</div>
</div>
<div class="md-option-line" v-show="app.cfg.advanced.AudioContext && app.cfg.advanced.ciderPPE === true">
@ -78,10 +78,10 @@
<small>{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.description')}}</small>
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn" :disabled="app.cfg.audio.ciderPPE_value === 0.5" v-model="app.cfg.audio.ciderPPE_value" onclick="app.cfg.audio.ciderPPE_value = 0.5">
<button class="md-btn" :disabled="app.cfg.audio.ciderPPE_value === 0.5" v-model="app.cfg.audio.ciderPPE_value" onclick="app.cfg.audio.ciderPPE_value = 0.5; CiderAudio.hierarchical_loading();">
{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.standard')}}
</button>
<button class="md-btn" style="margin-top: 5px;" :disabled="app.cfg.audio.ciderPPE_value === 0.55" v-model="app.cfg.audio.ciderPPE_value" onclick="app.cfg.audio.ciderPPE_value = 0.55">
<button class="md-btn" style="margin-top: 5px;" :disabled="app.cfg.audio.ciderPPE_value === 0.55" v-model="app.cfg.audio.ciderPPE_value" onclick="app.cfg.audio.ciderPPE_value = 0.55; CiderAudio.hierarchical_loading();">
{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.aggressive')}}
</button>
</div>
@ -132,8 +132,8 @@
<option value="dark.less">{{$root.getLz('settings.option.visual.theme.dark')}}</option>
<option v-for="theme in themes" :value="theme.file">{{ theme.name }}</option>
</select>
<button class="md-btn md-btn-small md-btn-block" @click="installTheme()" style="margin-top: 8px">
{{$root.getLz('settings.option.visual.theme.github.download')}}
<button class="md-btn md-btn-small md-btn-block" @click="gitHubExplore()" style="margin-top: 8px">
{{$root.getLz('settings.option.visual.theme.github.explore')}}
</button>
</div>
</div>
@ -774,21 +774,8 @@
}
},
methods: {
installTheme() {
let self = this
bootbox.prompt(app.getLz('settings.prompt.visual.theme.github.URL'), (result) => {
if (result) {
ipcRenderer.once("theme-installed", (event, arg) => {
if (arg.success) {
self.themes = ipcRenderer.sendSync("get-themes")
notyf.success(app.getLz('settings.notyf.visual.theme.install.success'));
} else {
notyf.error(app.getLz('settings.notyf.visual.theme.install.error'));
}
});
ipcRenderer.invoke("get-github-theme", result)
}
});
gitHubExplore() {
app.appRoute("themes-github")
},
copyLogs() {
ipcRenderer.send('fetch-log')
@ -839,14 +826,6 @@
CiderAudio.normalizerOff()
}
},
ciderPPE: function () {
if (app.cfg.advanced.ciderPPE) {
if (app.cfg.audio.spatial) {
app.cfg.advanced.ciderPPE = false;
notyf.error(app.getLz('settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility'))
}
}
},
toggleSpatial: function () {
if (app.cfg.audio.spatial) {
if (!app.cfg.advanced.ciderPPE) {

View file

@ -0,0 +1,176 @@
<script type="text/x-template" id="themes-github">
<div class="content-inner github-themes-page">
<div class="gh-header">
<div class="row">
<div class="col nopadding">
<h1 class="header-text">Themes from GitHub</h1>
</div>
<div class="col-auto nopadding flex-center">
<button class="md-btn md-btn-small md-btn-block" @click="installThemeURL()">
{{$root.getLz('settings.option.visual.theme.github.download')}}
</button>
</div>
</div>
</div>
<div class="gh-content">
<div class="repos-list">
<ul class="list-group list-group-flush">
<li @click="showRepo(repo)" class="list-group-item list-group-item-dark"
:style="{'background': (repo.id == openRepo.id) ? 'var(--keyColor)' : ''}"
v-for="repo in repos">
<div class="row">
<div class="col flex-center">
<div>
<h4 class="repo-name">{{ repo.description }}</h4>
<div>⭐ {{ repo.stargazers_count }}</div>
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="github-preview" v-if="openRepo.full_name">
<div class="gh-preview-header">
<div class="row nopadding">
<div class="col nopadding flex-center">
<div>
<h3 class="repo-preview-name">{{ openRepo.description }}</h3>
<div>
<div class="svg-icon inline" :style="{'--url': 'url(\'./assets/github.svg\')'}"></div>
<a class="repo-url" target="_blank" :href="openRepo.html_url">{{ openRepo.full_name
}}</a></div>
<div>⭐ {{ openRepo.stargazers_count }}</div>
</div>
</div>
<div class="col-auto nopadding flex-center">
<button class="md-btn md-btn-primary" @click="installThemeRepo(openRepo)">
<span v-if="!themesInstalled.includes(openRepo.full_name)">Install</span>
<span v-else>Update</span>
</button>
</div>
</div>
</div>
<hr>
<div v-html="openRepo.readme" class="github-content"></div>
</div>
<div class="github-preview" v-else>
</div>
</transition>
</div>
</div>
</script>
<script>
Vue.component('themes-github', {
template: "#themes-github",
props: [],
data: function () {
return {
repos: [],
openRepo: {
id: -1,
name: '',
description: '',
html_url: '',
stargazers_count: 0,
owner: {
avatar_url: ''
},
readme: ""
},
themesInstalled: []
}
},
mounted() {
this.getRepos();
this.getInstalledThemes();
},
methods: {
getInstalledThemes() {
let self = this
const themes = ipcRenderer.sendSync("get-themes")
// for each theme, get the github_repo property and push it to the themesInstalled array, if not blank
themes.forEach(theme => {
if (theme.github_repo !== "") {
self.themesInstalled.push(theme.github_repo)
}
})
},
showRepo(repo) {
const self = this
const readmeUrl = `https://raw.githubusercontent.com/${repo.full_name}/main/README.md`;
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
fetch(readmeUrl, requestOptions)
.then(response => response.text())
.then(result => {
self.openRepo = repo
self.openRepo.readme = self.convertReadMe(result);
})
.catch(error => {
self.openRepo = repo
self.openRepo.readme = `This repository doesn't have a README.md file.`;
console.log('error', error)
});
},
convertReadMe(text) {
var converter = new showdown.Converter(),
html = converter.makeHtml(text);
return html
},
installThemeRepo(repo) {
let self = this
let msg = app.stringTemplateParser(app.getLz('settings.option.visual.theme.github.install.confirm'), {
repo: repo.full_name
});
bootbox.confirm(msg, (res) => {
if (res) {
ipcRenderer.once("theme-installed", (event, arg) => {
if (arg.success) {
self.themes = ipcRenderer.sendSync("get-themes")
notyf.success(app.getLz('settings.notyf.visual.theme.install.success'));
} else {
notyf.error(app.getLz('settings.notyf.visual.theme.install.error'));
}
});
ipcRenderer.invoke("get-github-theme", repo.html_url)
}
})
},
installThemeURL() {
let self = this
bootbox.prompt(app.getLz('settings.prompt.visual.theme.github.URL'), (result) => {
if (result) {
ipcRenderer.once("theme-installed", (event, arg) => {
if (arg.success) {
self.themes = ipcRenderer.sendSync("get-themes")
notyf.success(app.getLz('settings.notyf.visual.theme.install.success'));
} else {
notyf.error(app.getLz('settings.notyf.visual.theme.install.error'));
}
});
ipcRenderer.invoke("get-github-theme", result)
}
});
},
getRepos() {
let self = this
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
fetch("https://api.github.com/search/repositories?q=topic:cidermusictheme fork:true", requestOptions)
.then(response => response.text())
.then(result => {
self.repos = JSON.parse(result).items
})
.catch(error => console.log('error', error));
}
}
})
</script>