merge in main, move pagination setting for consistency

This commit is contained in:
Kendall Garner 2022-07-11 13:28:05 -04:00
commit 74429ceb7b
No known key found for this signature in database
GPG key ID: 18D2767419676C87
48 changed files with 3512 additions and 2571 deletions

View file

@ -80,6 +80,12 @@ jobs:
sudo dpkg --add-architecture i386 sudo dpkg --add-architecture i386
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install -y wine32 sudo apt-get install -y wine32
- run:
name: Reinstall proper rust node module
command: |
cd ./node_modules/cider_utils
yarn run prebuild-downloads --platform=win32 --verbose
cd ../..
- run: - run:
name: Generate Builds (Windows) name: Generate Builds (Windows)
command: yarn electron-builder -w --x64 -p never command: yarn electron-builder -w --x64 -p never
@ -105,6 +111,12 @@ jobs:
sudo dpkg --add-architecture i386 sudo dpkg --add-architecture i386
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install -y wine32 sudo apt-get install -y wine32
- run:
name: Reinstall proper rust node module
command: |
cd ./node_modules/cider_utils
yarn run prebuild-downloads --platform=win32 --verbose
cd ../..
- run: - run:
name: Generate Builds (Winget) name: Generate Builds (Winget)
command: yarn electron-builder --win -c winget.json -p never command: yarn electron-builder --win -c winget.json -p never
@ -147,6 +159,7 @@ jobs:
- run: - run:
name: Publish Release name: Publish Release
command: | command: |
echo "Creating release for Cider v${APP_VERSION} on the ${CIRCLE_BRANCH} branch."
gh release create "v${APP_VERSION}" --title "Cider Version ${APP_VERSION} (${CIRCLE_BRANCH})" --generate-notes -R ciderapp/cider-releases ~/Cider/dist/artifacts/*.deb ~/Cider/dist/artifacts/*.AppImage ~/Cider/dist/artifacts/*.snap ~/Cider/dist/artifacts/*.exe ~/Cider/dist/artifacts/*.yml ~/Cider/dist/artifacts/*.blockmap gh release create "v${APP_VERSION}" --title "Cider Version ${APP_VERSION} (${CIRCLE_BRANCH})" --generate-notes -R ciderapp/cider-releases ~/Cider/dist/artifacts/*.deb ~/Cider/dist/artifacts/*.AppImage ~/Cider/dist/artifacts/*.snap ~/Cider/dist/artifacts/*.exe ~/Cider/dist/artifacts/*.yml ~/Cider/dist/artifacts/*.blockmap
# Orchestrate our job run sequence # Orchestrate our job run sequence

View file

@ -96,6 +96,7 @@ jobs:
cp resources/macPackager.js node_modules/app-builder-lib/out/macPackager.js cp resources/macPackager.js node_modules/app-builder-lib/out/macPackager.js
rm -r node_modules/pouchdb-node/node_modules/leveldown rm -r node_modules/pouchdb-node/node_modules/leveldown
rm -r node_modules/pouchdb-adapter-leveldb/node_modules/leveldown rm -r node_modules/pouchdb-adapter-leveldb/node_modules/leveldown
rm -r /node_modules/leveldown/node_modules/node-gyp-build || true
yarn dist:universalNotWorking -p never yarn dist:universalNotWorking -p never
# - name: Perform CodeQL Analysis # - name: Perform CodeQL Analysis
# uses: github/codeql-action/analyze@v1 # uses: github/codeql-action/analyze@v1

1
.gitignore vendored
View file

@ -330,3 +330,4 @@ savedconfig/config.json
savedconfig/session.json savedconfig/session.json
savedconfig/window-state.json savedconfig/window-state.json
src/main/base/sample.json src/main/base/sample.json

View file

@ -64,7 +64,7 @@
"leveldown": "^6.1.1", "leveldown": "^6.1.1",
"mdns-js": "git+https://github.com/ciderapp/node-mdns-js.git", "mdns-js": "git+https://github.com/ciderapp/node-mdns-js.git",
"mpris-service": "^2.1.2", "mpris-service": "^2.1.2",
"music-metadata": "^7.12.3", "music-metadata": "^7.12.4",
"node-gyp": "^9.0.0", "node-gyp": "^9.0.0",
"node-ssdp": "^4.0.1", "node-ssdp": "^4.0.1",
"pouchdb-adapter-leveldb": "^7.3.0", "pouchdb-adapter-leveldb": "^7.3.0",
@ -80,7 +80,8 @@
"wallpaper": "5.0.1", "wallpaper": "5.0.1",
"ws": "^8.5.0", "ws": "^8.5.0",
"xml2js": "^0.4.23", "xml2js": "^0.4.23",
"youtube-search-without-api-key": "^1.0.7" "youtube-search-without-api-key": "^1.0.7",
"cider_utils": "git+https://github.com/ciderapp/cider_utils"
}, },
"devDependencies": { "devDependencies": {
"@types/adm-zip": "^0.5.0", "@types/adm-zip": "^0.5.0",
@ -121,9 +122,9 @@
} }
], ],
"build": { "build": {
"electronVersion": "18.3.3", "electronVersion": "18.3.5",
"electronDownload": { "electronDownload": {
"version": "18.3.3+wvcus", "version": "18.3.5+wvcus",
"mirror": "https://github.com/castlabs/electron-releases/releases/download/v" "mirror": "https://github.com/castlabs/electron-releases/releases/download/v"
}, },
"appId": "cider", "appId": "cider",

View file

@ -24,8 +24,9 @@ exports.default = function(context) {
// execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac',{stdio: 'inherit'}) // execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac',{stdio: 'inherit'})
// if (fs.existsSync('dist/mac-arm64')) // if (fs.existsSync('dist/mac-arm64'))
// execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac-arm64 -z',{stdio: 'inherit'}) // execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac-arm64 -z',{stdio: 'inherit'})
// if (fs.existsSync('dist/mac-x64'))
// execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac-x64',{stdio: 'inherit'}) if (fs.existsSync('dist/mac-x64') || fs.existsSync('dist/mac-universal--x64') )
execSync('cd ./node_modules/cider_utils; yarn run prebuild-downloads --platform=darwin --arch=arm64 --verbose; cd ../..',{stdio: 'inherit'})
// console.log('VMP signing complete') // console.log('VMP signing complete')

View file

@ -515,3 +515,9 @@ Update 21/06/2022 20:39 UTC
Update 23/06/2022 04:00 UTC Update 23/06/2022 04:00 UTC
* `settings.option.connectivity.lastfmScrobble.filterTypes`: Added to `en_US` * `settings.option.connectivity.lastfmScrobble.filterTypes`: Added to `en_US`
Update 03/07/2022 20:00 UTC
* `term.plugins`: Added to `en_US`
* `settings.header.visual.styles`: Added to `en_US`

View file

@ -394,5 +394,10 @@
"action.cut": "Ausschneiden", "action.cut": "Ausschneiden",
"action.paste": "Einfügen", "action.paste": "Einfügen",
"action.selectAll": "Alles auswählen", "action.selectAll": "Alles auswählen",
"action.delete": "Löschen" "action.delete": "Löschen",
"home.syncFavorites": "Sync Favoriten",
"term.quit" : "Beenden",
"settings.option.connectivity.lastfmScrobble.filterLoop.description": "Verhindert, dass geloopte Titel gescrobbelt oder in der (Hört Gerade)-Liste auf Last.fm angezeigt werden",
"settings.option.connectivity.lastfmScrobble.filterTypes": "Medientypen filtern (Last.fm)",
"settings.option.connectivity.lastfmScrobble.manualToken": "Last.fm-Token manuell eingeben"
} }

View file

@ -31,6 +31,10 @@
"term.miniplayer": "MiniPlayer", "term.miniplayer": "MiniPlayer",
"term.history": "History", "term.history": "History",
"term.search": "Search", "term.search": "Search",
"term.scroll": "Scroll Mode",
"term.scroll.infinite": "Infinite",
"term.scroll.paged": "${songsPerPage} per page",
"term.live": "LIVE",
"term.showSearch": "Show search bar", "term.showSearch": "Show search bar",
"term.hideSearch": "Hide search bar", "term.hideSearch": "Hide search bar",
"term.library": "Library", "term.library": "Library",
@ -90,9 +94,6 @@
"term.size": "Size", "term.size": "Size",
"term.size.normal": "Normal", "term.size.normal": "Normal",
"term.size.compact": "Compact", "term.size.compact": "Compact",
"term.scroll": "Scroll Mode",
"term.scroll.infinite": "Infinite",
"term.scroll.paged": "${songsPerPage} per page",
"term.enable": "Enable", "term.enable": "Enable",
"term.disable": "Disable", "term.disable": "Disable",
"term.enabled": "Enabled", "term.enabled": "Enabled",
@ -139,7 +140,6 @@
"term.recentStations": "Recent Stations", "term.recentStations": "Recent Stations",
"term.personalStations": "Personal Stations", "term.personalStations": "Personal Stations",
"term.amLive": "Apple Music Live", "term.amLive": "Apple Music Live",
"term.live": "LIVE",
"term.language": "Language", "term.language": "Language",
"term.funLanguages": "Fun", "term.funLanguages": "Fun",
"term.noLyrics": "Instrumental Track / No Lyrics.", "term.noLyrics": "Instrumental Track / No Lyrics.",
@ -184,8 +184,9 @@
"term.top": "Top", "term.top": "Top",
"term.version": "Version", "term.version": "Version",
"term.noVideos": "No videos found.", "term.noVideos": "No videos found.",
"term.plugin": "Plug-in", "term.plugins": "Plugins",
"term.pluginMenu": "Plug-in Menu", "term.plugin": "Plugin",
"term.pluginMenu": "Plugins Menu",
"term.pluginMenu.none": "No interactive plugins", "term.pluginMenu.none": "No interactive plugins",
"term.replay": "Replay", "term.replay": "Replay",
"term.uniqueAlbums": "Unique Albums", "term.uniqueAlbums": "Unique Albums",
@ -200,7 +201,7 @@
"term.confirmLogout": "Are you sure you want to logout?", "term.confirmLogout": "Are you sure you want to logout?",
"term.creditDesignedBy": "Designed by ${authorUsername}", "term.creditDesignedBy": "Designed by ${authorUsername}",
"term.discNumber": "Disc ${discNumber}", "term.discNumber": "Disc ${discNumber}",
"term.reload" : "Reload Cider ?", "term.reload" : "Reload Cider?",
"term.toggleprivate" : "Toggle Private Session", "term.toggleprivate" : "Toggle Private Session",
"term.webremote" : "Web Remote", "term.webremote" : "Web Remote",
"term.cast" : "Cast", "term.cast" : "Cast",
@ -213,6 +214,9 @@
"term.nowPlaying": "Now Playing", "term.nowPlaying": "Now Playing",
"home.syncFavorites": "Sync Favorites", "home.syncFavorites": "Sync Favorites",
"home.syncFavorites.gettingArtists": "Getting Favorited Artists...", "home.syncFavorites.gettingArtists": "Getting Favorited Artists...",
"action.favorite": "Favorite",
"action.removeFavorite": "Remove Favorite",
"action.refresh": "Refresh",
"home.title": "Home", "home.title": "Home",
"home.recentlyPlayed": "Recently Played", "home.recentlyPlayed": "Recently Played",
"home.recentlyAdded": "Recently Added", "home.recentlyAdded": "Recently Added",
@ -233,8 +237,6 @@
"podcast.episodes": "Episodes", "podcast.episodes": "Episodes",
"podcast.playEpisode": "Play Episode", "podcast.playEpisode": "Play Episode",
"podcast.website": "Podcast Website", "podcast.website": "Podcast Website",
"action.favorite": "Favorite",
"action.removeFavorite": "Remove Favorite",
"action.hideLibrary": "Hide Library", "action.hideLibrary": "Hide Library",
"action.showLibrary": "Show Library", "action.showLibrary": "Show Library",
"action.cut": "Cut", "action.cut": "Cut",
@ -308,7 +310,6 @@
"action.createNew": "Create New...", "action.createNew": "Create New...",
"action.openArtworkInBrowser": "Open artwork in browser", "action.openArtworkInBrowser": "Open artwork in browser",
"action.scrollToTop": "Scroll to top", "action.scrollToTop": "Scroll to top",
"action.refresh": "Refresh",
"menubar.options.view": "View", "menubar.options.view": "View",
"menubar.options.reload": "Reload", "menubar.options.reload": "Reload",
"menubar.options.forcereload": "Force Reload", "menubar.options.forcereload": "Force Reload",
@ -421,9 +422,9 @@
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.E168_1": "Jasmine Macchiato", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.E168_1": "Jasmine Macchiato",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z3600": "Hokkaido Milk Tea", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z3600": "Hokkaido Milk Tea",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500A": "Moonlight Softcake", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500A": "Moonlight Softcake",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.BSCBM": "Brown Sugar Creme Brûlée Milk",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500B": "Clafoutis aux Cerises", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500B": "Clafoutis aux Cerises",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500C": "Uji Matcha Mochi", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500C": "Uji Matcha Mochi",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.BSCBM": "Brown Sugar Creme Brûlée Milk",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.CUDDLE": "Cuddle Warmth", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.CUDDLE": "Cuddle Warmth",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider Adrenaline Processor™", "settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider Adrenaline Processor™",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "Enhances the perceived audio quality of AAC encoded audio by using a real-time algorithm that takes advantage of both psychoacoustic models of human hearing and AAC encoding characteristics.", "settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "Enhances the perceived audio quality of AAC encoded audio by using a real-time algorithm that takes advantage of both psychoacoustic models of human hearing and AAC encoding characteristics.",
@ -457,15 +458,10 @@
"settings.header.visual": "Visual", "settings.header.visual": "Visual",
"settings.header.visual.description": "Adjust the visual settings for Cider.", "settings.header.visual.description": "Adjust the visual settings for Cider.",
"settings.option.visual.windowStyle": "Window Style", "settings.option.visual.windowStyle": "Window Style",
"settings.option.visual.customAccentColor": "Custom Accent Color",
"settings.option.visual.accentColor": "Accent Color",
"settings.option.visual.purplePodcastPlaybackBar": "Purple Playback Bar for Podcasts",
"settings.option.visual.windowColor": "Window Tint Color",
"settings.option.visual.windowBackgroundStyle": "Window Background Style", "settings.option.visual.windowBackgroundStyle": "Window Background Style",
"settings.header.visual.windowBackgroundStyle.none": "None", "settings.header.visual.windowBackgroundStyle.none": "None",
"settings.header.visual.windowBackgroundStyle.artwork": "Artwork", "settings.header.visual.windowBackgroundStyle.artwork": "Artwork",
"settings.header.visual.windowBackgroundStyle.image": "Image", "settings.header.visual.windowBackgroundStyle.image": "Image",
"settings.header.visual.windowBackgroundStyle.color": "Color Tint",
"settings.option.visual.animatedArtwork": "Animated Artwork", "settings.option.visual.animatedArtwork": "Animated Artwork",
"settings.header.visual.animatedArtwork.always": "Always", "settings.header.visual.animatedArtwork.always": "Always",
"settings.header.visual.animatedArtwork.limited": "Limited to pages and special entries", "settings.header.visual.animatedArtwork.limited": "Limited to pages and special entries",
@ -491,6 +487,7 @@
"settings.prompt.visual.theme.github.URL": "Enter the URL of the theme you want to install", "settings.prompt.visual.theme.github.URL": "Enter the URL of the theme you want to install",
"settings.prompt.visual.theme.uninstallTheme": "Are you sure you want to uninstall {{ theme }}?", "settings.prompt.visual.theme.uninstallTheme": "Are you sure you want to uninstall {{ theme }}?",
"settings.option.visual.theme.checkForUpdates": "Check for updates", "settings.option.visual.theme.checkForUpdates": "Check for updates",
"settings.header.visual.styles": "Styles",
"settings.option.visual.theme.manageStyles": "Manage Styles", "settings.option.visual.theme.manageStyles": "Manage Styles",
"settings.option.visual.theme.uninstall": "Uninstall", "settings.option.visual.theme.uninstall": "Uninstall",
"settings.option.visual.theme.viewInfo": "View Info", "settings.option.visual.theme.viewInfo": "View Info",
@ -559,11 +556,17 @@
"settings.option.experimental.unknownPlugin.description": "Allow installation of plugins from repos other than the Cider Plugin Repository", "settings.option.experimental.unknownPlugin.description": "Allow installation of plugins from repos other than the Cider Plugin Repository",
"settings.option.experimental.compactUI": "Compact UI", "settings.option.experimental.compactUI": "Compact UI",
"settings.option.window.close_button_hide": "Close Button Should Hide the Application", "settings.option.window.close_button_hide": "Close Button Should Hide the Application",
"settings.option.window.maxElementScale": "Maximum Element Scale",
"settings.option.experimental.inline_playlists": "Inline Playlists and Albums", "settings.option.experimental.inline_playlists": "Inline Playlists and Albums",
"settings.option.advanced.playlistTrackMapping": "Playlist Track Mapping", "settings.option.advanced.playlistTrackMapping": "Playlist Track Mapping",
"settings.option.advanced.playlistTrackMapping.description": "Enables deep scanning of playlists to determine which tracks are in which playlists. Playlist cache build times can increase significantly.", "settings.option.advanced.playlistTrackMapping.description": "Enables deep scanning of playlists to determine which tracks are in which playlists. Playlist cache build times can increase significantly.",
"settings.option.visual.transparent": "Transparent frame", "settings.option.visual.transparent": "Transparent frame",
"settings.option.visual.transparent.description": "needs Theme Support, requires relaunch", "settings.option.visual.transparent.description": "needs Theme Support, requires relaunch",
"settings.option.visual.customAccentColor": "Custom Accent Color",
"settings.option.visual.accentColor": "Accent Color",
"settings.option.visual.purplePodcastPlaybackBar": "Purple Playback Bar for Podcasts",
"settings.option.visual.windowColor": "Window Tint Color",
"settings.header.visual.windowBackgroundStyle.color": "Color Tint",
"settings.header.advanced": "Advanced", "settings.header.advanced": "Advanced",
"settings.header.connect": "Sync", "settings.header.connect": "Sync",
"settings.option.connect.link_account": "Enable Sync with Cider Connect", "settings.option.connect.link_account": "Enable Sync with Cider Connect",

View file

@ -31,6 +31,10 @@
"term.miniplayer": "MiniPlayer", "term.miniplayer": "MiniPlayer",
"term.history": "History", "term.history": "History",
"term.search": "Search", "term.search": "Search",
"term.scroll": "Scroll Mode",
"term.scroll.infinite": "Infinite",
"term.scroll.paged": "${songsPerPage} per page",
"term.live": "LIVE",
"term.showSearch": "Show search bar", "term.showSearch": "Show search bar",
"term.hideSearch": "Hide search bar", "term.hideSearch": "Hide search bar",
"term.library": "Library", "term.library": "Library",
@ -180,8 +184,9 @@
"term.top": "Top", "term.top": "Top",
"term.version": "Version", "term.version": "Version",
"term.noVideos": "No videos found.", "term.noVideos": "No videos found.",
"term.plugin": "Plug-in", "term.plugins": "Plugins",
"term.pluginMenu": "Plug-in Menu", "term.plugin": "Plugin",
"term.pluginMenu": "Plugins Menu",
"term.pluginMenu.none": "No interactive plugins", "term.pluginMenu.none": "No interactive plugins",
"term.replay": "Replay", "term.replay": "Replay",
"term.uniqueAlbums": "Unique Albums", "term.uniqueAlbums": "Unique Albums",
@ -196,7 +201,7 @@
"term.confirmLogout": "Are you sure you want to logout?", "term.confirmLogout": "Are you sure you want to logout?",
"term.creditDesignedBy": "Designed by ${authorUsername}", "term.creditDesignedBy": "Designed by ${authorUsername}",
"term.discNumber": "Disc ${discNumber}", "term.discNumber": "Disc ${discNumber}",
"term.reload" : "Reload Cider ?", "term.reload" : "Reload Cider?",
"term.toggleprivate" : "Toggle Private Session", "term.toggleprivate" : "Toggle Private Session",
"term.webremote" : "Web Remote", "term.webremote" : "Web Remote",
"term.cast" : "Cast", "term.cast" : "Cast",
@ -206,6 +211,12 @@
"term.zoomout" : "Zoom Out", "term.zoomout" : "Zoom Out",
"term.zoomreset" : "Reset Zoom", "term.zoomreset" : "Reset Zoom",
"term.fullscreen" : "Fullscreen", "term.fullscreen" : "Fullscreen",
"term.nowPlaying": "Now Playing",
"home.syncFavorites": "Sync Favorites",
"home.syncFavorites.gettingArtists": "Getting Favorited Artists...",
"action.favorite": "Favorite",
"action.removeFavorite": "Remove Favorite",
"action.refresh": "Refresh",
"home.title": "Home", "home.title": "Home",
"home.recentlyPlayed": "Recently Played", "home.recentlyPlayed": "Recently Played",
"home.recentlyAdded": "Recently Added", "home.recentlyAdded": "Recently Added",
@ -410,6 +421,8 @@
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z3600": "Hokkaido Milk Tea", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z3600": "Hokkaido Milk Tea",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500A": "Moonlight Softcake", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500A": "Moonlight Softcake",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.BSCBM": "Brown Sugar Creme Brûlée Milk", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.BSCBM": "Brown Sugar Creme Brûlée Milk",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500B": "Clafoutis aux Cerises",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500C": "Uji Matcha Mochi",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.CUDDLE": "Cuddle Warmth", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.CUDDLE": "Cuddle Warmth",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider Adrenaline Processor™", "settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider Adrenaline Processor™",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "Enhances the perceived audio quality of AAC encoded audio by using a real-time algorithm that takes advantage of both psychoacoustic models of human hearing and AAC encoding characteristics.", "settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "Enhances the perceived audio quality of AAC encoded audio by using a real-time algorithm that takes advantage of both psychoacoustic models of human hearing and AAC encoding characteristics.",
@ -472,6 +485,7 @@
"settings.prompt.visual.theme.github.URL": "Enter the URL of the theme you want to install", "settings.prompt.visual.theme.github.URL": "Enter the URL of the theme you want to install",
"settings.prompt.visual.theme.uninstallTheme": "Are you sure you want to uninstall {{ theme }}?", "settings.prompt.visual.theme.uninstallTheme": "Are you sure you want to uninstall {{ theme }}?",
"settings.option.visual.theme.checkForUpdates": "Check for updates", "settings.option.visual.theme.checkForUpdates": "Check for updates",
"settings.header.visual.styles": "Styles",
"settings.option.visual.theme.manageStyles": "Manage Styles", "settings.option.visual.theme.manageStyles": "Manage Styles",
"settings.option.visual.theme.uninstall": "Uninstall", "settings.option.visual.theme.uninstall": "Uninstall",
"settings.option.visual.theme.viewInfo": "View Info", "settings.option.visual.theme.viewInfo": "View Info",
@ -540,11 +554,17 @@
"settings.option.experimental.unknownPlugin.description": "Allow installation of plugins from repos other than the Cider Plugin Repository", "settings.option.experimental.unknownPlugin.description": "Allow installation of plugins from repos other than the Cider Plugin Repository",
"settings.option.experimental.compactUI": "Compact UI", "settings.option.experimental.compactUI": "Compact UI",
"settings.option.window.close_button_hide": "Close Button Should Hide the Application", "settings.option.window.close_button_hide": "Close Button Should Hide the Application",
"settings.option.window.maxElementScale": "Maximum Element Scale",
"settings.option.experimental.inline_playlists": "Inline Playlists and Albums", "settings.option.experimental.inline_playlists": "Inline Playlists and Albums",
"settings.option.advanced.playlistTrackMapping": "Playlist Track Mapping", "settings.option.advanced.playlistTrackMapping": "Playlist Track Mapping",
"settings.option.advanced.playlistTrackMapping.description": "Enables deep scanning of playlists to determine which tracks are in which playlists. Playlist cache build times can increase significantly.", "settings.option.advanced.playlistTrackMapping.description": "Enables deep scanning of playlists to determine which tracks are in which playlists. Playlist cache build times can increase significantly.",
"settings.option.visual.transparent": "Transparent frame", "settings.option.visual.transparent": "Transparent frame",
"settings.option.visual.transparent.description": "needs Theme Support, requires relaunch", "settings.option.visual.transparent.description": "needs Theme Support, requires relaunch",
"settings.option.visual.customAccentColor": "Custom Accent Color",
"settings.option.visual.accentColor": "Accent Color",
"settings.option.visual.purplePodcastPlaybackBar": "Purple Playback Bar for Podcasts",
"settings.option.visual.windowColor": "Window Tint Color",
"settings.header.visual.windowBackgroundStyle.color": "Color Tint",
"settings.header.advanced": "Advanced", "settings.header.advanced": "Advanced",
"settings.header.connect": "Sync", "settings.header.connect": "Sync",
"settings.option.connect.link_account": "Enable Sync with Cider Connect", "settings.option.connect.link_account": "Enable Sync with Cider Connect",

View file

@ -2,7 +2,7 @@
"i18n.languageName": "简体中文(中国)", "i18n.languageName": "简体中文(中国)",
"i18n.languageNameEnglish": "Simp. Chinese (China)", "i18n.languageNameEnglish": "Simp. Chinese (China)",
"i18n.category": "main", "i18n.category": "main",
"i18n.authors": "@notmaikiwi @BillKerman @jay900604", "i18n.authors": "@notmaikiwi @BillKerman @jay900604 @sakura0224",
"app.name": "Cider", "app.name": "Cider",
"date.format": "${y}年${m}月${d}日", "date.format": "${y}年${m}月${d}日",
"dialog.cancel": "取消", "dialog.cancel": "取消",
@ -21,17 +21,22 @@
"term.accountSettings": "账户设置", "term.accountSettings": "账户设置",
"term.logout": "退出登录", "term.logout": "退出登录",
"term.login": "登录", "term.login": "登录",
"term.quickNav":"快速导航", "term.quickNav": "快速导航",
"term.cast":"投射",
"term.about": "关于", "term.about": "关于",
"term.privateSession": "隐身聆听", "term.privateSession": "隐身聆听",
"term.disablePrivateSession":"停止隐身聆听", "term.disablePrivateSession": "停止隐身聆听",
"term.autoplay":"自动播放",
"term.lyrics": "歌词",
"term.queue": "待播清单", "term.queue": "待播清单",
"term.history": "历史记录", "term.autoplay": "自动播放",
"term.lyrics": "歌词",
"term.miniplayer": "迷你播放器", "term.miniplayer": "迷你播放器",
"term.history": "历史记录",
"term.search": "搜索", "term.search": "搜索",
"term.scroll": "滚动模式",
"term.scroll.infinite": "无限制",
"term.scroll.paged": "每页${songsPerPage}首",
"term.live": "LIVE",
"term.showSearch": "显示搜索栏",
"term.hideSearch": "隐藏搜索栏",
"term.library": "资料库", "term.library": "资料库",
"term.listenNow": "现在就听", "term.listenNow": "现在就听",
"term.browse": "浏览", "term.browse": "浏览",
@ -42,23 +47,24 @@
"term.artists": "艺人", "term.artists": "艺人",
"term.podcasts": "播客", "term.podcasts": "播客",
"term.playlists": "播放列表", "term.playlists": "播放列表",
"term.charts":"排行榜", "term.charts": "排行榜",
"term.playlist": "播放列表", "term.playlist": "播放列表",
"term.newPlaylist": "新播放列表", "term.newPlaylist": "新播放列表",
"term.newPlaylistFolder": "新播放列表文件夹", "term.newPlaylistFolder": "新播放列表文件夹",
"term.createNewPlaylist": "新建播放列表", "term.createNewPlaylist": "新建播放列表",
"term.createNewPlaylistFolder": "新建播放列表文件夹", "term.createNewPlaylistFolder": "新建播放列表文件夹",
"term.deletePlaylist": "您确定要删除该播放列表吗?", "term.deletePlaylist": "您确定要删除该播放列表吗?",
"term.navigateBack":"上一页", "term.navigateBack": "上一页",
"term.navigateForward":"下一页", "term.navigateForward": "下一页",
"term.play": "播放", "term.play": "播放",
"term.playpause": "播放/暂停",
"term.pause": "暂停", "term.pause": "暂停",
"term.stop": "停止", "term.stop": "停止",
"term.previous": "上一首", "term.previous": "上一首",
"term.next": "下一首", "term.next": "下一首",
"term.shuffle": "随机播放", "term.shuffle": "随机播放",
"term.enableShuffle":"开启随机播放", "term.enableShuffle": "开启随机播放",
"term.disableShuffle":"关闭随机播放", "term.disableShuffle": "关闭随机播放",
"term.repeat": "循环播放", "term.repeat": "循环播放",
"term.enableRepeatOne": "开启单曲循环", "term.enableRepeatOne": "开启单曲循环",
"term.disableRepeatOne": "关闭单曲循环", "term.disableRepeatOne": "关闭单曲循环",
@ -67,7 +73,7 @@
"term.mute": "静音", "term.mute": "静音",
"term.unmute": "解除静音", "term.unmute": "解除静音",
"term.share": "分享", "term.share": "分享",
"term.share.success": "已拷到剪贴板", "term.share.success": "已拷到剪贴板",
"term.settings": "设置", "term.settings": "设置",
"term.seeAll": "查看全部", "term.seeAll": "查看全部",
"term.sortBy": "排序", "term.sortBy": "排序",
@ -77,14 +83,14 @@
"term.sortBy.genre": "类型", "term.sortBy.genre": "类型",
"term.sortBy.releaseDate": "发行日期", "term.sortBy.releaseDate": "发行日期",
"term.sortBy.duration": "时长", "term.sortBy.duration": "时长",
"term.sortBy.dateAdded":"加入日期", "term.sortBy.dateAdded": "加入日期",
"term.sortOrder": "字母排序", "term.sortOrder": "字母排序",
"term.sortOrder.ascending": "升序", "term.sortOrder.ascending": "升序",
"term.sortOrder.descending": "倒序", "term.sortOrder.descending": "倒序",
"term.viewAs": "显示模式", "term.viewAs": "显示模式",
"term.viewAs.coverArt": "专辑封面", "term.viewAs.coverArt": "专辑封面",
"term.viewAs.list": "列表", "term.viewAs.list": "列表",
"term.dynamic":"动态", "term.dynamic": "动态",
"term.size": "大小", "term.size": "大小",
"term.size.normal": "正常", "term.size.normal": "正常",
"term.size.compact": "紧凑", "term.size.compact": "紧凑",
@ -106,6 +112,8 @@
"term.time.added": "添加于", "term.time.added": "添加于",
"term.time.released": "发行于", "term.time.released": "发行于",
"term.time.updated": "更新于", "term.time.updated": "更新于",
"term.time.days": "天",
"term.time.day": "天",
"term.time.hours": "小时", "term.time.hours": "小时",
"term.time.hour": "小时", "term.time.hour": "小时",
"term.time.minutes": "分钟", "term.time.minutes": "分钟",
@ -118,8 +126,8 @@
"term.audioSettings": "音频设置", "term.audioSettings": "音频设置",
"term.clearAll": "清空", "term.clearAll": "清空",
"term.recentStations": "最近播放的广播", "term.recentStations": "最近播放的广播",
"term.personalStations":"最近播放的个人广播", "term.personalStations": "最近播放的个人广播",
"term.amLive":"amLive", "term.amLive": "Apple Music Live",
"term.language": "语言", "term.language": "语言",
"term.funLanguages": "恶搞", "term.funLanguages": "恶搞",
"term.noLyrics": "加载中... / 无搜索结果 / 纯音乐", "term.noLyrics": "加载中... / 无搜索结果 / 纯音乐",
@ -133,13 +141,11 @@
"term.contributors": "贡献者", "term.contributors": "贡献者",
"term.equalizer": "均衡器", "term.equalizer": "均衡器",
"term.reset": "重置", "term.reset": "重置",
"term.track": {
"one": "首歌曲",
"other": "首歌曲"
},
"term.tracks": "歌曲", "term.tracks": "歌曲",
"term.track": "首歌曲",
"term.videos": "音乐视频", "term.videos": "音乐视频",
"term.menu": "菜单", "term.menu": "菜单",
"term.themeManaged": "由主题所管理",
"term.check": "检查", "term.check": "检查",
"term.aboutArtist": "关于{{artistName}}", "term.aboutArtist": "关于{{artistName}}",
"term.topResult": "热门搜索结果", "term.topResult": "热门搜索结果",
@ -155,30 +161,47 @@
"term.song.link.generate": "获取 song.link 共享链接...", "term.song.link.generate": "获取 song.link 共享链接...",
"term.musicVideos": "音乐视频", "term.musicVideos": "音乐视频",
"term.stations": "电台", "term.stations": "电台",
"term.curators": "策展人",
"term.appleCurators": "Apple 策展人",
"term.radioShows": "广播单集", "term.radioShows": "广播单集",
"term.recordLabels": "唱片公司", "term.recordLabels": "唱片公司",
"term.videoExtras": "视频特辑", "term.videoExtras": "视频特辑",
"term.top":"顶部", "term.top": "顶部",
"term.version": "版本", "term.version": "版本",
"term.noVideos":"无视频", "term.noVideos": "无视频",
"term.plugins": "插件",
"term.plugin": "插件", "term.plugin": "插件",
"term.pluginMenu": "插件菜单", "term.pluginMenu": "插件菜单",
"term.pluginMenu.none": "沒有交互式插件", "term.pluginMenu.none": "沒有交互式插件",
"term.replay":"音乐回忆", "term.replay": "音乐回忆",
"term.uniqueAlbums":"Unique Albums", "term.uniqueAlbums": "独特专辑",
"term.uniqueArtists":"Unique Artists", "term.uniqueArtists": "超绝艺人",
"term.uniqueSongs":"Unique Songs", "term.uniqueSongs": "别致单曲",
"term.topArtists":"热门艺人", "term.topArtists": "热门艺人",
"term.listenedTo":"听过", "term.listenedTo": "听过",
"term.times":"次", "term.times": "次",
"term.topAlbums":"热门专辑", "term.topAlbums": "热门专辑",
"term.plays":"次", "term.plays": "次",
"term.topGenres":"热门类型", "term.topGenres": "热门类型",
"term.confirmLogout":"你确定要退出登录吗?", "term.confirmLogout": "你确定要退出登录吗?",
"term.creditDesignedBy":"由 ${authorUsername} 设计", "term.creditDesignedBy": "由 ${authorUsername} 设计",
"term.discNumber":"碟 ${discNumber}", "term.discNumber": "碟 ${discNumber}",
"term.reload" : "重新载入 Cider?",
"term.toggleprivate": "切换隐身聆听",
"term.webremote": "远程控制",
"term.cast": "投射",
"term.cast2" : "投射到设备",
"term.quit" : "退出应用",
"term.zoomin" : "放大",
"term.zoomout" : "缩小",
"term.zoomreset" : "重置缩放",
"term.fullscreen" : "全屏模式",
"term.nowPlaying": "正在播放",
"home.syncFavorites": "同步喜爱艺人", "home.syncFavorites": "同步喜爱艺人",
"home.syncFavorites.gettingArtists": "获取喜爱艺人...", "home.syncFavorites.gettingArtists": "获取喜爱艺人...",
"action.favorite": "喜爱",
"action.removeFavorite": "取消喜爱",
"action.refresh": "刷新",
"home.title": "主页", "home.title": "主页",
"home.recentlyPlayed": "最近播放", "home.recentlyPlayed": "最近播放",
"home.recentlyAdded": "最近添加", "home.recentlyAdded": "最近添加",
@ -199,16 +222,15 @@
"podcast.episodes": "单集", "podcast.episodes": "单集",
"podcast.playEpisode": "播放单集", "podcast.playEpisode": "播放单集",
"podcast.website": "Podcast 网站", "podcast.website": "Podcast 网站",
"action.favorite":"喜爱", "action.hideLibrary": "隐藏资料库",
"action.removeFavorite":"取消喜爱", "action.showLibrary": "显示资料库",
"action.hideLibrary":"隐藏资料库", "action.cut": "剪切",
"action.showLibrary":"显示资料可查", "action.paste": "粘贴",
"action.cut":"剪切", "action.selectAll": "全选",
"action.paste":"粘贴", "action.delete": "删除",
"action.selectAll":"全选",
"action.delete":"删除",
"action.edit": "编辑", "action.edit": "编辑",
"action.done": "完成", "action.done": "完成",
"action.submit": "提交",
"action.editTracklist": "编辑歌曲清单", "action.editTracklist": "编辑歌曲清单",
"action.addToLibrary": "加入资料库", "action.addToLibrary": "加入资料库",
"action.addToLibrary.success": "成功加入资料库", "action.addToLibrary.success": "成功加入资料库",
@ -224,7 +246,7 @@
"action.createPlaylist": "新建播放列表", "action.createPlaylist": "新建播放列表",
"action.addToPlaylist": "添加到播放列表", "action.addToPlaylist": "添加到播放列表",
"action.removeFromPlaylist": "从播放列表移除", "action.removeFromPlaylist": "从播放列表移除",
"action.addToFavorites": "加至收藏", "action.addToFavorites": "加至收藏",
"action.follow": "关注", "action.follow": "关注",
"action.follow.success": "已关注", "action.follow.success": "已关注",
"action.follow.error": "尝试关注的过程发生了错误", "action.follow.error": "尝试关注的过程发生了错误",
@ -236,7 +258,7 @@
"action.startRadio": "开始电台", "action.startRadio": "开始电台",
"action.goToArtist": "前往艺人", "action.goToArtist": "前往艺人",
"action.goToAlbum": "前往专辑", "action.goToAlbum": "前往专辑",
"action.showInPlaylist":"在播放列表中显示", "action.showInPlaylist": "在播放列表中显示",
"action.showInAppleMusic": "在 Apple Music 中显示", "action.showInAppleMusic": "在 Apple Music 中显示",
"action.moveToTop": "移到顶部", "action.moveToTop": "移到顶部",
"action.share": "分享歌曲", "action.share": "分享歌曲",
@ -253,11 +275,7 @@
"action.export": "导出", "action.export": "导出",
"action.showAlbum": "显示专辑", "action.showAlbum": "显示专辑",
"action.tray.minimize": "最小化", "action.tray.minimize": "最小化",
"action.tray.quit": "退出",
"action.tray.show": "显示 Cider", "action.tray.show": "显示 Cider",
"action.tray.playpause": "播放/暂停",
"action.tray.next": "下一首",
"action.tray.previous": "上一首",
"action.tray.listento": "Listen To:", "action.tray.listento": "Listen To:",
"action.update": "更新", "action.update": "更新",
"action.install": "安装", "action.install": "安装",
@ -266,7 +284,7 @@
"action.deletepreset": "删除默认", "action.deletepreset": "删除默认",
"action.open": "打开", "action.open": "打开",
"action.close": "关闭", "action.close": "关闭",
"action.relaunch.confirm":"你想重新启动 Cider 吗?", "action.relaunch.confirm": "你想重新启动 Cider 吗?",
"action.cast.chromecast": "Chromecast", "action.cast.chromecast": "Chromecast",
"action.cast.todevices": "投射到设备", "action.cast.todevices": "投射到设备",
"action.cast.stop": "停止投射到所有设备", "action.cast.stop": "停止投射到所有设备",
@ -277,49 +295,29 @@
"action.createNew": "添加...", "action.createNew": "添加...",
"action.openArtworkInBrowser": "在浏览器中打开专辑封面", "action.openArtworkInBrowser": "在浏览器中打开专辑封面",
"action.scrollToTop": "回到顶部", "action.scrollToTop": "回到顶部",
"menubar.options.about": "关于",
"menubar.options.settings": "设置",
"menubar.options.quit": "退出 Cider",
"menubar.options.view": "查看 ", "menubar.options.view": "查看 ",
"menubar.options.reload": "重新载入", "menubar.options.reload": "重新载入",
"menubar.options.forcereload": "强制重新载入", "menubar.options.forcereload": "强制重新载入",
"menubar.options.toggledevtools": "切换开发人员工具", "menubar.options.toggledevtools": "切换开发人员工具",
"menubar.options.window": "窗口", "menubar.options.window": "窗口",
"menubar.options.minimize": "最小化", "menubar.options.minimize": "最小化",
"menubar.options.toggleprivate": "切换隐身聆听",
"menubar.options.webremote": "远程控制",
"menubar.options.audio": "音频设定",
"menubar.options.plugins": "插件目录", "menubar.options.plugins": "插件目录",
"menubar.options.controls": "控制", "menubar.options.controls": "控制",
"menubar.options.next": "下一首",
"menubar.options.playpause": "播放/暂停",
"menubar.options.previous": "上一首",
"menubar.options.volumeup": "增大音量", "menubar.options.volumeup": "增大音量",
"menubar.options.volumedown": "减小音量", "menubar.options.volumedown": "减小音量",
"menubar.options.browse": "浏览",
"menubar.options.artists": "艺人",
"menubar.options.search": "搜索",
"menubar.options.albums": "专辑",
"menubar.options.cast": "投射至设备",
"menubar.options.account": "账户", "menubar.options.account": "账户",
"menubar.options.accountsettings": "账户设置",
"menubar.options.signout": "注销", "menubar.options.signout": "注销",
"menubar.options.support": "支持", "menubar.options.support": "支持",
"menubar.options.discord": "Discord",
"menubar.options.github": "GitHub Wiki",
"menubar.options.report": "报告...", "menubar.options.report": "报告...",
"menubar.options.bug": "Bug", "menubar.options.bug": "Bug",
"menubar.options.feature": "功能请求", "menubar.options.feature": "功能请求",
"menubar.options.trans": "翻译报告/请求", "menubar.options.trans": "翻译报告/请求",
"menubar.options.license": "查看授权", "menubar.options.license": "查看授权",
"menubar.options.conf": "在编辑器打开配置文件", "menubar.options.conf": "在编辑器打开配置文件",
"menubar.options.listennow": "现在就听", "menubar.options.zoom": "缩放",
"menubar.options.recentlyAdded": "最近添加",
"menubar.options.songs": "歌曲",
"settings.header.general": "通用", "settings.header.general": "通用",
"settings.header.general.description": "调整 Cider 的通用设置", "settings.header.general.description": "调整 Cider 的通用设置",
"settings.option.audio.volumeStep": "音量改变量", "settings.option.general.language": "语言",
"settings.option.audio.maxVolume": "最大音量",
"settings.option.general.resumebehavior": "恢复行为", "settings.option.general.resumebehavior": "恢复行为",
"settings.option.general.resumebehavior.description": "会影响你回到 Cider 应用程序时,恢复歌曲的方式。", "settings.option.general.resumebehavior.description": "会影响你回到 Cider 应用程序时,恢复歌曲的方式。",
"settings.option.general.resumebehavior.locally": "本地", "settings.option.general.resumebehavior.locally": "本地",
@ -330,61 +328,66 @@
"settings.option.general.resumetabs.description": "你可以选择启动 Cider 时要默认打开的页面。", "settings.option.general.resumetabs.description": "你可以选择启动 Cider 时要默认打开的页面。",
"settings.option.general.resumetabs.dynamic": "动态", "settings.option.general.resumetabs.dynamic": "动态",
"settings.option.general.resumetabs.dynamic.description": "Cider 将自动打开你上次停留的页面。", "settings.option.general.resumetabs.dynamic.description": "Cider 将自动打开你上次停留的页面。",
"settings.option.general.language": "语言",
"settings.option.general.language.main": "语言", "settings.option.general.language.main": "语言",
"settings.option.general.language.fun": "恶搞语言", "settings.option.general.language.fun": "恶搞语言",
"settings.option.general.language.unsorted": "未分类", "settings.option.general.language.unsorted": "未分类",
"settings.option.general.customizeSidebar": "自定义侧边栏的功能", "settings.option.general.customizeSidebar": "自定义侧边栏的功能",
"settings.option.general.customizeSidebar.customize": "自定义", "settings.option.general.customizeSidebar.customize": "自定义",
"settings.option.general.keybindings": "快捷操作键", "settings.option.general.keybindings": "快捷操作键",
"settings.option.general.keybindings.pressCombination":"按下两个键组合来更新操作设定。", "settings.option.general.keybindings.library": "资料库",
"settings.option.general.keybindings.session": "聆听",
"settings.option.general.keybindings.control": "控制",
"settings.option.general.keybindings.interface": "界面",
"settings.option.general.keybindings.advanced": "高级",
"settings.option.general.keybindings.pressCombination": "按下两个键组合来更新操作设定。",
"settings.option.general.keybindings.pressEscape": "按下 Esc 键返回。", "settings.option.general.keybindings.pressEscape": "按下 Esc 键返回。",
"settings.notyf.general.keybindings.update.success":"快捷键更新成功。", "settings.notyf.general.keybindings.update.success": "快捷键更新成功。",
"settings.prompt.general.keybindings.update.success":"快捷键更新成功,按下 OK 重新启动 Cider.", "settings.prompt.general.keybindings.update.success": "快捷键更新成功,按下 OK 重新启动 Cider。",
"settings.option.general.keybindings.open": "打开", "settings.option.general.themeUpdateNotification": "自动检查主题更新",
"settings.option.general.themeUpdateNotification":"自动检查主题更新", "settings.option.general.showLovedTracksInline": "行内显示喜爱曲目",
"settings.option.general.showLovedTracksInline":"行内显示喜爱曲目", "settings.description.search": "搜索",
"settings.description.search":"搜索", "settings.description.albums": "资料库专辑",
"settings.description.albums":"资料库专辑", "settings.description.artists": "资料库艺人",
"settings.description.artists":"资料库艺人", "settings.description.browse": "浏览",
"settings.description.browse":"浏览", "settings.description.private": "隐身聆听",
"settings.description.private":"隐身聆听", "settings.description.remote": "远程控制",
"settings.description.remote":"远程控制", "settings.description.audio": "音频设定",
"settings.description.audio":"音频设定", "settings.description.plugins": "插件目录",
"settings.description.plugins":"插件目录", "settings.description.cast": "投射到装置",
"settings.description.cast":"投射到装置", "settings.description.settings": "设置",
"settings.description.settings":"设置", "settings.description.developer": "开发者",
"settings.description.developer":"开发者", "settings.description.listnow": "现在就听",
"settings.description.listnow":"现在就听", "settings.description.recentAdd": "最近加入",
"settings.description.recentAdd":"最近加入", "settings.description.songs": "歌曲",
"settings.description.songs":"歌曲",
"settings.notyf.updateCider.update-not-available": "没有可用的更新", "settings.notyf.updateCider.update-not-available": "没有可用的更新",
"settings.notyf.updateCider.update-downloaded": "更新已成功下载,重启后进行更新", "settings.notyf.updateCider.update-downloaded": "更新已成功下载,重启后进行更新",
"settings.notyf.updateCider.update-timeout": "更新超时", "settings.notyf.updateCider.update-timeout": "更新超时",
"settings.header.audio": "音频", "settings.header.audio": "音频",
"settings.header.audio.description": "调整 Cider 的音频设置", "settings.header.audio.description": "调整 Cider 的音频设置",
"settings.option.audio.advanced":"高级功能", "settings.option.audio.volumeStep": "音量改变量",
"settings.option.audio.changePlaybackRate":"修改播放速度", "settings.option.audio.advanced": "高级功能",
"settings.option.audio.playbackRate":"播放速度", "settings.option.audio.maxVolume": "最大音量",
"settings.option.audio.playbackRate.change":"修改", "settings.option.audio.changePlaybackRate": "修改播放速度",
"settings.option.audio.playbackRate": "播放速度",
"settings.option.audio.playbackRate.change": "修改",
"settings.option.audio.quality": "音质", "settings.option.audio.quality": "音质",
"settings.header.audio.quality.hireslossless": "高解析度无损", "settings.header.audio.quality.hireslossless": "高解析度无损",
"settings.header.audio.quality.hireslossless.description": "(最高 24 位/192 kHz)", "settings.header.audio.quality.hireslossless.description": "(最高 24 位/192 kHz)",
"settings.header.audio.quality.lossless": "无损", "settings.header.audio.quality.lossless": "无损",
"settings.header.audio.quality.lossless.description": "(最高 24 位/48 kHz)", "settings.header.audio.quality.lossless.description": "(最高 24 位/48 kHz)",
"settings.header.audio.quality.high": "高音质", "settings.header.audio.quality.high": "高音质",
"settings.header.audio.quality.high.description":"256 kbps", "settings.header.audio.quality.high.description": "256 kbps",
"settings.header.audio.quality.standard": "高效率", "settings.header.audio.quality.standard": "高效率",
"settings.header.audio.quality.standard.description":"64 kbps", "settings.header.audio.quality.standard.description": "64 kbps",
"settings.option.audio.seamlessTransition": "无缝播放", "settings.option.audio.seamlessTransition": "无缝播放",
"settings.option.audio.enableAdvancedFunctionality": "高级音频功能", "settings.option.audio.enableAdvancedFunctionality": "高级音频功能",
"settings.option.audio.enableAdvancedFunctionality.description": "打开 AudioContext 将启用类似音量平衡和等化器的高级设置。但这并不一定适合每部电脑,可能会发生音乐卡顿。", "settings.option.audio.enableAdvancedFunctionality.description": "打开 AudioContext 将启用类似音量平衡和等化器的高级设置。但这并不一定适合每部电脑,可能会发生音乐卡顿。",
"settings.warn.audio.enableAdvancedFunctionality.lowcores":"您的电脑可能无法处理这些功能, 您确定要继续?", "settings.warn.audio.enableAdvancedFunctionality.lowcores": "您的电脑可能无法处理这些功能, 您确定要继续?",
"settings.option.audio.audioLab": "Cider 音频实验室", "settings.option.audio.audioLab": "Cider 音频实验室",
"settings.option.audio.audioLab.description": "包含由 Cider 开发团队进行的各种音频优化功能。", "settings.option.audio.audioLab.description": "包含由 Cider 开发团队进行的各种音频优化功能。",
"settings.option.audio.audioLab.subheader":"Designed by Cider Acoustic Technologies in California", "settings.option.audio.audioLab.subheader": "Designed by Cider Acoustic Technologies in California",
"settings.warn.audioLab.withoutAF": "使用 Cider 音频实验室需要打开进阶音频功能才可使用。", "settings.warn.audioLab.withoutAF": "使用 Cider 音频实验室需要打开进阶音频功能才可使用。",
"settings.warn.enableAdvancedFunctionality":"此功能需要开启高级音频功能才可使用。", "settings.warn.enableAdvancedFunctionality": "此功能需要开启高级音频功能才可使用。",
"settings.option.audio.enableAdvancedFunctionality.analogWarmth": "模拟温暖", "settings.option.audio.enableAdvancedFunctionality.analogWarmth": "模拟温暖",
"settings.option.audio.enableAdvancedFunctionality.analogWarmth.description": "以 Korg Nutube 6P1 为蓝本的模拟温暖。", "settings.option.audio.enableAdvancedFunctionality.analogWarmth.description": "以 Korg Nutube 6P1 为蓝本的模拟温暖。",
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity": "模拟温暖强度", "settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity": "模拟温暖强度",
@ -401,18 +404,20 @@
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.E68_2": "宇治抹茶奶茶", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.E68_2": "宇治抹茶奶茶",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.E168_1": "春毫茉莉玛琪雅朵", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.E168_1": "春毫茉莉玛琪雅朵",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z3600": "北海道奶茶", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z3600": "北海道奶茶",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500": "月光软饼干", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500A": "月光软饼干",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.BSCBM":"布蕾黑糖鲜奶", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.BSCBM": "布蕾黑糖鲜奶",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.CUDDLE":"温暖抱抱", "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500B": "樱桃克拉芙缇",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.Z8500C": "宇治抹茶麻糬",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.CUDDLE": "温暖抱抱",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider 数码增强音频处理™️", "settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider 数码增强音频处理™️",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "通过人类的听力心理学模型和 AAC 编码特色的即时算法,强化 AAC 音频的感知音频质量。", "settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "通过人类的听力心理学模型和 AAC 编码特色的即时算法,强化 AAC 音频的感知音频质量。",
"settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility": "数码增强音频处理与空间音频不兼容,请先停用空间音频。",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength": "数码增强音频处理设置", "settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength": "数码增强音频处理设置",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.description": "将更改音频处理的激进/振奋程度(增强选项有可能会引起杂讯)。", "settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.description": "将更改音频处理的激进/振奋程度(增强选项有可能会引起杂讯)。",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.standard": "标准", "settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.standard": "标准",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.adaptive":"自适应", "settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.adaptive": "自适应",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.legacy":"传统", "settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.legacy": "传统",
"settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.aggressive": "增强", "settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.aggressive": "增强",
"settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility":"数码增强音频处理与空间音频不兼容,请先停用空间音频。",
"settings.option.audio.enableAdvancedFunctionality.audioNormalization": "音量平衡", "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "音量平衡",
"settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "自动将歌曲播放音量调整到相同水平,享受更舒适的聆听体验。", "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "自动将歌曲播放音量调整到相同水平,享受更舒适的聆听体验。",
"settings.option.audio.enableAdvancedFunctionality.audioNormalization.disabled": "此功能由音频实验室管理", "settings.option.audio.enableAdvancedFunctionality.audioNormalization.disabled": "此功能由音频实验室管理",
@ -421,28 +426,25 @@
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile": "Cider 音频空间配置档", "settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile": "Cider 音频空间配置档",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.description": "变更音频空间的配置档,需重新启动应用程序。", "settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.description": "变更音频空间的配置档,需重新启动应用程序。",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.standard": "标准", "settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.standard": "标准",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.soundstage":"声场", "settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.soundstage": "声场",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.separation":"分离感", "settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.separation": "分离感",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.minimal":"微调", "settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.minimal": "微调",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.audiophile": "发烧友", "settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.audiophile": "发烧友",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.diffused": "扩散",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.bplk": "安可",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.hw2k": "延长版安可",
"settings.warn.audio.enableAdvancedFunctionality.audioSpatialization.compatibility": "音频空间无法与 CAP 相容,请关闭 CAP 在进行操作。", "settings.warn.audio.enableAdvancedFunctionality.audioSpatialization.compatibility": "音频空间无法与 CAP 相容,请关闭 CAP 在进行操作。",
"settings.option.audio.dbspl.display":"显示 dB SPL(声压)", "settings.option.audio.dbspl.display": "显示 dB SPL(声压)",
"settings.option.audio.dbspl.description":"(专业用户选项) 音量滑动条显示 dB SPL 而非 dBFS.", "settings.option.audio.dbspl.description": "(专业用户选项) 音量滑动条显示 dB SPL 而非 dBFS。",
"settings.option.audio.dbfs.calibration":"0 dBFS 校正", "settings.option.audio.dbfs.calibration": "0 dBFS 校正",
"settings.option.audio.dbfs.description":"Enter the peak Z-weighted dB SPL when Cider is at 0 dBFS.", "settings.option.audio.dbfs.description": "输入当 Cider 为 0 dBFS 时的峰值 Z 加权 dB SPL。",
"settings.option.visual.uiscale": "UI界面大小",
"settings.header.visual": "外观", "settings.header.visual": "外观",
"settings.header.visual.description": "调整 Cider 的外观", "settings.header.visual.description": "调整 Cider 的外观",
"settings.option.visual.windowStyle":"窗口风格", "settings.option.visual.windowStyle": "窗口风格",
"settings.option.visual.customAccentColor": "自定义强调色",
"settings.option.visual.accentColor": "强调色",
"settings.option.visual.purplePodcastPlaybackBar": "播放播客时使用紫色进度条",
"settings.option.visual.windowColor": "窗口色调",
"settings.option.visual.windowBackgroundStyle": "窗口背景样式", "settings.option.visual.windowBackgroundStyle": "窗口背景样式",
"settings.header.visual.windowBackgroundStyle.none": "无", "settings.header.visual.windowBackgroundStyle.none": "无",
"settings.header.visual.windowBackgroundStyle.artwork": "专辑插图", "settings.header.visual.windowBackgroundStyle.artwork": "专辑插图",
"settings.header.visual.windowBackgroundStyle.image": "图像", "settings.header.visual.windowBackgroundStyle.image": "图像",
"settings.header.visual.windowBackgroundStyle.color":"色调",
"settings.option.visual.animatedArtwork": "动态专辑插图", "settings.option.visual.animatedArtwork": "动态专辑插图",
"settings.header.visual.animatedArtwork.always": "总是显示", "settings.header.visual.animatedArtwork.always": "总是显示",
"settings.header.visual.animatedArtwork.limited": "只在艺人页面和专辑插图显示", "settings.header.visual.animatedArtwork.limited": "只在艺人页面和专辑插图显示",
@ -458,20 +460,22 @@
"settings.option.visual.hardwareAcceleration.description": "需要重启 Cider 才会生效", "settings.option.visual.hardwareAcceleration.description": "需要重启 Cider 才会生效",
"settings.header.visual.hardwareAcceleration.default": "默认", "settings.header.visual.hardwareAcceleration.default": "默认",
"settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU",
"settings.option.visual.uiscale": "UI界面大小",
"settings.header.visual.theme": "主题", "settings.header.visual.theme": "主题",
"settings.option.visual.theme.github.download": "从 GitHub 链接安装", "settings.option.visual.theme.github.download": "从 GitHub 链接安装",
"settings.option.visual.theme.github.openfolder":"开启主题文件夹", "settings.option.visual.theme.github.openfolder": "开启主题文件夹",
"settings.option.visual.theme.github.explore": "浏览 GitHub 上的主题", "settings.option.visual.theme.github.explore": "浏览 GitHub 上的主题",
"settings.header.visual.theme.github.page":"GitHub 上的主题", "settings.header.visual.theme.github.page": "GitHub 上的主题",
"settings.option.visual.theme.github.install.confirm":"你确定要安装 {{ repo }}", "settings.option.visual.theme.github.install.confirm": "你确定要安装 {{ repo }}",
"settings.prompt.visual.theme.github.URL": "输入您要安装的窗口主题链接", "settings.prompt.visual.theme.github.URL": "输入您要安装的窗口主题链接",
"settings.prompt.visual.theme.uninstallTheme":"你确定要删除 {{ theme }}", "settings.prompt.visual.theme.uninstallTheme": "你确定要删除 {{ theme }}",
"settings.option.visual.theme.checkForUpdates":"检查更新", "settings.option.visual.theme.checkForUpdates": "检查更新",
"settings.option.visual.theme.manageStyles":"管理风格", "settings.header.visual.styles": "主题",
"settings.option.visual.theme.uninstall":"卸载", "settings.option.visual.theme.manageStyles": "管理主题",
"settings.option.visual.theme.viewInfo":"查看信息", "settings.option.visual.theme.uninstall": "卸载",
"settings.option.visual.theme.github.available":"可使用的主题", "settings.option.visual.theme.viewInfo": "查看信息",
"settings.option.visual.theme.github.applied":"已应用", "settings.option.visual.theme.github.available": "可使用的主题",
"settings.option.visual.theme.github.applied": "已应用",
"settings.notyf.visual.theme.install.success": "主题成功安装", "settings.notyf.visual.theme.install.success": "主题成功安装",
"settings.notyf.visual.theme.install.error": "主题安装失败", "settings.notyf.visual.theme.install.error": "主题安装失败",
"settings.header.visual.plugin": "插件", "settings.header.visual.plugin": "插件",
@ -503,21 +507,27 @@
"settings.option.lyrics.enableQQLyrics": "启用 QQ 音乐的歌词", "settings.option.lyrics.enableQQLyrics": "启用 QQ 音乐的歌词",
"settings.header.connectivity": "外部连接", "settings.header.connectivity": "外部连接",
"settings.header.connectivity.description": "调整 Cider 与外部应用的交互设置", "settings.header.connectivity.description": "调整 Cider 与外部应用的交互设置",
"settings.option.connectivity.discordRPC": "Discord 动态",
"settings.option.connectivity.playbackNotifications": "歌曲播放通知", "settings.option.connectivity.playbackNotifications": "歌曲播放通知",
"settings.option.connectivity.discordRPC": "Discord 动态",
"settings.option.connectivity.discordRPC.clientName": "应用程序名称", "settings.option.connectivity.discordRPC.clientName": "应用程序名称",
"settings.option.connectivity.discordRPC.clearOnPause": "暂停时清除 Discord 动态", "settings.option.connectivity.discordRPC.clearOnPause": "暂停时清除 Discord 动态",
"settings.option.connectivity.discordRPC.hideButtons": "隐藏 Discord 动态上的按钮", "settings.option.connectivity.discordRPC.hideButtons": "隐藏 Discord 动态上的按钮",
"settings.option.connectivity.discordRPC.hideTimestamp":"隐藏 Discord 动态上的时间戳", "settings.option.connectivity.discordRPC.hideTimestamp": "隐藏 Discord 动态上的时间戳",
"settings.option.connectivity.discordRPC.detailsFormat": "详细信息格式", "settings.option.connectivity.discordRPC.detailsFormat": "详细信息格式",
"settings.option.connectivity.discordRPC.stateFormat": "动态格式", "settings.option.connectivity.discordRPC.stateFormat": "动态格式",
"settings.option.connectivity.discordRPC.reload":"重新加载 DiscordRPC", "settings.option.connectivity.discordRPC.reload": "重新加载 DiscordRPC",
"settings.option.connectivity.discordRPC.reconnectedToUser":"DiscordRPC 重新连接至用户: {{user}} ({{userid}})", "settings.option.connectivity.discordRPC.reconnectedToUser": "DiscordRPC 重新连接至用户: {{user}} ({{userid}})",
"settings.option.connectivity.lastfmScrobble": "Last.FM 音乐记录", "settings.option.connectivity.lastfmScrobble": "Last.FM 音乐记录",
"settings.option.connectivity.lastfmScrobble.delay": "Last.FM 歌曲追踪延迟 (%)", "settings.option.connectivity.lastfmScrobble.delay": "Last.FM 歌曲追踪延迟 (%)",
"settings.option.connectivity.lastfmScrobble.nowPlaying": "打开 Last.FM 正在聆听", "settings.option.connectivity.lastfmScrobble.nowPlaying": "打开 Last.FM 正在聆听",
"settings.option.connectivity.lastfmScrobble.removeFeatured": "从歌名里去除合作者 (Last.FM)", "settings.option.connectivity.lastfmScrobble.removeFeatured": "从歌名里去除合作者 (Last.FM)",
"settings.option.connectivity.lastfmScrobble.filterLoop": "不记录单曲循环 (Last.FM)", "settings.option.connectivity.lastfmScrobble.filterLoop": "不记录单曲循环 (Last.FM)",
"settings.option.connectivity.lastfmScrobble.filterLoop.description": "防止循环单曲被记录或展示在Last.FM 的正在播放列表中。",
"settings.option.connectivity.lastfmScrobble.filterTypes": "过滤媒体类型 (Last.fm)",
"settings.option.connectivity.lastfmScrobble.manualToken": "手动输入 Last.fm 验证码",
"settings.notyf.connectivity.lastfmScrobble.connectError": "Last.fm 连接超时",
"settings.notyf.connectivity.lastfmScrobble.connectSuccess": "Last.fm 连接成功",
"settings.notyf.connectivity.lastfmScrobble.connecting": "正在连接至 Last.fm...",
"settings.header.debug": "Debug", "settings.header.debug": "Debug",
"settings.option.debug.copy_log": "拷贝日志至剪贴板", "settings.option.debug.copy_log": "拷贝日志至剪贴板",
"settings.option.debug.openAppData": "打开 Cider 程序文件夹", "settings.option.debug.openAppData": "打开 Cider 程序文件夹",
@ -529,15 +539,21 @@
"settings.option.experimental.unknownPlugin.description": "允许从 Cider 来源以外的 repo 安装插件", "settings.option.experimental.unknownPlugin.description": "允许从 Cider 来源以外的 repo 安装插件",
"settings.option.experimental.compactUI": "紧凑型 UI", "settings.option.experimental.compactUI": "紧凑型 UI",
"settings.option.window.close_button_hide": "关闭按钮将 Cider 隐藏至系统栏", "settings.option.window.close_button_hide": "关闭按钮将 Cider 隐藏至系统栏",
"settings.option.window.maxElementScale": "最大元素比例",
"settings.option.experimental.inline_playlists": "将播放列表做为行内元素显示", "settings.option.experimental.inline_playlists": "将播放列表做为行内元素显示",
"settings.option.advanced.playlistTrackMapping": "播放列表追踪映射", "settings.option.advanced.playlistTrackMapping": "播放列表追踪映射",
"settings.option.advanced.playlistTrackMapping.description": "打开对播放列表的深度扫描,以确认歌曲在哪些播放列表中。但播放列表加载时间会显著增加。", "settings.option.advanced.playlistTrackMapping.description": "打开对播放列表的深度扫描,以确认歌曲在哪些播放列表中。但播放列表加载时间会显著增加。",
"settings.option.visual.transparent": "透明窗口框架", "settings.option.visual.transparent": "透明窗口框架",
"settings.option.visual.transparent.description": "需主题有支持透明框架,且须重新启动才会生效。", "settings.option.visual.transparent.description": "需主题有支持透明框架,且须重新启动才会生效。",
"settings.option.visual.customAccentColor": "自定义强调色",
"settings.option.visual.accentColor": "强调色",
"settings.option.visual.purplePodcastPlaybackBar": "播放播客时使用紫色进度条",
"settings.option.visual.windowColor": "窗口色调",
"settings.header.visual.windowBackgroundStyle.color": "色调",
"settings.header.advanced": "高级", "settings.header.advanced": "高级",
"settings.header.connect":"同步", "settings.header.connect": "同步",
"settings.option.connect.link_account":"开启 Cider Connect 同步", "settings.option.connect.link_account": "开启 Cider Connect 同步",
"settings.option.connect.link_account.description":"将您的 Discord 帐户与 Cider Connect 关联后,您可以储存用户资料,包括设定、均衡器,并在后续版本中加入更多可同步选项。(正在更新中)", "settings.option.connect.link_account.description": "将您的 Discord 帐户与 Cider Connect 关联后,您可以储存用户资料,包括设定、均衡器,并在后续版本中加入更多可同步选项。(正在更新中)",
"spatial.notTurnedOn": "请在设置中开启空间音频。", "spatial.notTurnedOn": "请在设置中开启空间音频。",
"spatial.spatialProperties": "空间属性", "spatial.spatialProperties": "空间属性",
"spatial.width": "宽度", "spatial.width": "宽度",
@ -560,54 +576,54 @@
"settings.header.unfinished": "未完成", "settings.header.unfinished": "未完成",
"remote.web.title": "Cider 远程控制", "remote.web.title": "Cider 远程控制",
"remote.web.description": "扫描以下的二维码以控制 Cider", "remote.web.description": "扫描以下的二维码以控制 Cider",
"share.platform.twitter.tweet": "在 Apple Music 上聆听 {{song}}。 \n\n{{url}}\n\n#AppleMusic #Cider",
"share.platform.twitter": "Twitter",
"share.platform.facebook": "Facebook",
"share.platform.reddit": "Reddit",
"share.platform.telegram": "Telegram",
"share.platform.whatsapp": "WhatsApp",
"share.platform.messenger": "Messenger",
"share.platform.email": "电子邮件",
"share.platform.songLink": "复制 song.link 链接",
"share.platform.clipboard": "复制到剪贴板",
"about.thanks": "郑重感谢 Cider Collective 以及为这个项目提供支持的贡献者。", "about.thanks": "郑重感谢 Cider Collective 以及为这个项目提供支持的贡献者。",
"share.platform.twitter.tweet":"在 Apple Music 上聆听 {{song}}。 \n\n{{url}}\n\n#AppleMusic #Cider", "oobe.yes": "好的",
"share.platform.twitter":"Twitter", "oobe.no": "不",
"share.platform.facebook":"Facebook", "oobe.next": "下一步",
"share.platform.reddit":"Reddit", "oobe.previous": "上一步",
"share.platform.telegram":"Telegram", "oobe.done": "完成",
"share.platform.whatsapp":"WhatsApp", "oobe.amupsell.title": "在我们开始之前",
"share.platform.messenger":"Messenger", "oobe.amupsell.text": "使用 Cider 需要付费的 Apple Music 订阅。\nCider 不能在 Apple Music Voice 计划或某些促销试用订阅状态下使用。 如果您已经订阅 Apple Music请点击下一步继续。",
"share.platform.email":"电子邮件", "oobe.amupsell.subscribeBtn": "订阅 Apple Music",
"share.platform.songLink":"复制 song.link 链接", "oobe.amupsell.explainBtn": "这是什么?",
"share.platform.clipboard":"复制到剪贴板", "oobe.amupsell.subscribeUrl": "https://apple.co/3MdqJVQ",
"oobe.yes":"好的", "oobe.amupsell.amWebUrl": "https://beta.music.apple.com/",
"oobe.no":"不", "oobe.amupsell.promoExplained": "Cider 无法获取部分促销活动与非美区 Apple Muisc 试用状态下的网络播放器API. 要验证您的试用订阅是否能够在Cider内使用, 点击<a href='{{ amWebUrl }}'>{{ amWebUrl }}</a>, 登陆后尝试播放音乐。如果能够播放,您就可以使用 Cider 了!否则请考虑订阅 Apple Music 服务: <a href='{{ subscribeUrl }}'>{{ subscribeUrl }}</a>。",
"oobe.next":"下一步", "oobe.intro.title": "欢迎使用 Cider",
"oobe.previous":"上一步", "oobe.intro.subtitle": "",
"oobe.done":"完成", "oobe.intro.text": "为了按您喜欢的方式使用 Cider ,请先完成一些设置。您之后可以随时改变这些设置。",
"oobe.amupsell.title":"在我们开始之前", "oobe.general.title": "通用设置",
"oobe.amupsell.text":"使用 Cider 需要付费的 Apple Music 订阅。\nCider 不能在 Apple Music Voice 计划或某些促销试用订阅状态下使用。 如果您已经订阅 Apple Music请点击下一步继续。", "oobe.general.subtitle": "",
"oobe.amupsell.subscribeBtn":"订阅 Apple Music", "oobe.general.text": "",
"oobe.amupsell.explainBtn":"这是什么?", "oobe.audio.title": "音频设置",
"oobe.amupsell.subscribeUrl":"https://apple.co/3MdqJVQ", "oobe.audio.subtitle": "",
"oobe.amupsell.amWebUrl":"https://beta.music.apple.com/", "oobe.audio.text": "Cider 能够自定义调整和设置的音频属性提供丰富的高品质音频体验包括Cider Adrenaline Processor气氛实现器和空间音频。要启用这些功能必须启用 \"高级音频功能\"。",
"oobe.amupsell.promoExplained":"Cider 无法获取部分促销活动与非美区 Apple Muisc 试用状态下的网络播放器API. 要验证您的试用订阅是否能够在Cider内使用, 点击<a href='{{ amWebUrl }}'>{{ amWebUrl }}</a>, 登陆后尝试播放音乐。如果能够播放,您就可以使用 Cider 了!否则请考虑订阅 Apple Music 服务: <a href='{{ subscribeUrl }}'>{{ subscribeUrl }}</a>。", "oobe.audio.advancedFunctionality": "",
"oobe.intro.title":"欢迎使用 Cider", "oobe.visual.title": "外观设置",
"oobe.intro.subtitle":"", "oobe.visual.subtitle": "",
"oobe.intro.text":"为了按您喜欢的方式使用 Cider ,请先完成一些设置。您之后可以随时改变这些设置。", "oobe.visual.text": "",
"oobe.general.title":"通用设置", "oobe.visual.layout.text": "Cider 拥有两种不同的窗口布局。Maverick 是一个类似 iTunes 的布局播放器在窗口的顶部。Mojave 是由 Cider 团队设计的一种新的布局。您可以在设置中随时改变布局。",
"oobe.general.subtitle":"", "oobe.visual.suggestingThemes": "主题能够个性化您的播放器。以下是推荐的几个主题:",
"oobe.general.text":"", "oobe.visual.suggestingThemes.subtext": "(主题会从 GitHub 上下载)",
"oobe.audio.title":"音频设置", "oobe.visual.suggestingThemes.default": "Cider",
"oobe.audio.subtitle":"", "oobe.visual.suggestingThemes.default.text": "经典的 Cider 主题。",
"oobe.audio.text":"Cider 能够自定义调整和设置的音频属性提供丰富的高品质音频体验包括Cider Adrenaline Processor气氛实现器和空间音频。要启用这些功能必须启用 \"高级音频功能\"。", "oobe.visual.suggestingThemes.dark": "Dark",
"oobe.audio.advancedFunctionality":"", "oobe.visual.suggestingThemes.dark.text": "暗黑模式。",
"oobe.visual.title":"外观设置", "oobe.visual.suggestingThemes.community1": "Groovy",
"oobe.visual.subtitle":"", "oobe.visual.suggestingThemes.community1.text": "类 WinUI 主题。",
"oobe.visual.text":"", "oobe.visual.suggestingThemes.community2": "iTheme",
"oobe.visual.layout.text":"Cider 拥有两种不同的窗口布局。Maverick 是一个类似 iTunes 的布局播放器在窗口的顶部。Mojave 是由 Cider 团队设计的一种新的布局。您可以在设置中随时改变布局。", "oobe.visual.suggestingThemes.community2.text": "经典的苹果风主题。",
"oobe.visual.suggestingThemes":"主题能够个性化您的播放器。以下是推荐的几个主题:", "oobe.visual.suggestingThemes.community3": "Dracula",
"oobe.visual.suggestingThemes.subtext":"(主题会从 GitHub 上下载)", "oobe.visual.suggestingThemes.community3.text": "著名的德古拉吸血鬼主题。",
"oobe.visual.suggestingThemes.default":"Cider",
"oobe.visual.suggestingThemes.default.text":"传统的 Cider 主题。",
"oobe.visual.suggestingThemes.dark":"Dark",
"oobe.visual.suggestingThemes.dark.text":"暗黑模式。",
"oobe.visual.suggestingThemes.community1":"Groovy",
"oobe.visual.suggestingThemes.community1.text":"类 WinUI 主题。",
"oobe.visual.suggestingThemes.community2":"iTheme",
"oobe.visual.suggestingThemes.community2.text":"基于 MacOS Monterey 的 Apple Music bata 主题。",
"oobe.visual.suggestingThemes.community3":"Dracula",
"oobe.visual.suggestingThemes.community3.text":"著名的德古拉吸血鬼主题。",
"oobe.amsignin.title": "" "oobe.amsignin.title": ""
} }

View file

@ -135,6 +135,7 @@
"term.videos": "音樂錄影帶", "term.videos": "音樂錄影帶",
"term.menu": "選單", "term.menu": "選單",
"term.check": "檢查", "term.check": "檢查",
"term.themeManaged": "此功能現在由主題管理。",
"term.aboutArtist": "關於{{artistName}}", "term.aboutArtist": "關於{{artistName}}",
"term.requestError": "請求發生錯誤。", "term.requestError": "請求發生錯誤。",
"term.song.link.generate": "正在取得 song.link 的分享網址...", "term.song.link.generate": "正在取得 song.link 的分享網址...",
@ -142,8 +143,10 @@
"term.version": "版本", "term.version": "版本",
"term.creditDesignedBy": "由 ${authorUsername} 設計", "term.creditDesignedBy": "由 ${authorUsername} 設計",
"term.plugin": "模組", "term.plugin": "模組",
"term.plugins": "模組",
"term.pluginMenu": "模組選單", "term.pluginMenu": "模組選單",
"term.pluginMenu.none": "沒有交互式模組", "term.pluginMenu.none": "沒有交互式模組",
"term.fullscreen" : "全螢幕模式",
"home.title": "首頁", "home.title": "首頁",
"home.recentlyPlayed": "最近播放", "home.recentlyPlayed": "最近播放",
"home.recentlyAdded": "最近加入", "home.recentlyAdded": "最近加入",
@ -232,6 +235,7 @@
"action.cast.scanning": "尋找中...", "action.cast.scanning": "尋找中...",
"action.createNew": "新增...", "action.createNew": "新增...",
"action.refresh": "重新整理", "action.refresh": "重新整理",
"menubar.options.reload": "重新載入",
"settings.header.general": "一般", "settings.header.general": "一般",
"settings.header.general.description": "調整 Cider 的一般設定", "settings.header.general.description": "調整 Cider 的一般設定",
"settings.option.general.resumebehavior": "還原行為", "settings.option.general.resumebehavior": "還原行為",
@ -345,6 +349,7 @@
"settings.option.visual.theme.github.explore": "探索 GitHub 上的主題", "settings.option.visual.theme.github.explore": "探索 GitHub 上的主題",
"settings.prompt.visual.theme.github.URL": "輸入你要安裝的主題網址", "settings.prompt.visual.theme.github.URL": "輸入你要安裝的主題網址",
"settings.option.visual.theme.checkForUpdates": "檢查更新", "settings.option.visual.theme.checkForUpdates": "檢查更新",
"settings.header.visual.styles": "主題",
"settings.option.visual.theme.manageStyles": "管理主題", "settings.option.visual.theme.manageStyles": "管理主題",
"settings.option.visual.theme.uninstall": "移除", "settings.option.visual.theme.uninstall": "移除",
"settings.option.visual.theme.viewInfo": "查看資訊", "settings.option.visual.theme.viewInfo": "查看資訊",
@ -366,6 +371,7 @@
"settings.option.visual.showPersonalInfo": "顯示個人檔案", "settings.option.visual.showPersonalInfo": "顯示個人檔案",
"settings.header.window": "視窗", "settings.header.window": "視窗",
"settings.header.window.description": "調整 Cider 的視窗設定", "settings.header.window.description": "調整 Cider 的視窗設定",
"settings.option.window.maxElementScale": "最大元素比例",
"settings.option.window.openOnStartup": "開機時,啟動 Cider ", "settings.option.window.openOnStartup": "開機時,啟動 Cider ",
"settings.option.window.openOnStartup.hidden": "啟動時,自動隱藏至系統列", "settings.option.window.openOnStartup.hidden": "啟動時,自動隱藏至系統列",
"settings.option.window.useNativeTitleBar": "使用原生視窗標題列", "settings.option.window.useNativeTitleBar": "使用原生視窗標題列",

View file

@ -64,7 +64,7 @@ export class BrowserWindow {
"pages/groupings", "pages/groupings",
"pages/charts", "pages/charts",
"pages/settings", "pages/settings",
"pages/installed-themes", //"pages/installed-themes",
"pages/listen_now", "pages/listen_now",
"pages/radio", "pages/radio",
"pages/home", "pages/home",
@ -80,13 +80,12 @@ export class BrowserWindow {
"pages/about", "pages/about",
"pages/library-videos", "pages/library-videos",
"pages/remote-pair", "pages/remote-pair",
"pages/themes-github", //"pages/themes-github",
"pages/plugins-github", //"pages/plugins-github",
"pages/replay", "pages/replay",
"pages/audiolabs", "pages/audiolabs",
"pages/zoo", "pages/zoo",
"pages/plugin-renderer", "pages/plugin-renderer",
"pages/keybinds",
"pages/oobe", "pages/oobe",
"components/app-content", "components/app-content",
"components/sidebar", "components/sidebar",
@ -126,7 +125,11 @@ export class BrowserWindow {
"components/hello-world", "components/hello-world",
"components/inline-collection-list", "components/inline-collection-list",
"components/settings-window", "components/settings-window",
"components/pagination" "components/pagination",
"components/settings-keybinds",
"components/settings-themes",
"components/settings-themes-github",
"components/settings-plugins-github",
], ],
appRoutes: [ appRoutes: [
{ {
@ -276,6 +279,10 @@ export class BrowserWindow {
page: "replay", page: "replay",
component: `<replay-page></replay-page>`, component: `<replay-page></replay-page>`,
condition: `$root.page == 'replay'` condition: `$root.page == 'replay'`
}, {
page: "keydinds",
component: `<keybinds-settings></keybinds-settings>`,
condition: `$root.page == 'keybinds-settings'`
} }
] ]
}, },

View file

@ -244,12 +244,13 @@ export class Store {
"windowColor": "#000000", "windowColor": "#000000",
"customAccentColor": false, "customAccentColor": false,
"accentColor": "#fc3c44", "accentColor": "#fc3c44",
"purplePodcastPlaybackBar": false "purplePodcastPlaybackBar": false,
"maxElementScale": -1 // -1 default, anything else is a custom scale
}, },
"lyrics": { "lyrics": {
"enable_mxm": false, "enable_mxm": true,
"mxm_karaoke": false, "mxm_karaoke": false,
"mxm_language": "en", "mxm_language": "disabled",
"enable_qq": false, "enable_qq": false,
"enable_yt": false, "enable_yt": false,
}, },
@ -258,7 +259,7 @@ export class Store {
"experiments": [], "experiments": [],
"playlistTrackMapping": true, "playlistTrackMapping": true,
"ffmpegLocation": "", "ffmpegLocation": "",
"disableLogging": false "disableLogging": true
}, },
"connectUser": { "connectUser": {
"auth": null, "auth": null,

View file

@ -52,12 +52,22 @@ export default class DiscordRPC {
const self = this const self = this
this.connect(); this.connect();
console.debug(`[Plugin][${this.name}] Ready.`); console.debug(`[Plugin][${this.name}] Ready.`);
ipcMain.on('updateRPCImage', (_event, imageurl) => { ipcMain.on('updateRPCImage', async (_event, imageurl) => {
if (!this._utils.getStoreValue("general.privateEnabled")) { if (!this._utils.getStoreValue("general.privateEnabled")) {
let b64data = ""
let postbody = ""
if (imageurl.startsWith("/ciderlocalart")){
let port = await _win.webContents.executeJavaScript(
`app.clientPort`
);
console.log("http://localhost:"+port+imageurl)
const response = await fetch("http://localhost:"+port+imageurl)
b64data = (await response.buffer()).toString('base64');
postbody = JSON.stringify({data: b64data})
fetch('https://api.cider.sh/v1/images', { fetch('https://api.cider.sh/v1/images', {
method: 'POST', method: 'POST',
body: JSON.stringify({url: imageurl}), body: postbody,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'User-Agent': _win.webContents.getUserAgent() 'User-Agent': _win.webContents.getUserAgent()
@ -68,6 +78,24 @@ export default class DiscordRPC {
self._attributes["artwork"]["url"] = json.url self._attributes["artwork"]["url"] = json.url
self.setActivity(self._attributes) self.setActivity(self._attributes)
}) })
} else {
postbody = JSON.stringify({url: imageurl})
fetch('https://api.cider.sh/v1/images', {
method: 'POST',
body: postbody,
headers: {
'Content-Type': 'application/json',
'User-Agent': _win.webContents.getUserAgent()
},
})
.then(res => res.json())
.then(function (json) {
self._attributes["artwork"]["url"] = json.url
self.setActivity(self._attributes)
})
}
} }
}) })
ipcMain.on("reloadRPC", () => { ipcMain.on("reloadRPC", () => {
@ -88,6 +116,7 @@ export default class DiscordRPC {
}) })
} }
/** /**
* Runs on app stop * Runs on app stop
*/ */

View file

@ -7,10 +7,7 @@ export default class lastfm {
public version: string = '2.0.0'; public version: string = '2.0.0';
public author: string = 'Core (Cider Collective)'; public author: string = 'Core (Cider Collective)';
/**
* Private variables for interaction in plugins
*/
private _attributes: any;
private _apiCredentials = { private _apiCredentials = {
key: "f9986d12aab5a0fe66193c559435ede3", key: "f9986d12aab5a0fe66193c559435ede3",
secret: "acba3c29bd5973efa38cc2f0b63cc625" secret: "acba3c29bd5973efa38cc2f0b63cc625"
@ -31,31 +28,36 @@ export default class lastfm {
constructor(utils: any) { constructor(utils: any) {
this._utils = utils; this._utils = utils;
this.initializeLastFM("", this._apiCredentials)
} }
onReady(_win: Electron.BrowserWindow): void { onReady(_win: Electron.BrowserWindow): void {
this.initializeLastFM("", this._apiCredentials)
// Register the ipcMain handlers // Register the ipcMain handlers
this._utils.getIPCMain().handle('lastfm:url', (event: any) => { this._utils.getIPCMain().handle('lastfm:url', (event: any) => {
console.debug(`${lastfm.name}:url`) console.debug(`[${lastfm.name}:url] Called.`)
return this._lfm.getAuthenticationUrl({"cb": "cider://auth/lastfm"}) return this._lfm.getAuthenticationUrl({"cb": "cider://auth/lastfm"})
}) })
this._utils.getIPCMain().on('lastfm:auth', (event: any, token: string) => { this._utils.getIPCMain().on('lastfm:auth', (event: any, token: string) => {
console.debug(`${lastfm.name}:auth`, token) console.debug(`[${lastfm.name}:auth] Token: `, token)
this.authenticateLastFM(token) this.authenticateLastFM(token)
}) })
this._utils.getIPCMain().on('lastfm:disconnect', (_event: any) => { this._utils.getIPCMain().on('lastfm:disconnect', (_event: any) => {
this._lfm.setSessionCredentials(null, null); this._lfm.setSessionCredentials(null, null);
this._authenticated = false; this._authenticated = false;
console.debug(`${lastfm.name}:disconnect`) console.debug(`[${lastfm.name}:disconnect] Disconnected`)
}) })
this._utils.getIPCMain().on('lastfm:nowPlayingChange', (event: any, attributes: any) => { this._utils.getIPCMain().on('lastfm:nowPlayingChange', (event: any, attributes: any) => {
if (this._utils.getStoreValue("connectivity.lastfm.filter_loop")) return; if (this._utils.getStoreValue("connectivity.lastfm.filter_loop") || this._utils.getStoreValue("general.privateEnabled")) return;
this.onNowPlayingItemDidChange(attributes) this.updateNowPlayingTrack(attributes)
})
this._utils.getIPCMain().on('lastfm:scrobbleTrack', (event: any, attributes: any) => {
if (this._utils.getStoreValue("general.privateEnabled")) return;
this.scrobbleTrack(attributes)
}) })
} }
@ -64,22 +66,15 @@ export default class lastfm {
* @param attributes Music Attributes (attributes.status = current state) * @param attributes Music Attributes (attributes.status = current state)
*/ */
onPlaybackStateDidChange(attributes: object): void { onPlaybackStateDidChange(attributes: object): void {
this._attributes = attributes
// this.scrobbleTrack(attributes)
} }
/** /**
* Runs on song change * Runs on song change
* @param attributes Music Attributes * @param attributes Music Attributes
* @param scrobble
*/ */
onNowPlayingItemDidChange(attributes: any): void { onNowPlayingItemDidChange(attributes: any, scrobble = false): void {
if (this._utils.getStoreValue("general.privateEnabled")) return; if (this._utils.getStoreValue("general.privateEnabled")) return;
this._attributes = attributes
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
this.verifyTrack(attributes)
return
}
this.scrobbleTrack(attributes)
this.updateNowPlayingTrack(attributes) this.updateNowPlayingTrack(attributes)
} }
@ -90,6 +85,7 @@ export default class lastfm {
* @private * @private
*/ */
private initializeLastFM(token: string, api: { key: string, secret: string }): void { private initializeLastFM(token: string, api: { key: string, secret: string }): void {
console.debug(`[${lastfm.name}:initialize] Initializing LastFM`)
const LastfmAPI = require("lastfmapi") const LastfmAPI = require("lastfmapi")
this._lfm = new LastfmAPI({ this._lfm = new LastfmAPI({
'api_key': api.key, 'api_key': api.key,
@ -113,7 +109,7 @@ export default class lastfm {
if (!token) return; if (!token) return;
this._lfm.authenticate(token, (err: any, session: any) => { this._lfm.authenticate(token, (err: any, session: any) => {
if (err) { if (err) {
console.error(err); console.error(`[${lastfm.name}:authenticate] Error: ${typeof err === "string" ? err : err.message}`);
this._utils.getWindow().webContents.executeJavaScript(`app.notyf.error("${err.message}");`) this._utils.getWindow().webContents.executeJavaScript(`app.notyf.error("${err.message}");`)
return; return;
@ -127,37 +123,36 @@ export default class lastfm {
/** /**
* Verifies the track information with lastfm * Verifies the track information with lastfm
* @param attributes * @param attributes
* @param callback
* @private * @private
*/ */
private verifyTrack(attributes: any): object { private verifyTrack(attributes: any, callback: Function): void {
if (!attributes) return attributes; if (!attributes) return attributes;
if (!attributes.lfmAlbum) { if (!attributes.lfmAlbum) {
return this._lfm.album.getInfo({ this._lfm.album.getInfo({
"artist": attributes.artistName, "artist": attributes.artistName,
"album": attributes.albumName "album": attributes.albumName
}, (err: any, data: any) => { }, (err: any, data: any) => {
if (err) { if (err) {
console.error(`[${lastfm.name}] [album.getInfo] Error: ${typeof err === "string" ? err : err.message}`) console.error(`[${lastfm.name}] [album.getInfo] Error: ${typeof err === "string" ? err : err.message}`)
console.error(err)
return {}; return {};
} }
if (data) { if (data) {
attributes.lfmAlbum = data attributes.lfmAlbum = data
callback(attributes)
} }
this.onNowPlayingItemDidChange(attributes)
}) })
} else { } else {
return this._lfm.track.getCorrection(attributes.artistName, attributes.name, (err: any, data: any) => { this._lfm.track.getCorrection(attributes.artistName, attributes.name, (err: any, data: any) => {
if (err) { if (err) {
console.error(`[${lastfm.name}] [track.getCorrection] Error: ${typeof err === "string" ? err : err.message}`) console.error(`[${lastfm.name}] [track.getCorrection] Error: ${typeof err === "string" ? err : err.message}`)
console.error(err)
return {}; return {};
} }
if (data) { if (data) {
attributes.lfmTrack = data.correction.track attributes.lfmTrack = data.correction.track
callback(attributes)
} }
this.onNowPlayingItemDidChange(attributes)
}) })
} }
@ -170,14 +165,14 @@ export default class lastfm {
* @private * @private
*/ */
private scrobbleTrack(attributes: any): void { private scrobbleTrack(attributes: any): void {
if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._scrobbleCache.track === attributes.lfmTrack.name)) return; if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
this.verifyTrack(attributes, (a: any) => {
if (this._scrobbleDelay) { this.scrobbleTrack(a)
clearTimeout(this._scrobbleDelay); })
return
} }
// Scrobble delay if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._scrobbleCache.track === attributes.lfmTrack.name)) return;
this._scrobbleDelay = setTimeout(() => {
// Scrobble // Scrobble
const scrobble = { const scrobble = {
@ -191,9 +186,7 @@ export default class lastfm {
} }
// Easy Debugging // Easy Debugging
if (!this._utils.getApp().isPackaged) { console.debug(`[${lastfm.name}:scrobble] Scrobbling ${scrobble.artist} - ${scrobble.track}`)
console.debug(scrobble)
}
// Scrobble the track // Scrobble the track
this._lfm.track.scrobble(scrobble, (err: any, _res: any) => { this._lfm.track.scrobble(scrobble, (err: any, _res: any) => {
@ -204,10 +197,21 @@ export default class lastfm {
this._scrobbleCache = scrobble this._scrobbleCache = scrobble
} }
}); });
}, Math.round(attributes.durationInMillis * Math.min((this._utils.getStoreValue("connectivity.lastfm.scrobble_after") / 100), 0.8)))
} }
/**
* Updates the now playing track
* @param attributes
* @private
*/
private updateNowPlayingTrack(attributes: any): void { private updateNowPlayingTrack(attributes: any): void {
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
this.verifyTrack(attributes, (a: any) => {
this.updateNowPlayingTrack(a)
})
return
}
if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._nowPlayingCache.track === attributes.lfmTrack.name)) return; if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._nowPlayingCache.track === attributes.lfmTrack.name)) return;
const nowPlaying = { const nowPlaying = {
@ -223,7 +227,6 @@ export default class lastfm {
if (err) { if (err) {
console.error(`[${lastfm.name}:updateNowPlaying] Now Playing Update failed: ${err.message}`); console.error(`[${lastfm.name}:updateNowPlaying] Now Playing Update failed: ${err.message}`);
} else { } else {
console.log(res)
console.debug(`[${lastfm.name}:updateNowPlaying] Now Playing Updated: ${nowPlaying.artist} - ${nowPlaying.track}`); console.debug(`[${lastfm.name}:updateNowPlaying] Now Playing Updated: ${nowPlaying.artist} - ${nowPlaying.track}`);
this._nowPlayingCache = nowPlaying this._nowPlayingCache = nowPlaying
} }

View file

@ -6,8 +6,7 @@ import * as mm from 'music-metadata';
import {Md5} from 'ts-md5/dist/md5'; import {Md5} from 'ts-md5/dist/md5';
import e from "express"; import e from "express";
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { parseFile, recursiveFolderSearch } from 'cider_utils';
export class LocalFiles { export class LocalFiles {
static localSongs: any = []; static localSongs: any = [];
@ -38,21 +37,20 @@ export class LocalFiles {
let folders = utils.getStoreValue("libraryPrefs.localPaths") let folders = utils.getStoreValue("libraryPrefs.localPaths")
if (folders == null || folders.length == null || folders.length == 0) folders = [] if (folders == null || folders.length == null || folders.length == 0) folders = []
console.log('folders', folders) console.log('folders', folders)
let files: any[] = [] let parseFileQueue: any[] = []; let mmQueue: any[] = []
for (var folder of folders) { for (var folder of folders) {
// get files from the Music folder // Recursively search and add
files = files.concat(await LocalFiles.getFiles(folder)) let result = await recursiveFolderSearch(folder)
parseFileQueue = parseFileQueue.concat(result.parseFile)
mmQueue = mmQueue.concat(result.musicMetadata)
} }
if (parseFileQueue.length !== 0 || mmQueue.length !== 0) {console.log('Recursive Folder Search in Cider Utils worki')}
//console.log("cider.files", files2);
let supporttedformats = ["mp3", "aac", "webm", "flac", "m4a", "ogg", "wav", "opus"]
let audiofiles = files.filter(f => supporttedformats.includes(f.substring(f.lastIndexOf('.') + 1)));
// console.log("cider.files2", audiofiles, audiofiles.length);
let metadatalist = [] let metadatalist = []
let metadatalistart = [] let metadatalistart = []
let numid = 0; let numid = 0;
for (var audio of audiofiles) { // Music Metadata fallback
for (var audio of mmQueue) {
try { try {
const metadata = await mm.parseFile(audio); const metadata = await mm.parseFile(audio);
let lochash = Md5.hashStr(audio) ?? numid; let lochash = Md5.hashStr(audio) ?? numid;
@ -121,7 +119,80 @@ export class LocalFiles {
if (this.localSongs.length === 0 && numid % 10 === 0) { // send updated chunks only if there is no previous database if (this.localSongs.length === 0 && numid % 10 === 0) { // send updated chunks only if there is no previous database
this.eventEmitter.emit('newtracks', metadatalist)} this.eventEmitter.emit('newtracks', metadatalist)}
} }
} catch (e) { } } catch (e) {console.error("error:", e)}
}
// Cider-Utils supported formats.
for (var audio of parseFileQueue) {
try {
const metadata = await parseFile(audio);
let lochash = Md5.hashStr(audio) ?? numid;
if (metadata != null) {
let form = {
"id": "ciderlocal" + lochash,
"_id": "ciderlocal" + lochash,
"type": "podcast-episodes",
"href": audio,
"attributes": {
"artwork": {
"width": 3000,
"height": 3000,
"url": "/ciderlocalart/" + "ciderlocal" + lochash,
},
"topics": [],
"url": "",
"subscribable": true,
"mediaKind": "audio",
"genreNames": [
""
],
// "playParams": {
// "id": "ciderlocal" + numid,
// "kind": "podcast",
// "isLibrary": true,
// "reporting": false },
"trackNumber": metadata.track_number ?? 0,
"discNumber": metadata.disc_number ?? 0,
"name": metadata.title ?? audio.substring(audio.lastIndexOf('\\') + 1),
"albumName": metadata.album,
"artistName": metadata.artist,
"copyright": metadata.copyright ?? "",
"assetUrl": "file:///" + audio,
"contentAdvisory": "",
"releaseDateTime": `${metadata.year ?? '2022'}-05-13T00:23:00Z`,
"durationInMillis": metadata.duration_in_ms ?? 0,
"bitrate": metadata.bitrate ?? 0,
"offers": [
{
"kind": "get",
"type": "STDQ"
}
],
"contentRating": "clean"
},
flavor: metadata.bitrate,
localFilesMetadata: {
lossless: metadata.lossless,
container: metadata.container,
bitDepth: metadata.bit_depth,
sampleRate: metadata.sample_rate ?? 0,
},
};
let art = {
id: "ciderlocal" + lochash,
_id: "ciderlocalart" + lochash,
url: metadata.artwork != undefined ? metadata.artwork : "",
}
metadatalistart.push(art)
numid += 1;
ProviderDB.db.putIfNotExists(form)
ProviderDB.db.putIfNotExists(art)
metadatalist.push(form)
if (this.localSongs.length === 0 && numid % 10 === 0) { // send updated chunks only if there is no previous database
this.eventEmitter.emit('newtracks', metadatalist)}
}
} catch (e) {console.error("error:", e)}
} }
this.localSongs = metadatalist; this.localSongs = metadatalist;
this.localSongsArts = metadatalistart; this.localSongsArts = metadatalistart;
@ -173,7 +244,7 @@ export class LocalFiles {
// metadata.common.picture[0].data.toString('base64') // metadata.common.picture[0].data.toString('base64')
res.setHeader('Cache-Control', 'public, max-age=31536000'); res.setHeader('Cache-Control', 'public, max-age=31536000');
res.setHeader('Expires', new Date(Date.now() + 31536000).toUTCString()); res.setHeader('Expires', new Date(Date.now() + 31536000000).toUTCString());
res.setHeader('Content-Type', 'image/jpeg'); res.setHeader('Content-Type', 'image/jpeg');
let data = let data =

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-package"><line x1="16.5" y1="9.4" x2="7.5" y2="4.21"></line><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path><polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline><line x1="12" y1="22.08" x2="12" y2="12"></line></svg>

After

Width:  |  Height:  |  Size: 517 B

View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24px"
height="24px"
viewBox="0 0 24 24"
version="1.1"
id="svg4"
sodipodi:docname="style-svgrepo-com.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="36.541667"
inkscape:cx="8.031927"
inkscape:cy="12.054732"
inkscape:window-width="1920"
inkscape:window-height="1044"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M23.14.93l-.07-.07A2.926 2.926 0 0 0 20.98 0a2.886 2.886 0 0 0-2.08.86L8.858 10.9a3.04 3.04 0 0 0-.53.72 7.793 7.793 0 0 0-4.1 1.621c-.191.144-.36.316-.5.51a6.08 6.08 0 0 0-.98 1.961c-.25.69-.59 1.631-1.22 3-.42.91-.75 1.541-.98 1.981a3.092 3.092 0 0 0-.54 1.631c.014.206.08.406.19.58a2.64 2.64 0 0 0 2.23 1.07 10.462 10.462 0 0 0 8.161-3.371c.378-.44.692-.932.93-1.461a7.882 7.882 0 0 0 .69-3.361.142.142 0 0 1 .02-.04c.325-.144.62-.347.87-.6L23.14 5.1A2.888 2.888 0 0 0 24 3.021 2.927 2.927 0 0 0 23.14.93zM9.7 18.317c-.17.368-.388.711-.65 1.02a8.393 8.393 0 0 1-6.891 2.6c.05-.1.11-.21.17-.32.24-.46.58-1.11 1.02-2.061a39.058 39.058 0 0 0 1.28-3.151c.14-.491.355-.957.64-1.381.062-.08.133-.154.21-.22a5.221 5.221 0 0 1 2.59-1.14c.121.537.396 1.027.79 1.411l.07.07c.35.357.788.616 1.27.75a5.614 5.614 0 0 1-.499 2.422zM21.73 3.691L11.678 13.735a.947.947 0 0 1-.67.28.983.983 0 0 1-.67-.28l-.07-.07a.948.948 0 0 1 0-1.34L20.309 2.271c.18-.173.42-.27.671-.271a.937.937 0 0 1 .67.27l.08.08c.36.374.36.967 0 1.341z"
fill="#494c4e"
fill-rule="evenodd"
id="path2"
style="fill:#000000;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -1,57 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg width="38" height="38" viewBox="0 0 600 400" xmlns="http://www.w3.org/2000/svg">
<svg <path style="fill:#fff;fill-opacity:1;fill-rule:nonzero;stroke:#000;stroke-width:13;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" d="M464.7 222.884c-21.905 2.737-39.702.683-39.702.683V89.44h41.754s46.548 13 46.548 62.273c0 45.165-23.272 62.959-48.6 71.171m115.382-94.16C561.821 32.277 465.385 20.292 465.385 20.292H33.42c-14.266 0-16.021 18.833-16.021 18.833s-1.924 172.892-.529 279.07c3.87 57.21 61.058 63.076 61.058 63.076s195.155-.57 282.462-1.14c57.558-10.083 63.339-60.573 62.769-88.188 102.713 5.707 175.182-66.771 156.923-163.219"/>
fill="none" <path style="fill:#ff5f5f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00346" d="M216.99 306.032c4.46 2.246 7.31-.544 7.31-.544s65.27-59.573 94.674-93.882c26.154-30.691 27.858-82.413-17.056-101.739-44.913-19.324-81.866 22.736-81.866 22.736-32.046-35.245-80.546-33.46-102.979-9.608-22.431 23.852-14.598 64.791 2.137 87.576 15.709 21.388 84.757 82.93 95.222 93.338 0 0 .763.798 2.557 2.123"/>
height="391"
viewBox="0 0 391 391"
width="391"
version="1.1"
id="svg10"
sodipodi:docname="ko_fi.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs14" />
<sodipodi:namedview
id="namedview12"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="2.1202046"
inkscape:cx="111.07419"
inkscape:cy="196.67913"
inkscape:window-width="1920"
inkscape:window-height="1009"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg10" />
<path
d="M 31.247286,101.05669 H 327.24729 v 199 H 31.247286 Z"
fill="#fff"
id="path2"
style="display:inline;fill:none;fill-opacity:1;stroke:none;stroke-width:5;stroke-linecap:square;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill" />
<path
d="m 311.81693,84.320186 c 30.63288,8.509134 52.99975,29.903524 61.02265,58.348344 9.4816,34.1581 -0.12156,67.58684 -26.1352,89.83214 -13.97929,11.91279 -39.50669,20.7866 -60.29329,20.7866 h -9.23849 l -0.97247,8.75225 c -2.30962,23.58246 -13.85773,39.5067 -32.82095,44.97685 -3.52521,1.09404 -30.63288,1.45871 -97.24724,1.45871 l -92.38476,0.12156 -7.293543,-3.40365 c -11.66967,-5.47016 -20.543481,-15.438 -23.947134,-26.98611 -0.486236,-1.94495 -0.972473,-44.49062 -0.972473,-94.57295 0,-98.098154 0,-97.976594 6.321071,-100.529335 1.701827,-0.607795 59.077579,-1.094031 138.941879,-1.094031 133.10716,-0.121559 136.38926,-0.121559 145.01995,2.309622 z"
fill="#579fbf"
id="path4"
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:12.1559;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="cccscccccccsccc" />
<path
d="m 278.02351,168.19593 v 41.33008 h 10.6972 c 18.84165,0 30.38977,-6.44263 37.92643,-21.15127 4.01145,-8.0229 4.25456,-8.99537 4.25456,-21.27284 0,-11.66967 -0.36467,-13.49305 -3.40365,-19.81412 -3.64677,-7.53667 -10.45408,-14.10085 -18.47698,-17.99074 -4.01145,-1.94495 -7.53666,-2.43118 -17.99074,-2.43118 h -13.00682 z"
fill="#579fbf"
id="path6"
style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:12.1559;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" />
<path
d="m 173.34293,137.08897 c -8.87381,2.91742 -11.66966,4.49769 -18.59853,10.21096 l -5.71328,4.74081 -5.22704,-4.25457 c -17.26138,-14.10085 -42.54566,-15.68112 -56.768074,-3.52521 -7.050426,6.07795 -9.967357,12.52058 -10.696711,23.58245 -0.607795,9.84629 1.458709,19.20633 6.077467,28.2017 1.337149,2.6743 7.171984,9.72473 12.885259,15.80268 17.869179,18.59854 51.541039,49.47454 53.972219,49.47454 1.45871,0 14.70865,-12.27747 33.18562,-30.75445 27.83703,-27.71546 31.24068,-31.48379 34.76589,-39.02045 4.98392,-10.57564 6.07796,-22.8531 3.03898,-32.09159 -5.95639,-17.74762 -28.44482,-28.44482 -46.9218,-22.36687 z"
fill="#ff5f5f"
id="path8"
style="display:inline;stroke-width:1.21559" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

View file

@ -1,5 +1,9 @@
var notyf = new Notyf(); var notyf = new Notyf();
function clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
const MusicKitObjects = { const MusicKitObjects = {
LibraryPlaylist: function () { LibraryPlaylist: function () {
this.id = ""; this.id = "";
@ -84,8 +88,14 @@ function fallbackinitMusicKit() {
} }
function initMusicKit() { function initMusicKit() {
if(!this.responseText) {
console.log("Using stored token")
this.responseText = JSON.stringify({
token: localStorage.getItem("lastToken")
})
}
let parsedJson = JSON.parse(this.responseText); let parsedJson = JSON.parse(this.responseText);
localStorage.setItem("lastToken", parsedJson.token);
MusicKit.configure({ MusicKit.configure({
developerToken: parsedJson.token, developerToken: parsedJson.token,
app: { app: {
@ -116,7 +126,13 @@ function capiInit() {
request.addEventListener("load", initMusicKit); request.addEventListener("load", initMusicKit);
request.onreadystatechange = function (aEvt) { request.onreadystatechange = function (aEvt) {
if (request.readyState == 4) { if (request.readyState == 4) {
if (request.status != 200) fallbackinitMusicKit(); if (request.status != 200) {
if(localStorage.getItem("lastToken") != null) {
initMusicKit()
}else{
fallbackinitMusicKit()
}
};
} }
}; };
request.open("GET", "https://api.cider.sh/v1/"); request.open("GET", "https://api.cider.sh/v1/");

View file

@ -239,6 +239,12 @@ input[type=range].md-slider::-webkit-slider-runnable-track {
width: auto; width: auto;
} }
@media only screen and (min-width: 1133px) and (max-width: 1233px) {
.row .col-auto {
display: none !important;
}
}
.col-1 { .col-1 {
flex: 0 0 auto; flex: 0 0 auto;
width: 8.33333333%; width: 8.33333333%;

View file

@ -2642,6 +2642,12 @@ fieldset:disabled .btn {
width: auto; width: auto;
} }
@media only screen and (min-width: 1133px) and (max-width: 1241px) {
.row .col-auto {
display: none !important;
}
}
.col-1 { .col-1 {
flex : 0 0 auto; flex : 0 0 auto;
width: 8.33333333%; width: 8.33333333%;

View file

@ -984,11 +984,11 @@
/* mediaitem-square */ /* mediaitem-square */
.cd-mediaitem-square { .cd-mediaitem-square {
--transitionDuration: .25s; --transitionDuration: .5s;
--scaleRate: 1.25; --scaleRate: 1.25;
--scaleRateArtwork: 1; --scaleRateArtwork: 1;
width: 200px; width: calc(160px * var(--windowRelativeScale));
height: 200px; height: calc(200px * var(--windowRelativeScale));
display: inline-flex; display: inline-flex;
flex: 0 0 auto; flex: 0 0 auto;
flex-direction: column; flex-direction: column;
@ -996,14 +996,13 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
border-radius: 6px; border-radius: 6px;
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
.artwork-container { .artwork-container {
position: relative; position: relative;
.artwork { .artwork {
height: 150px; height: calc(140px * var(--windowRelativeScale));
width: 150px; width: calc(140px * var(--windowRelativeScale));
background: blue; background: blue;
border-radius: var(--mediaItemRadius); border-radius: var(--mediaItemRadius);
background: var(--artwork); background: var(--artwork);
@ -1011,7 +1010,6 @@
flex: 0 0 auto; flex: 0 0 auto;
margin: 6px; margin: 6px;
cursor: pointer; cursor: pointer;
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
.mediaitem-artwork { .mediaitem-artwork {
box-shadow: unset; box-shadow: unset;
@ -1085,31 +1083,31 @@
} }
} }
&:not(.mediaitem-card):not(.mediaitem-brick):not(.mediaitem-video):not(.noscale) { // &:not(.mediaitem-card):not(.mediaitem-brick):not(.mediaitem-video):not(.noscale) {
@media (min-width: 1460px) { // @media (min-width: 1460px) {
--scaleRate: 1.1; // --scaleRate: 1.1;
--scaleRateArtwork: 0.9; // --scaleRateArtwork: 0.9;
width: calc(200px * var(--scaleRate)); // width: calc(200px * var(--scaleRate));
height: calc(200px * var(--scaleRate)); // height: calc(200px * var(--scaleRate));
.artwork-container > .artwork { // .artwork-container > .artwork {
width: calc(190px * var(--scaleRateArtwork)); // width: calc(190px * var(--scaleRateArtwork));
height: calc(190px * var(--scaleRateArtwork)); // height: calc(190px * var(--scaleRateArtwork));
} // }
} // }
@media (min-width: 1550px) { // @media (min-width: 1550px) {
--scaleRate: 1.25; // --scaleRate: 1.25;
--scaleRateArtwork: 1; // --scaleRateArtwork: 1;
width: calc(200px * var(--scaleRate)); // width: calc(200px * var(--scaleRate));
height: calc(200px * var(--scaleRate)); // height: calc(200px * var(--scaleRate));
.artwork-container > .artwork { // .artwork-container > .artwork {
width: calc(190px * var(--scaleRateArtwork)); // width: calc(190px * var(--scaleRateArtwork));
height: calc(190px * var(--scaleRateArtwork)); // height: calc(190px * var(--scaleRateArtwork));
} // }
} // }
} // }
.info-rect { .info-rect {
@ -1161,10 +1159,12 @@
&.mediaitem-video { &.mediaitem-video {
height: 200px; height: 200px;
width: 240px; width: 240px;
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
.artwork { .artwork {
height: 120px; height: 120px;
width: 212px; width: 212px;
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
} }
&:not(.noscale) { &:not(.noscale) {
@ -1197,10 +1197,12 @@
&.mediaitem-brick { &.mediaitem-brick {
height: 200px; height: 200px;
width: 240px; width: 240px;
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
.artwork { .artwork {
height: 123px; height: 123px;
width: 220px; width: 220px;
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
} }
&:not(.noscale) { &:not(.noscale) {
@ -1231,12 +1233,14 @@
} }
&.mediaitem-small { &.mediaitem-small {
width: 140px; width: calc(140px, var(--windowRelativeScale));
height: 180px; height: calc(180px, var(--windowRelativeScale));
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
.artwork { .artwork {
height: 128px; height: calc(128px, var(--windowRelativeScale));
width: 128px; width: calc(128px, var(--windowRelativeScale));
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
} }
} }
@ -1249,6 +1253,7 @@
position: relative; position: relative;
border-radius: calc(var(--mediaItemRadius) * 2); border-radius: calc(var(--mediaItemRadius) * 2);
box-shadow: var(--mediaItemShadow-ShadowSubtle); box-shadow: var(--mediaItemShadow-ShadowSubtle);
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
.artwork { .artwork {
width: 230px; width: 230px;
@ -1341,7 +1346,7 @@
} }
&:not(.noscale) { &:not(.noscale) {
@media (min-width: 1460px) { @media (min-width: 1200px) {
width: calc(230px * 1.1); width: calc(230px * 1.1);
height: calc(298px * 1.1); height: calc(298px * 1.1);
.artwork-container > .artwork { .artwork-container > .artwork {
@ -1350,7 +1355,7 @@
} }
} }
@media (min-width: 1550px) { @media (min-width: 1400px) {
width: calc(230px * 1.25); width: calc(230px * 1.25);
height: calc(298px * 1.25); height: calc(298px * 1.25);
.artwork-container > .artwork { .artwork-container > .artwork {

View file

@ -1,6 +1,6 @@
body[platform="darwin"] { body[platform="darwin"] {
html { html {
background: transparent!important; background: transparent !important;
} }
&.notransparency::before { &.notransparency::before {
@ -11,6 +11,7 @@ body[platform="darwin"] {
&.simplebg { &.simplebg {
background: transparent; background: transparent;
} }
&::before { &::before {
display: none; display: none;
} }
@ -26,6 +27,7 @@ body[platform="darwin"] {
.app-chrome .app-chrome-item.search { .app-chrome .app-chrome-item.search {
margin-right: 12px; margin-right: 12px;
} }
.app-chrome .app-mainmenu { .app-chrome .app-mainmenu {
width: 46px; width: 46px;
} }
@ -35,15 +37,20 @@ body[platform="darwin"] {
} }
} }
// &::after { &[window-state="normal"] {
// position: fixed; &::after {
// top:0;left:0;right:0;bottom:0; position: fixed;
// box-shadow: inset 0px 0px .5px 1px rgb(200 200 200 / 40%); top: 0;
// border-radius: 10px; left: 0;
// content: " "; right: 0;
// z-index: 999999; bottom: 0;
// pointer-events: none; box-shadow: inset 0px 0px .5px 1px rgb(200 200 200 / 40%);
// } border-radius: 10px;
content: " ";
z-index: 999999;
pointer-events: none;
}
}
} }
#app-main { #app-main {
@ -58,6 +65,13 @@ body[platform="darwin"] {
} }
} }
.settings-window.maxed {
.tabs>.col-auto {
transition: padding-top .3s linear;
padding-top: var(--chromeHeight1);
}
}
#apple-music-video-player-controls #player-exit { #apple-music-video-player-controls #player-exit {
margin-top: 18px; margin-top: 18px;
left: 70px; left: 70px;

View file

@ -23,8 +23,7 @@
.github-themes-page { .github-themes-page {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 0px; height: 100%;
height: calc(100% - var(--navigationBarHeight));
.github-avatar { .github-avatar {
height: 42px; height: 42px;
@ -52,9 +51,11 @@
.repos-list { .repos-list {
height: 100%; height: 100%;
overflow-y: overlay;
width: 320px; width: 320px;
font-size: 14px; font-size: 14px;
overflow: overlay;
padding-bottom: 16px;
flex: 0 0 auto;
> .list-group { > .list-group {
margin: 0px; margin: 0px;
@ -76,9 +77,9 @@
.github-preview { .github-preview {
height: 100%; height: 100%;
flex: 1; flex: 1;
background: var(--color2);
padding: 16px 32px; padding: 16px 32px;
overflow-y: overlay; overflow: auto;
padding-bottom: 16px;
} }
.gh-content { .gh-content {
@ -90,6 +91,182 @@
.gh-header { .gh-header {
padding: 16px; padding: 16px;
height: 64px;
display: grid;
align-content: center;
flex: 0 0 auto;
.header-text {
position: initial !important;
justify-content: left !important;
}
}
.installed-themes-page {
.style-editor-container {
height: 100%;
flex: 1;
background: var(--color2);
padding: 0px;
overflow-y: overlay;
.list-group-item {
border-radius: 0px;
}
}
}
}
//Styles Page
.installed-themes-page {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
.themeContextMenu {
background: transparent;
color: var(--keyColor);
border: 0px;
}
.list-group-item {
&.addon {
background: rgb(86 86 86 / 20%);
}
&.applied {
background: var(--keyColor-disabled);
pointer-events: none;
}
}
.repo-header {
font-size: 16px;
position: sticky;
top: 0;
left: 0;
right: 0;
width: 100%;
height: 50px;
z-index: 1;
background: rgba(36, 36, 36, 0.5);
display: flex;
justify-content: center;
align-items: center;
backdrop-filter: var(--glassFilter);
overflow: hidden;
border-bottom: 1px solid rgb(0 0 0 / 18%);
border-top: 1px solid rgb(135 135 135 / 18%);
}
.gh-header {
z-index: 5;
padding: 16px;
flex: 0 0 auto;
height: 64px;
display: grid;
align-content: center;
.header-text {
position: initial !important;
justify-content: left !important;
}
}
.gh-content {
display: flex;
flex-direction: row;
padding: 0px;
height: 100%;
flex: 0 0 auto;
.repos-list {
width: 320px;
overflow: overlay;
height: 90%;
font-size: 14px;
white-space: nowrap;
> .list-group {
margin: 0px;
padding-bottom: 16px;
}
.list-group-item {
padding: 12px 6px;
&:hover {
filter: brightness(1.2);
}
&:active {
filter: brightness(0.8);
}
}
}
.style-editor-container {
height: 100%;
flex: 1;
padding: 0px;
width: 100%;
overflow: hidden;
.stylestack-editor {
padding-bottom: 16px;
}
.list-group-item {
border-radius: 0px;
}
}
}
.stylestack-editor {
width: 100%;
.btn,
.btn-group {
width: 100%;
}
.themeLabel {
display: flex;
align-items: center;
}
.handle {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.list-group-item {
&:hover {
cursor: grab;
}
&:active {
cursor: grabbing;
}
}
.removeItem {
border: 0px;
background: transparent;
height: 32px;
font-weight: bold;
color: var(--textColor);
cursor: pointer;
}
.stylesDropdown {
> .dropdown-menu {
height: 300px;
overflow-y: overlay;
}
}
} }
} }
@ -1053,7 +1230,7 @@
} }
&.animated .artist-header { &.animated .artist-header {
min-height: 500px; min-height: 80vh;
} }
.artist-header { .artist-header {
@ -1113,6 +1290,24 @@
right: 28px; right: 28px;
} }
.social-btn {
border-radius: 100%;
background: transparent;
height: 17px;
border: 0px;
cursor: pointer;
z-index: 69;
display: flex;
justify-content: center;
align-items: center;
float: right;
}
@media only screen and (min-width: 1133px) and (max-width: 1277px) {
.social-btn {
display: none !important;
}
}
.animated { .animated {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -1131,6 +1326,7 @@
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
object-fit: cover;
} }
} }
@ -1273,107 +1469,6 @@
/* Artist Page End */ /* Artist Page End */
.installed-themes-page {
.themeContextMenu {
background: transparent;
color: var(--keyColor);
border: 0px;
}
.list-group-item {
&.addon {
background: rgb(86 86 86 / 20%);
}
&.applied {
background: var(--keyColor-disabled);
pointer-events: none;
}
}
.repo-header {
font-size: 16px;
position: sticky;
top: 0;
left: 0;
right: 0;
width: 100%;
height: 50px;
z-index: 1;
background: rgba(36, 36, 36, 0.5);
display: flex;
justify-content: center;
align-items: center;
backdrop-filter: var(--glassFilter);
overflow: hidden;
border-bottom: 1px solid rgb(0 0 0 / 18%);
border-top: 1px solid rgb(135 135 135 / 18%);
}
.style-editor-container {
height: 100%;
flex: 1;
background: var(--color2);
padding: 0px;
overflow-y: overlay;
.list-group-item {
border-radius: 0px;
}
}
.stylestack-editor {
width: 100%;
.btn,
.btn-group {
width: 100%;
}
.themeLabel {
display: flex;
align-items: center;
}
.handle {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.list-group-item {
&:hover {
cursor: grab;
}
&:active {
cursor: grabbing;
}
}
.removeItem {
border: 0px;
background: transparent;
height: 32px;
font-weight: bold;
color: var(--textColor);
cursor: pointer;
}
.stylesDropdown {
> .dropdown-menu {
height: 300px;
overflow-y: overlay;
}
}
}
}
// Settings page // Settings page
.settings-page { .settings-page {
padding: 0px; padding: 0px;
@ -1987,7 +2082,7 @@
.settings-window { .settings-window {
background: var(--baseColorMix); background: var(--baseColorMix);
max-width: 80%; max-width: 90%;
max-height: 90%; max-height: 90%;
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -2024,6 +2119,11 @@
display: flex; display: flex;
gap: 10px; gap: 10px;
align-items: center; align-items: center;
height: 35px;
:nth-child(2) {
white-space: nowrap;
}
} }
@ -2082,6 +2182,11 @@
background-color: rgb(196, 43, 28) background-color: rgb(196, 43, 28)
} }
&.back-btn {
left: 10px;
right: unset;
}
&.minmax-btn { &.minmax-btn {
right: 52px; right: 52px;
@ -2109,6 +2214,9 @@
> .col-auto { > .col-auto {
width: 230px; width: 230px;
overflow-x: hidden;
overflow-y: overlay;
transition: width 0.25s ease-in-out;
} }
.tab-content { .tab-content {
@ -2120,9 +2228,50 @@
overflow-y: overlay; overflow-y: overlay;
height: 100%; height: 100%;
background-color: var(--panelColor2); background-color: var(--panelColor2);
padding:0px;
padding-top: 48px; padding-top: 48px;
border-left: 1px solid var(--borderColor); border-left: 1px solid var(--borderColor);
} }
.github-themes-page, .installed-themes-page {
.header-text {
font-size: 1.25em;
}
}
.tab-pane {
height:100%;
}
.settings-tab-content {
height:100%;
}
&.no-sidebar {
.gh-header {
>.row {
&:last-child {
padding-right: 90px;
}
}
}
.tab-content {
padding-top:0px;
}
.tabs {
.nav-pills .nav-link {
width: 50px;
:nth-child(2) {
// font-size: 0px;
opacity:0;
}
}
>.col-auto {
width: 80px;
}
}
}
} }
} }

View file

@ -12,6 +12,7 @@ const app = new Vue({
ipcRenderer: ipcRenderer, ipcRenderer: ipcRenderer,
cfg: ipcRenderer.sendSync("getStore"), cfg: ipcRenderer.sendSync("getStore"),
isDev: ipcRenderer.sendSync("is-dev"), isDev: ipcRenderer.sendSync("is-dev"),
clientPort: ipcRenderer.sendSync("get-port"),
drawertest: false, drawertest: false,
platform: "", platform: "",
mk: {}, mk: {},
@ -705,6 +706,9 @@ const app = new Vue({
} catch (err) { } catch (err) {
} }
// Used to get a scale factor for the window for CSS scaling
window.addEventListener("resize", e => this.setWindowScaleFactor())
this.setWindowScaleFactor()
this.mk._bag.features['seamless-audio-transitions'] = this.cfg.audio.seamless_audio this.mk._bag.features['seamless-audio-transitions'] = this.cfg.audio.seamless_audio
this.mk._bag.features["broadcast-radio"] = true this.mk._bag.features["broadcast-radio"] = true
this.mk._services.apiManager.store.storekit._restrictedEnabled = false this.mk._services.apiManager.store.storekit._restrictedEnabled = false
@ -915,13 +919,19 @@ const app = new Vue({
} }
}); });
this.mk.addEventListener(MusicKit.Events.playbackProgressDidChange, () => {
if (self.mk.currentPlaybackProgress === (app.cfg.connectivity.lastfm.scrobble_after / 100)) {
ipcRenderer.send('lastfm:scrobbleTrack', MusicKitInterop.getAttributes());
}
})
this.mk.addEventListener(MusicKit.Events.playbackStateDidChange, (event) => { this.mk.addEventListener(MusicKit.Events.playbackStateDidChange, (event) => {
ipcRenderer.send('wsapi-updatePlaybackState', wsapi.getAttributes()); ipcRenderer.send('wsapi-updatePlaybackState', wsapi.getAttributes());
document.body.setAttribute("playback-state", event.state == 2 ? "playing" : "paused") document.body.setAttribute("playback-state", event.state == 2 ? "playing" : "paused")
}) })
this.mk.addEventListener(MusicKit.Events.playbackTimeDidChange, (a) => { this.mk.addEventListener(MusicKit.Events.playbackTimeDidChange, (a) => {
self.lyriccurrenttime = self.mk.currentPlaybackTime + app.lyricOffset // self.lyriccurrenttime = self.mk.currentPlaybackTime - app.lyricOffset
this.currentSongInfo = a this.currentSongInfo = a
self.playerLCD.playbackDuration = (self.mk.currentPlaybackTime) self.playerLCD.playbackDuration = (self.mk.currentPlaybackTime)
// wsapi // wsapi
@ -1091,6 +1101,18 @@ const app = new Vue({
ipcRenderer.invoke("scanLibrary") ipcRenderer.invoke("scanLibrary")
}, },
setWindowScaleFactor() {
let scale = window.devicePixelRatio * window.innerWidth / 1280 * window.innerHeight / 720
let desiredScale = clamp(parseFloat(app.cfg.visual.maxElementScale == -1 ? 1.5 : app.cfg.visual.maxElementScale), 1, 1.5)
app.$store.state.windowRelativeScale = scale
if(scale <= 1) {
scale = 1
}else if(scale >= desiredScale) {
scale = desiredScale
}
document.documentElement.style
.setProperty('--windowRelativeScale', scale);
},
showFoo(querySelector, time) { showFoo(querySelector, time) {
clearTimeout(this.idleTimer); clearTimeout(this.idleTimer);
if (this.idleState == true) { if (this.idleState == true) {
@ -1120,7 +1142,7 @@ const app = new Vue({
message: `[Themes] ${theme.name} has an update available.` message: `[Themes] ${theme.name} has an update available.`
}) })
notify.on("click", () => { notify.on("click", () => {
app.appRoute("themes-github") app.openSettingsPage("github-themes")
notyf.dismiss(notify) notyf.dismiss(notify)
}) })
} }
@ -1944,12 +1966,31 @@ const app = new Vue({
}) })
return; return;
} else if(item.attributes.link.url.includes("viewFeature")) {
const params = new Proxy(new URLSearchParams(new URL(item.attributes.link.url).search), {
get: (searchParams, prop) => searchParams.get(prop),
});
id = params.id
app.mk.api.v3.music(`/v1/editorial/vn/multiplex/${id}?art%5Burl%5D=f&format%5Bresources%5D=map&platform=web`).then(
(data) => {
let item = data.data.results?.target ?? []
app.routeView(item)
}
)
} else { } else {
window.open(item.attributes.link.url) window.open(item.attributes.link.url)
} }
} }
} else if (kind == "multirooms") { } else if (kind == "multiplex") {
app.mk.api.v3.music(`/v1/editorial/vn/multiplex/${id}?art%5Burl%5D=f&format%5Bresources%5D=map&platform=web`).then(
(data) => {
let item = data.data.results?.target ?? []
app.routeView(item)
}
)
}if (kind == "multirooms") {
app.getTypeFromID("multiroom", id, false, { app.getTypeFromID("multiroom", id, false, {
platform: "web", platform: "web",
extend: "editorialArtwork,uber,lockupStyle" extend: "editorialArtwork,uber,lockupStyle"
@ -1990,7 +2031,7 @@ const app = new Vue({
params["fields[artists]"] = "name,url" params["fields[artists]"] = "name,url"
params["omit[resource]"] = "autos" params["omit[resource]"] = "autos"
params["meta[albums:tracks]"] = 'popularity' params["meta[albums:tracks]"] = 'popularity'
params["fields[albums]"] = "artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialNotes,editorialVideo,name,playParams,releaseDate,url,copyright" params["fields[albums]"] = "artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialNotes,editorialVideo,name,playParams,releaseDate,url,copyright,genreNames"
} }
if (kind.includes("playlist") || kind.includes("album")) { if (kind.includes("playlist") || kind.includes("album")) {
app.page = (kind) + "_" + (id); app.page = (kind) + "_" + (id);
@ -3019,7 +3060,10 @@ const app = new Vue({
const track = encodeURIComponent((this.mk.nowPlayingItem != null) ? this.mk.nowPlayingItem.title ?? '' : ''); const track = encodeURIComponent((this.mk.nowPlayingItem != null) ? this.mk.nowPlayingItem.title ?? '' : '');
const artist = encodeURIComponent((this.mk.nowPlayingItem != null) ? this.mk.nowPlayingItem.artistName ?? '' : ''); const artist = encodeURIComponent((this.mk.nowPlayingItem != null) ? this.mk.nowPlayingItem.artistName ?? '' : '');
const time = encodeURIComponent((this.mk.nowPlayingItem != null) ? (Math.round((this.mk.nowPlayingItem.attributes["durationInMillis"] ?? -1000) / 1000) ?? -1) : -1); const time = encodeURIComponent((this.mk.nowPlayingItem != null) ? (Math.round((this.mk.nowPlayingItem.attributes["durationInMillis"] ?? -1000) / 1000) ?? -1) : -1);
const id = encodeURIComponent((this.mk.nowPlayingItem != null) ? app.mk.nowPlayingItem._songId ?? (app.mk.nowPlayingItem["songId"] ?? '') : ''); let id = null; let vanity_id = null;
if (this.mk.nowPlayingItem != null && app.mk.nowPlayingItem.localFilesMetadata != null) {const id = encodeURIComponent('')}
else {id = encodeURIComponent((this.mk.nowPlayingItem != null) ? (app.mk.nowPlayingItem._songId) ?? (app.mk.nowPlayingItem["songId"] ?? '') : '');}
let lrcfile = ""; let lrcfile = "";
let richsync = []; let richsync = [];
const lang = app.cfg.lyrics.mxm_language // translation language const lang = app.cfg.lyrics.mxm_language // translation language
@ -3027,67 +3071,13 @@ const app = new Vue({
return Math.random().toString(36).replace(/[^a-z]+/g, '').slice(2, 10); return Math.random().toString(36).replace(/[^a-z]+/g, '').slice(2, 10);
} }
/* get token */
function getToken(mode, track, artist, songid, lang, time, id) { function getMXMSubs(track, artist, lang, time, id) {
if (attempt > 2) { let richsyncQuery = app.cfg.lyrics.mxm_karaoke
app.loadNeteaseLyrics(); let itunesid = (id && id != "") ? id : ''; // Mode 1 -> Subs
// app.loadAMLyrics(); let url = "https://api.cider.sh/v1/lyrics?" + "mode=1" + "&richsyncQuery=" + richsyncQuery + "&track=" + track + "&artist=" + artist + "&songID=" + itunesid + "&source=mxm" + "&lang=" + lang + "&time=" + time;
} else {
attempt = attempt + 1;
let url = "https://apic-desktop.musixmatch.com/ws/1.1/token.get?app_id=web-desktop-app-v1.0&t=" + revisedRandId();
let req = new XMLHttpRequest(); let req = new XMLHttpRequest();
req.overrideMimeType("application/json"); req.overrideMimeType("application/json");
req.open('GET', url, true);
req.setRequestHeader("authority", "apic-desktop.musixmatch.com");
req.onload = function () {
try {
let jsonResponse = JSON.parse(this.responseText);
let status2 = jsonResponse["message"]["header"]["status_code"];
if (status2 == 200) {
let token = jsonResponse["message"]["body"]["user_token"] ?? '';
if (token != "" && token != "UpgradeOnlyUpgradeOnlyUpgradeOnlyUpgradeOnly") {
console.debug('200 token', mode);
// token good
app.mxmtoken = token;
if (mode == 1) {
getMXMSubs(track, artist, app.mxmtoken, lang, time, id);
} else {
getMXMTrans(songid, lang, app.mxmtoken);
}
} else {
console.debug('fake 200 token');
getToken(mode, track, artist, songid, lang, time)
}
} else {
// console.log('token 4xx');
getToken(mode, track, artist, songid, lang, time)
}
} catch (e) {
console.log('error');
app.loadQQLyrics();
//app.loadAMLyrics();
}
};
req.onerror = function () {
console.log('error');
app.loadQQLyrics();
// app.loadAMLyrics();
};
req.send();
}
}
function getMXMSubs(track, artist, token, lang, time, id) {
let usertoken = encodeURIComponent(token);
let richsyncQuery = (app.cfg.lyrics.mxm_karaoke) ? "&optional_calls=track.richsync" : ""
let timecustom = (!time || (time && time < 0)) ? '' : `&f_subtitle_length=${time}&q_duration=${time}&f_subtitle_length_max_deviation=40`;
let itunesid = (id && id != "") ? `&track_itunes_id=${id}` : '';
let url = "https://apic-desktop.musixmatch.com/ws/1.1/macro.subtitles.get?format=json&namespace=lyrics_richsynched" + richsyncQuery + "&subtitle_format=lrc&q_artist=" + artist + "&q_track=" + track + itunesid + "&usertoken=" + usertoken + timecustom + "&app_id=web-desktop-app-v1.0&t=" + revisedRandId();
let req = new XMLHttpRequest();
req.overrideMimeType("application/json");
req.open('GET', url, true);
req.setRequestHeader("authority", "apic-desktop.musixmatch.com");
req.onload = function () { req.onload = function () {
try { try {
let jsonResponse = JSON.parse(this.responseText); let jsonResponse = JSON.parse(this.responseText);
@ -3095,11 +3085,13 @@ const app = new Vue({
let status1 = jsonResponse["message"]["header"]["status_code"]; let status1 = jsonResponse["message"]["header"]["status_code"];
if (status1 == 200) { if (status1 == 200) {
let id = ''; let id, songLang = '';
try { try {
if (jsonResponse["message"]["body"]["macro_calls"]["matcher.track.get"]["message"]["header"]["status_code"] == 200 && jsonResponse["message"]["body"]["macro_calls"]["track.subtitles.get"]["message"]["header"]["status_code"] == 200) { if (jsonResponse["message"]["body"]["macro_calls"]["matcher.track.get"]["message"]["header"]["status_code"] == 200 && jsonResponse["message"]["body"]["macro_calls"]["track.subtitles.get"]["message"]["header"]["status_code"] == 200) {
id = jsonResponse["message"]["body"]["macro_calls"]["matcher.track.get"]["message"]["body"]["track"]["track_id"] ?? ''; id = jsonResponse["message"]["body"]["macro_calls"]["matcher.track.get"]["message"]["body"]["track"]["track_id"] ?? '';
lrcfile = jsonResponse["message"]["body"]["macro_calls"]["track.subtitles.get"]["message"]["body"]["subtitle_list"][0]["subtitle"]["subtitle_body"]; lrcfile = jsonResponse["message"]["body"]["macro_calls"]["track.subtitles.get"]["message"]["body"]["subtitle_list"][0]["subtitle"]["subtitle_body"];
vanity_id = jsonResponse["message"]["body"]["macro_calls"]["matcher.track.get"]["message"]["body"]["track"]["commontrack_vanity_id"];
songLang = jsonResponse["message"]["body"]["macro_calls"]["track.lyrics.get"]["message"]["body"]["lyrics"]["lyrics_language_description"];
try { try {
let lrcrich = jsonResponse["message"]["body"]["macro_calls"]["track.richsync.get"]["message"]["body"]["richsync"]["richsync_body"]; let lrcrich = jsonResponse["message"]["body"]["macro_calls"]["track.richsync.get"]["message"]["body"]["richsync"]["richsync_body"];
@ -3114,7 +3106,7 @@ const app = new Vue({
// app.loadAMLyrics() // app.loadAMLyrics()
} else { } else {
if (richsync == [] || richsync.length == 0) { if (richsync == [] || richsync.length == 0) {
console.log("ok"); console.log("musixmatch worki");
// process lrcfile to json here // process lrcfile to json here
app.lyricsMediaItem = lrcfile app.lyricsMediaItem = lrcfile
let u = app.lyricsMediaItem.split(/[\r\n]/); let u = app.lyricsMediaItem.split(/[\r\n]/);
@ -3155,24 +3147,21 @@ const app = new Vue({
}); });
app.lyrics = preLrc; app.lyrics = preLrc;
} }
if (lrcfile != null && lrcfile != '') {
// load translation // Load translation
getMXMTrans(id, lang, token); if (songLang.toLowerCase() !== lang){
} else { getMXMTrans(lang, vanity_id);
// app.loadAMLyrics()
app.loadQQLyrics();
} }
} }
} catch (e) { } catch (e) {
console.log(e); console.log(e);
app.loadQQLyrics(); app.loadQQLyrics();
// app.loadAMLyrics() // app.loadAMLyrics()
} }
} else { //4xx rejected
getToken(1, track, artist, '', lang, time);
} }
} catch (e) { } catch (e) {
console.log(e); console.error(e);
app.loadQQLyrics(); app.loadQQLyrics();
//app.loadAMLyrics() //app.loadAMLyrics()
} }
@ -3182,59 +3171,59 @@ const app = new Vue({
console.log('error'); console.log('error');
// app.loadAMLyrics(); // app.loadAMLyrics();
}; };
req.open('POST', url, true);
req.send(); req.send();
} }
function getMXMTrans(id, lang, token) { function getMXMTrans(lang, vanity_id) {
if (lang != "disabled" && id != '') {
let usertoken = encodeURIComponent(token);
let url2 = "https://apic-desktop.musixmatch.com/ws/1.1/crowd.track.translations.get?translation_fields_set=minimal&selected_language=" + lang + "&track_id=" + id + "&comment_format=text&part=user&format=json&usertoken=" + usertoken + "&app_id=web-desktop-app-v1.0&t=" + revisedRandId();
let req2 = new XMLHttpRequest();
req2.overrideMimeType("application/json");
req2.open('GET', url2, true);
req2.setRequestHeader("authority", "apic-desktop.musixmatch.com");
req2.onload = function () {
try { try {
let jsonResponse2 = JSON.parse(this.responseText); if (lang != "disabled" && vanity_id != '') { // Mode 2 -> Trans
console.log(jsonResponse2); fetch('https://www.musixmatch.com/lyrics/' + vanity_id +'/translation/' + lang, {
let status2 = jsonResponse2["message"]["header"]["status_code"]; method: 'GET',
if (status2 == 200) { headers: {
try { 'Host': 'musixmatch.com',
let preTrans = [] 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
let u = app.lyrics; 'authority': "www.musixmatch.com"
let translation_list = jsonResponse2["message"]["body"]["translations_list"]; },
if (translation_list.length > 0) { })
for (var i = 0; i < u.length - 1; i++) { .then(async (res) => {
preTrans[i] = "" if (res.status != 200) {return}
for (var trans_line of translation_list) { let html = document.createElement('html'); html.innerHTML = await res.text()
if (u[i].line == " " + trans_line["translation"]["matched_line"] || u[i].line == trans_line["translation"]["matched_line"]) { let lyric_isolated = html.querySelector("#site > div > div > div > main > div > div > div.mxm-track-lyrics-container > div.container > div > div > div > div.col-sm-12.col-md-10.col-ml-9.col-lg-9 > div.mxm-lyrics.translated > div.row > div.col-xs-12.col-sm-12.col-md-12.col-ml-12.col-lg-12")
u[i].translation = trans_line["translation"]["description"]; let raw_lines = lyric_isolated.getElementsByClassName("col-xs-6 col-sm-6 col-md-6 col-ml-6 col-lg-6")
break; let applied = 0;
for (let i = 1; applied < app.lyrics.length; i+=2) { // Start on odd elements because even ones are original.
if (raw_lines[i].childNodes[0].childNodes[0].textContent.trim() == "") {i+=2;}
if (app.lyrics[applied].line.trim() == "") {applied+=1;}
if (app.lyrics[applied].line.trim() === raw_lines[i].childNodes[0].childNodes[0].textContent.trim().replace('', "'")) {
// Do Nothing
applied +=1;
}
else {
if (app.lyrics[applied].line === "lrcInstrumental") {
if (app.lyrics[applied+1].line.trim() === raw_lines[i].childNodes[0].childNodes[0].textContent.trim()) {
// Do Nothing
applied +=2;
}
else {
app.lyrics[applied+1].translation = raw_lines[i].childNodes[0].childNodes[0].textContent.trim();
applied +=2;
}
}
else {
app.lyrics[applied].translation = raw_lines[i].childNodes[0].childNodes[0].textContent.trim();
applied +=1;
} }
} }
} }
app.lyrics = u; })
}
} catch (e) {
/// not found trans -> ignore
}
} else { //4xx rejected
getToken(2, '', '', id, lang, '');
}
} catch (e) {
}
}
req2.send();
} }
} catch (e) {console.debug("Error while parsing MXM Trans: " + e)}
} }
if (track != "" & track != "No Title Found") { if (track != "" & track != "No Title Found") {
if (app.mxmtoken != null && app.mxmtoken != '') { getMXMSubs(track, artist, lang, time, id);
getMXMSubs(track, artist, app.mxmtoken, lang, time, id)
} else {
getToken(1, track, artist, '', lang, time);
}
} }
}, },
loadNeteaseLyrics() { loadNeteaseLyrics() {
@ -3976,9 +3965,8 @@ const app = new Vue({
this.currentArtUrl = this.mk.nowPlayingItem._assets[0].artworkURL this.currentArtUrl = this.mk.nowPlayingItem._assets[0].artworkURL
} }
try { try {
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`); // document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
} catch (e) { } catch (e) {}
}
} else { } else {
let data = await this.mk.api.v3.music(`/v1/me/library/songs/${this.mk.nowPlayingItem.id}`); let data = await this.mk.api.v3.music(`/v1/me/library/songs/${this.mk.nowPlayingItem.id}`);
data = data.data.data[0]; data = data.data.data[0];
@ -3990,14 +3978,14 @@ const app = new Vue({
} }
ipcRenderer.send('updateRPCImage', this.currentArtUrl ?? ''); ipcRenderer.send('updateRPCImage', this.currentArtUrl ?? '');
try { try {
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`); // document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
} catch (e) { } catch (e) {
} }
} else { } else {
this.currentArtUrlRaw = '' this.currentArtUrlRaw = ''
this.currentArtUrl = ''; this.currentArtUrl = '';
try { try {
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`); // document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
} catch (e) { } catch (e) {
} }
} }
@ -4441,21 +4429,30 @@ const app = new Vue({
case "audiolabs": case "audiolabs":
this.$store.state.pageState.settings.currentTabIndex = 2 this.$store.state.pageState.settings.currentTabIndex = 2
break; break;
case "visual": case "styles":
this.$store.state.pageState.settings.currentTabIndex = 3 this.$store.state.pageState.settings.currentTabIndex = 3
break; break;
case "lyrics": case "visual":
this.$store.state.pageState.settings.currentTabIndex = 4 this.$store.state.pageState.settings.currentTabIndex = 4
break; break;
case "connectivity": case "github-plugins":
this.$store.state.pageState.settings.currentTabIndex = 5 this.$store.state.pageState.settings.currentTabIndex = 5
break; break;
case "advanced": case "lyrics":
this.$store.state.pageState.settings.currentTabIndex = 6 this.$store.state.pageState.settings.currentTabIndex = 6
break; break;
case "keybindings": case "connectivity":
this.$store.state.pageState.settings.currentTabIndex = 7 this.$store.state.pageState.settings.currentTabIndex = 7
break; break;
case "advanced":
this.$store.state.pageState.settings.currentTabIndex = 8
break;
case "keybindings":
this.$store.state.pageState.settings.currentTabIndex = 9
break;
case "github-themes":
this.$store.state.pageState.settings.currentTabIndex = 10
break;
} }
app.modals.settings = true app.modals.settings = true
}, },

View file

@ -1,5 +1,6 @@
const store = new Vuex.Store({ const store = new Vuex.Store({
state: { state: {
windowRelativeScale: 1,
library: { library: {
// songs: ipcRenderer.sendSync("get-library-songs"), // songs: ipcRenderer.sendSync("get-library-songs"),
// albums: ipcRenderer.sendSync("get-library-albums"), // albums: ipcRenderer.sendSync("get-library-albums"),

View file

@ -14,6 +14,7 @@
@import url("less/pages.less"); @import url("less/pages.less");
:root { :root {
--windowRelativeScale: 1;
--appleEase: cubic-bezier(0.42, 0, 0.58, 1); --appleEase: cubic-bezier(0.42, 0, 0.58, 1);
--borderColor: rgb(200 200 200 / 16%); --borderColor: rgb(200 200 200 / 16%);
--mediaItemShadow: inset 0px 0px 0px 1px rgb(200 200 200 / 16%); --mediaItemShadow: inset 0px 0px 0px 1px rgb(200 200 200 / 16%);
@ -1885,6 +1886,25 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
} }
} }
.social-btn {
border-radius: 100%;
background: transparent;
height: 17px;
border: 0px;
cursor: pointer;
z-index: 69;
display: flex;
justify-content: center;
align-items: center;
float: right;
}
@media only screen and (min-width: 1133px) and (max-width: 1277px) {
.social-btn {
display: none !important;
}
}
.about-page { .about-page {
.teamBtn { .teamBtn {
display: flex; display: flex;
@ -2037,7 +2057,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
// screen size > 1200px // screen size > 1200px
@media screen and (min-width: 1500px) { @media screen and (min-width: 1500px) {
grid-template-columns: repeat(6, minmax(200px, 1fr)); grid-template-columns: repeat(5, minmax(200px, 1fr));
} }
// less than 1100px // less than 1100px
@media screen and (max-width: 1150px) { @media screen and (max-width: 1150px) {

View file

@ -146,7 +146,7 @@
<img v-if="!(cfg.visual.bg_artwork_rotation && animateBackground)" class="bg-artwork no-animation" :src="$store.state.artwork.playerLCD"> <img v-if="!(cfg.visual.bg_artwork_rotation && animateBackground)" class="bg-artwork no-animation" :src="$store.state.artwork.playerLCD">
</div> </div>
</div> </div>
<lyrics-view v-if="drawer.panel == 'lyrics'" :time="lyriccurrenttime" :lyrics="lyrics" <lyrics-view v-if="drawer.panel == 'lyrics'" :time="mk.currentPlaybackTime - lyricOffset" :lyrics="lyrics"
:richlyrics="richlyrics"></lyrics-view> :richlyrics="richlyrics"></lyrics-view>
<div v-if="drawer.panel == 'lyrics'" class="lyric-footer"> <div v-if="drawer.panel == 'lyrics'" class="lyric-footer">
<button class="md-btn" @click="modularUITest(!fullscreenLyrics)">{{fullscreenLyrics ? <button class="md-btn" @click="modularUITest(!fullscreenLyrics)">{{fullscreenLyrics ?

View file

@ -5,7 +5,7 @@
<div class="app-playback-controls" @mouseover="chrome.progresshover = true" <div class="app-playback-controls" @mouseover="chrome.progresshover = true"
@mouseleave="chrome.progresshover = false" @contextmenu="nowPlayingContextMenu"> @mouseleave="chrome.progresshover = false" @contextmenu="nowPlayingContextMenu">
<div class="artwork" id="artworkLCD"> <div class="artwork" id="artworkLCD">
<mediaitem-artwork :url="currentArtUrl"></mediaitem-artwork> <mediaitem-artwork :url="$root.currentArtUrl"></mediaitem-artwork>
</div> </div>
<b-popover custom-class="mediainfo-popover" target="artworkLCD" triggers="hover" placement="right"> <b-popover custom-class="mediainfo-popover" target="artworkLCD" triggers="hover" placement="right">
<div class="content"> <div class="content">

View file

@ -1,6 +1,7 @@
<script type="text/x-template" id="mediaitem-artwork"> <script type="text/x-template" id="mediaitem-artwork">
<div class="mediaitem-artwork" :style="awStyle" @contextmenu="contextMenu" :class="[{'rounded': (type == 'artists')}, classes]" :key="url"> <div class="mediaitem-artwork" :style="awStyle" @contextmenu="contextMenu" :class="[{'rounded': (type == 'artists')}, classes]" :key="url">
<img :src="app.getMediaItemArtwork(url, size, width)" <img :src="imgSrc"
ref="image"
decoding="async" decoding="async"
loading="lazy" loading="lazy"
:style="imgStyle" :style="imgStyle"
@ -47,6 +48,10 @@
shadow: { shadow: {
type: String, type: String,
default: '' default: ''
},
upscaling: {
type: Boolean,
default: false
} }
}, },
data: function () { data: function () {
@ -63,15 +68,37 @@
opacity: 0, opacity: 0,
transition: "opacity .25s linear" transition: "opacity .25s linear"
}, },
classes: [] classes: [],
imgSrc: ""
}
},
computed: {
windowRelativeScale: function () {
return app.$store.state.windowRelativeScale;
}
},
watch: {
windowRelativeScale: function (newValue, oldValue) {
this.swapImage(newValue)
},
url: function (newValue, oldValue) {
this.imgSrc = app.getMediaItemArtwork(this.url, this.size, this.width)
} }
}, },
mounted() { mounted() {
this.getClasses() this.getClasses()
this.imgSrc = app.getMediaItemArtwork(this.url, this.size, this.width)
}, },
methods: { methods: {
swapImage(newValue) {
if(!this.upscaling || window.devicePixelRatio !== 1) return
if (newValue > 1.5) {
this.imgSrc = app.getMediaItemArtwork(this.url, parseInt(this.size * 2.0), parseInt(this.size * 2.0));
}
},
imgLoaded() { imgLoaded() {
this.imgStyle.opacity = 1 this.imgStyle.opacity = 1
this.swapImage(app.$store.state.windowRelativeScale)
// this.awStyle.background = "" // this.awStyle.background = ""
}, },
contextMenu(event) { contextMenu(event) {

View file

@ -16,7 +16,7 @@
@controller-click="route()" @controller-click="route()"
tabindex="0" tabindex="0"
:class="[{'mediaitem-selected': app.select_hasMediaItem(guid)}, addClasses]"> :class="[{'mediaitem-selected': app.select_hasMediaItem(guid)}, addClasses]">
<div v-if="isVisible" class="listitem-content"> <div v-show="isVisible" class="listitem-content">
<div class="popular" v-if="!showInLibrary && item?.meta?.popularity != null && item?.meta?.popularity > 0.7"></div> <div class="popular" v-if="!showInLibrary && item?.meta?.popularity != null && item?.meta?.popularity > 0.7"></div>
<div class="isLibrary" v-if="showLibraryStatus == true"> <div class="isLibrary" v-if="showLibraryStatus == true">
<div v-if="showInLibrary" :style="{display: (showInLibrary ? 'block' : 'none'), 'margin-left':'11px'}"> <div v-if="showInLibrary" :style="{display: (showInLibrary ? 'block' : 'none'), 'margin-left':'11px'}">

View file

@ -17,6 +17,7 @@
:url="getArtworkUrl()" :url="getArtworkUrl()"
:video="(item.attributes != null && item.attributes.editorialVideo != null) ? (item.attributes.editorialVideo.motionDetailSquare ? item.attributes.editorialVideo.motionDetailSquare.video : (item.attributes.editorialVideo.motionSquareVideo1x1 ? item.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' " :video="(item.attributes != null && item.attributes.editorialVideo != null) ? (item.attributes.editorialVideo.motionDetailSquare ? item.attributes.editorialVideo.motionDetailSquare.video : (item.attributes.editorialVideo.motionSquareVideo1x1 ? item.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
:size="size" :size="size"
:upscaling="true"
shadow="subtle" shadow="subtle"
:bgcolor="getBgColor()" :bgcolor="getBgColor()"
:video-priority="forceVideo" :video-priority="forceVideo"

View file

@ -0,0 +1,323 @@
<script type="text/x-template" id="keybinds-settings">
<div class="keybinds-page">
<div class="md-option-header">
<span>{{$root.getLz('settings.option.general.keybindings')}}</span>
</div>
<div class="settings-option-body">
<div class="md-option-header-sub">
<span>{{$root.getLz('settings.option.general.keybindings.library')}}</span>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.search')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('search')">
{{app.cfg.general.keybindings.search.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.listnow')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('listnow')">
{{app.cfg.general.keybindings.listnow.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.browse')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('browse')">
{{app.cfg.general.keybindings.browse.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.recentAdd')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('recentAdd')">
{{app.cfg.general.keybindings.recentAdd.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.songs')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('songs')">
{{app.cfg.general.keybindings.songs.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.albums')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('albums')">
{{app.cfg.general.keybindings.albums.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.artists')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('artists')">
{{app.cfg.general.keybindings.artists.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-header-sub">
<span>{{$root.getLz('settings.option.general.keybindings.session')}}</span>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.private')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('togglePrivateSession')">
{{app.cfg.general.keybindings.togglePrivateSession.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-header-sub">
<span>{{$root.getLz('settings.option.general.keybindings.control')}}</span>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.remote')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('webRemote')">
{{app.cfg.general.keybindings.webRemote.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.audio')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('audioSettings')">
{{app.cfg.general.keybindings.audioSettings.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.plugins')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('pluginMenu')">
{{app.cfg.general.keybindings.pluginMenu.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.cast')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('castToDevices')">
{{app.cfg.general.keybindings.castToDevices.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.settings')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('settings')">
{{app.cfg.general.keybindings.settings.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-header-sub" v-if="app.platform !== 'darwin'">
<span>{{$root.getLz('settings.option.general.keybindings.interface')}}</span>
</div>
<div class="md-option-line" v-if="app.platform !== 'darwin'">
<div class="md-option-segment">
{{$root.getLz('term.zoomin')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('zoomn')">
{{app.cfg.general.keybindings.zoomn.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line" v-if="app.platform !== 'darwin'">
<div class="md-option-segment">
{{$root.getLz('term.zoomout')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('zoomt')">
{{app.cfg.general.keybindings.zoomt.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-line" v-if="app.platform !== 'darwin'">
<div class="md-option-segment">
{{$root.getLz('term.zoomreset')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('zoomrst')">
{{app.cfg.general.keybindings.zoomrst.join(' + ')}}
</button>
</div>
</div>
<div class="md-option-header-sub">
<span>{{$root.getLz('settings.option.general.keybindings.advanced')}}</span>
</div>
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.description.developer')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn md-btn-small md-btn-block"
@click="keyBindUpdate('openDeveloperTools')">
{{app.cfg.general.keybindings.openDeveloperTools.join(' + ')}}
</button>
</div>
</div>
<button class="md-btn md-btn-large md-btn-block" @click="keyBindReset()">
{{$root.getLz('term.reset')}}
</button>
</div>
</div>
</script>
<script>
Vue.component('keybinds-settings', {
template: "#keybinds-settings",
props: [],
data: function () {
return {
app: this.$root
}
},
methods: {
keyBindUpdate: function (action) {
const blur = document.createElement('div');
blur.className = 'blur';
blur.style.backgroundColor = 'rgba(0,0,0,0.25)';
blur.style.position = 'fixed';
blur.style.top = '0';
blur.style.left = '0';
blur.style.width = '100%';
blur.style.height = '100%';
blur.style.zIndex = '9999';
blur.style.display = 'flex';
blur.style.alignItems = 'center';
blur.style.justifyContent = 'center';
blur.style.fontSize = '2em';
blur.style.color = 'white';
blur.innerHTML = `<center>${app.getLz('settings.option.general.keybindings.pressCombination')}<br />${app.getLz('settings.option.general.keybindings.pressEscape')}</center>`
document.body.appendChild(blur);
let keyBind = [];
const keyBindTimeout = setTimeout(function () {
keyBind = [];
document.body.removeChild(blur);
}, 30000);
const keyBindUpdate = function (e) {
if (document.body.contains(blur)) {
if (e.key == 'Escape') {
document.body.removeChild(blur);
clearTimeout(keyBindTimeout);
return;
} else {
if (e.keyCode >= 65 && e.keyCode <= 90 && e.keyCode <= 97 && e.keyCode <= 122) {
keyBind.push(e.key.toUpperCase());
} else {
keyBind.push(e.key);
}
if (keyBind.length === 2) {
if (keyBind[0] !== keyBind[1]) {
app.cfg.general.keybindings[action] = keyBind
document.body.removeChild(blur);
clearTimeout(keyBindTimeout);
notyf.success(app.getLz('settings.notyf.general.keybindings.update.success'));
app.confirm(app.getLz("settings.prompt.general.keybindings.update.success"), (ok) => {
if (ok) ipcRenderer.invoke("relaunchApp")
})
} else {
keyBind = [];
}
}
}
}
};
document.addEventListener('keydown', keyBindUpdate);
},
keyBindReset: function () {
app.cfg.general.keybindings.search = [app.platform == "darwin" ? "Command" : "Control", "F"];
app.cfg.general.keybindings.listnow = [app.platform == "darwin" ? "Command" : "Control", "L"];
app.cfg.general.keybindings.browse = [app.platform == "darwin" ? "Command" : "Control", "B"];
app.cfg.general.keybindings.recentAdd = [app.platform == "darwin" ? "Command" : "Control", "G"];
app.cfg.general.keybindings.songs = [app.platform == "darwin" ? "Command" : "Control", "J"];
app.cfg.general.keybindings.albums = [app.platform == "darwin" ? "Command" : "Control", "A"];
app.cfg.general.keybindings.artists = [app.platform == "darwin" ? "Command" : "Control", "D"];
app.cfg.general.keybindings.togglePrivateSession = [app.platform == "darwin" ? "Command" : "Control", "P"];
app.cfg.general.keybindings.webRemote = [app.platform == "darwin" ? "Command" : "Control",app.platform == "darwin" ? "Option" : (app.platform == "linux" ? "Shift" : "Alt"), "W"];
app.cfg.general.keybindings.audioSettings = [app.platform == "darwin" ? "Command" : "Control",app.platform == "darwin" ? "Option" : (app.platform == "linux" ? "Shift" : "Alt"), "A"];
app.cfg.general.keybindings.pluginMenu = [app.platform == "darwin" ? "Command" : "Control",app.platform == "darwin" ? "Option" : (app.platform == "linux" ? "Shift" : "Alt"), "P"];
app.cfg.general.keybindings.castToDevices = [app.platform == "darwin" ? "Command" : "Control",app.platform == "darwin" ? "Option" : (app.platform == "linux" ? "Shift" : "Alt"), "C"];
app.cfg.general.keybindings.settings = [app.platform == "darwin" ? "Command" : "Control", ","];
app.cfg.general.keybindings.zoomn = [app.platform == "darwin" ? "Command" : "Control", "numadd"];
app.cfg.general.keybindings.zoomt = [app.platform == "darwin" ? "Command" : "Control", "numsub"];
app.cfg.general.keybindings.zoomrst = [app.platform == "darwin" ? "Command" : "Control", "num0"];
app.cfg.general.keybindings.openDeveloperTools = [app.platform == "darwin" ? "Command" : "Control", app.platform == "darwin" ? "Option" : "Shift", "I"];
notyf.success(app.getLz('settings.notyf.general.keybindings.update.success'));
app.confirm(app.getLz("settings.prompt.general.keybindings.update.success"), (ok) => {
if (ok) ipcRenderer.invoke("relaunchApp")
})
},
getLanguages: function () {
let langs = this.$root.lzListing
let categories = {
"main": [],
"fun": [],
"unsorted": []
}
// sort by category if category is undefined or empty put it in "unsorted"
for (let i = 0; i < langs.length; i++) {
if (langs[i].category === undefined || langs[i].category === "") {
categories.unsorted.push(langs[i])
} else {
categories[langs[i].category].push(langs[i])
}
}
// return
return categories
},
}
})
</script>

View file

@ -0,0 +1,188 @@
<script type="text/x-template" id="plugins-github">
<div class="github-themes-page">
<div class="gh-header">
<div class="row">
<div class="col nopadding">
<h1 class="header-text">{{$root.getLz('settings.header.visual.plugin.github.page')}}</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.plugin.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)' : '', 'border-radius': '5px'}"
v-for="repo in repos">
<div class="row">
<div class="col flex-center">
<div>
<h4 class="repo-name">{{ (repo.description != null) ? repo.description : repo.full_name }}</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)">{{$root.getLz('action.install')}}</span>
<span v-else>{{$root.getLz('action.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('plugins-github', {
template: "#plugins-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) {
return marked.parse(text)
},
installThemeRepo(repo) {
let self = this
let msg = app.stringTemplateParser(app.getLz('settings.option.visual.plugin.github.install.confirm'), {
repo: repo.full_name
});
app.confirm(msg, (res) => {
if (res) {
ipcRenderer.once("plugin-installed", (event, arg) => {
if (arg.success) {
self.themes = []
notyf.success(app.getLz('settings.notyf.visual.plugin.install.success'));
app.confirm(app.getLz("settings.prompt.visual.plugin.github.success"), (ok)=>{
if (ok) {
ipcRenderer.invoke("relaunchApp")
} else {
return
}
})
} else {
notyf.error(app.getLz('settings.notyf.visual.plugin.install.error'));
}
});
ipcRenderer.invoke("get-github-plugin", repo.html_url)
}
})
},
installThemeURL() {
let self = this
app.prompt(app.getLz('settings.prompt.visual.plugin.github.URL'), (result) => {
if (result) {
ipcRenderer.once("plugin-installed", (event, arg) => {
if (arg.success) {
self.themes = ipcRenderer.sendSync("get-themes")
app.confirm(app.getLz("settings.prompt.visual.plugin.github.success"), (ok)=>{
if (ok) {
ipcRenderer.invoke("relaunchApp")
} else {
return
}
})
notyf.success(app.getLz('settings.notyf.visual.plugin.install.success'));
} else {
notyf.error(app.getLz('settings.notyf.visual.plugin.install.error'));
}
});
ipcRenderer.invoke("get-github-plugin", result)
}
});
},
getRepos() {
let self = this
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
fetch("https://api.github.com/search/repositories?q=topic:cidermusicplugin fork:true&per_page=100", requestOptions)
.then(response => response.text())
.then(result => {
self.repos = JSON.parse(result).items
})
.catch(error => console.log('error', error));
}
}
})
</script>

View file

@ -0,0 +1,197 @@
<script type="text/x-template" id="themes-github">
<div class="github-themes-page">
<div class="gh-header">
<div class="row">
<div class="col nopadding">
<h1 class="header-text">{{$root.getLz('settings.header.visual.theme.github.page')}}</h1>
</div>
<div class="col-auto nopadding flex-center">
<button class="md-btn md-btn-small md-btn-block" @click="$root.openSettingsPage('styles')">
{{$root.getLz('settings.option.visual.theme.manageStyles')}}
</button>
</div>
<div class="col-auto flex-center">
<button class="md-btn md-btn-small md-btn-block" @click="$root.checkForThemeUpdates()">
{{ $root.getLz('settings.option.visual.theme.checkForUpdates') }}
</button>
</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 != null) ? repo.description :
repo.full_name }}</h4>
<div>⭐ {{ repo.stargazers_count }}</div>
</div>
</div>
<div class="col-auto">
<span v-if="themesInstalled.includes(repo.full_name.toLowerCase())"
class="codicon codicon-cloud-download"></span>
</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.toLowerCase())">{{$root.getLz('action.install')}}</span>
<span v-else>{{$root.getLz('action.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: [],
themes: []
}
},
mounted() {
this.themes = ipcRenderer.sendSync("get-themes")
this.getRepos();
this.getInstalledThemes();
},
methods: {
openThemesFolder() {
ipcRenderer.invoke("open-path", "themes")
},
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 !== "" && typeof theme.commit != "") {
self.themesInstalled.push(theme.github_repo.toLowerCase())
}
})
},
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) {
return marked.parse(text)
},
installThemeRepo(repo) {
let self = this
let msg = app.stringTemplateParser(app.getLz('settings.option.visual.theme.github.install.confirm'), {
repo: repo.full_name
});
app.confirm(msg, (res) => {
if (res) {
ipcRenderer.once("theme-installed", (event, arg) => {
if (arg.success) {
self.themes = ipcRenderer.sendSync("get-themes")
self.getInstalledThemes()
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
app.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&per_page=100", requestOptions)
.then(response => response.text())
.then(result => {
let items = JSON.parse(result).items
self.repos = items
})
.catch(error => console.log('error', error));
}
}
})
</script>

View file

@ -0,0 +1,367 @@
<script type="text/x-template" id="installed-themes">
<div class="installed-themes-page">
<div class="gh-header">
<div class="row">
<div class="col nopadding">
<h1 class="header-text">
{{ $root.getLz("settings.option.visual.theme.manageStyles") }}
</h1>
</div>
<div class="col-auto nopadding flex-center">
<button class="md-btn md-btn-small md-btn-block" @click="$root.openSettingsPage('github-themes')">
{{$root.getLz('settings.option.visual.theme.github.explore')}}
</button>
</div>
<div class="col-auto flex-center">
<button class="md-btn md-btn-small md-btn-block" @click="$root.checkForThemeUpdates()">
{{ $root.getLz('settings.option.visual.theme.checkForUpdates') }}
</button>
</div>
<div class="col-auto nopadding flex-center">
<button class="md-btn md-btn-small md-btn-block" @click="openThemesFolder()">
{{$root.getLz('settings.option.visual.theme.github.openfolder')}}
</button>
</div>
</div>
</div>
<div class="gh-content">
<div class="repos-list">
<div class="repo-header">
<h4>{{$root.getLz('settings.option.visual.theme.github.available')}}</h4>
</div>
<ul class="list-group list-group-flush">
<template v-for="theme in themes">
<li @click="addStyle(theme.file)"
@contextmenu="contextMenu($event, theme)"
class="list-group-item list-group-item-dark"
:class="{'applied': $root.cfg.visual.styles.includes(theme.file)}">
<b-row>
<b-col class="themeLabel">{{theme.name}}</b-col>
<template v-if="$root.cfg.visual.styles.includes(theme.file)">
<b-col sm="auto" v-if="theme.pack">
<button class="themeContextMenu codicon codicon-package"></button>
</b-col>
<b-col sm="auto">
<button class="themeContextMenu codicon codicon-check"></button>
</b-col>
</template>
<template v-else>
<b-col sm="auto" v-if="theme.pack">
<button class="themeContextMenu codicon codicon-package"></button>
</b-col>
<b-col sm="auto">
<button @click.stop="contextMenu($event, theme)" class="themeContextMenu codicon codicon-list-unordered"></button>
</b-col>
</template>
</b-row>
</li>
<li @click="addStyle(packEntry.file)"
@contextmenu="contextMenu($event, theme)"
class="list-group-item list-group-item-dark addon"
v-for="packEntry in theme.pack"
:class="{'applied': $root.cfg.visual.styles.includes(packEntry.file)}"
v-if="theme.pack">
<b-row>
<b-col class="themeLabel">{{packEntry.name}}</b-col>
<template v-if="$root.cfg.visual.styles.includes(packEntry.file)">
<b-col sm="auto">
<button class="themeContextMenu codicon codicon-check"></button>
</b-col>
</template>
<template v-else>
<b-col sm="auto">
<button class="themeContextMenu codicon codicon-diff-added"></button>
</b-col>
</template>
</b-row>
</li>
</template>
</ul>
</div>
<div class="style-editor-container">
<div class="repo-header">
<h4>{{ $root.getLz("settings.option.visual.theme.github.applied") }} </h4>
</div>
<stylestack-editor ref="stackEditor" v-if="themes.length != 0" :themes="themes"/>
</div>
</div>
</div>
</script>
<script>
// do not translate
Vue.component('stylestack-editor', {
/*html*/
template: `
<div class="stylestack-editor" >
<draggable class="list-group" v-model="$root.cfg.visual.styles" @end="$root.reloadStyles()">
<b-list-group-item variant="dark" v-for="theme in $root.cfg.visual.styles" :key="theme">
<b-row>
<b-col sm="auto">
<div class="handle codicon codicon-grabber"></div>
</b-col>
<b-col class="themeLabel">{{getThemeName(theme)}}</b-col>
<b-col sm="auto">
<button class="removeItem codicon codicon-close" @click="remove(theme)"></button>
</b-col>
</b-row>
</b-list-group-item>
</draggable>
</div>
`,
props: {
themes: {
type: Array,
default: [],
required: true
}
},
data: function () {
return {
selected: null,
newTheme: null,
themeList: []
}
},
mounted() {
console.log(this.themes)
this.themeList = [...this.themes]
this.themeList.forEach(theme => {
if (theme.pack) {
theme.pack.forEach(packEntry => {
packEntry.file = theme.file.replace('index.less', '') + packEntry.file
this.themeList.push(packEntry)
})
}
})
},
methods: {
gitHubExplore() {
this.$root.openSettingsPage("github-themes")
},
getThemeName(filename) {
try {
return this.themeList.find(theme => theme.file === filename).name;
} catch (e) {
return filename;
}
},
moveUp() {
const styles = this.$root.cfg.visual.styles
const index = styles.indexOf(this.selected)
if (index > 0) {
styles.splice(index, 1)
styles.splice(index - 1, 0, this.selected)
}
this.$root.reloadStyles()
},
moveDown() {
const styles = this.$root.cfg.visual.styles
const index = styles.indexOf(this.selected)
if (index < styles.length - 1) {
styles.splice(index, 1)
styles.splice(index + 1, 0, this.selected)
}
this.$root.reloadStyles()
},
remove(style) {
const styles = this.$root.cfg.visual.styles
const index = styles.indexOf(style)
styles.splice(index, 1)
this.$root.reloadStyles()
},
addStyle(style) {
const styles = this.$root.cfg.visual.styles
styles.push(style)
this.$root.reloadStyles()
}
}
})
</script>
<script>
Vue.component('installed-themes', {
template: "#installed-themes",
props: [],
data: function () {
return {
repos: [],
openRepo: {
id: -1,
name: '',
description: '',
html_url: '',
stargazers_count: 0,
owner: {
avatar_url: ''
},
readme: ""
},
themesInstalled: [],
themes: []
}
},
mounted() {
this.getThemesList();
},
methods: {
getThemesList() {
let self = this
let themes = ipcRenderer.sendSync("get-themes")
themes.unshift({
name: "Acrylic Grain",
file: "grain.less"
})
themes.unshift({
name: "Sweetener",
file: "sweetener.less"
})
themes.unshift({
name: "Reduce Visuals",
file: "reduce_visuals.less"
})
// themes.unshift({
// name: "Inline Drawer",
// file: "inline_drawer.less"
// })
themes.unshift({
name: "Dark",
file: "dark.less"
})
this.themes = themes
},
contextMenu(event, theme) {
let self = this
let menu = {
items: {
"uninstall": {
name: app.getLz("settings.option.visual.theme.uninstall"),
disabled: true,
action: () => {
app.confirm(app.stringTemplateParser(app.getLz("settings.prompt.visual.theme.uninstallTheme"), {
theme: theme.name ?? theme.file
}), (res) => {
if (res) {
console.debug(theme)
ipcRenderer.once("theme-uninstalled", (event, args) => {
console.debug(event, args)
self.getThemesList()
})
ipcRenderer.invoke("uninstall-theme", theme.path)
}
})
}
},
"viewInfo": {
name: app.getLz("settings.option.visual.theme.viewInfo"),
disabled: true,
action: () => {
}
}
}
}
if (theme.path) {
menu.items.uninstall.disabled = false
}
this.$root.showMenuPanel(menu, event)
},
openThemesFolder() {
ipcRenderer.invoke("open-path", "themes")
},
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 !== "" && typeof theme.commit != "") {
self.themesInstalled.push(theme.github_repo.toLowerCase())
}
})
},
addStyle(filename) {
this.$refs.stackEditor.addStyle(filename)
},
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) {
return marked.parse(text)
},
installThemeRepo(repo) {
let self = this
let msg = app.stringTemplateParser(app.getLz('settings.option.visual.theme.github.install.confirm'), {
repo: repo.full_name
});
app.confirm(msg, (res) => {
if (res) {
ipcRenderer.once("theme-installed", (event, arg) => {
if (arg.success) {
self.themes = ipcRenderer.sendSync("get-themes")
self.getInstalledThemes()
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
app.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 => {
let items = JSON.parse(result).items
self.repos = items
})
.catch(error => console.log('error', error));
}
}
})
</script>

File diff suppressed because it is too large Load diff

View file

@ -145,7 +145,7 @@
Local Library Local Library
</div> </div>
<template v-if="!$root.cfg.general.sidebarCollapsed.localLibrary"> <template v-if="!$root.cfg.general.sidebarCollapsed.localLibrary">
<sidebar-playlist :item="{attributes: { name:'Songs'} , id:'ciderlocal'}"> <sidebar-playlist :item="{attributes: { name:'Songs'} , id:'ciderlocal'}"></sidebar-playlist>
</template> </template>
</template> </template>
<template v-if="$root.getPlaylistFolderChildren('p.applemusic').length != 0"> <template v-if="$root.getPlaylistFolderChildren('p.applemusic').length != 0">

View file

@ -86,13 +86,13 @@
</transition> </transition>
<transition name="fsModeSwitch"> <transition name="fsModeSwitch">
<div class="fullscreen-view-container" v-if="appMode == 'fullscreen'"> <div class="fullscreen-view-container" v-if="appMode == 'fullscreen'">
<fullscreen-view :image="currentArtUrlRaw" :time="lyriccurrenttime" :lyrics="lyrics" <fullscreen-view :image="currentArtUrlRaw" :time="mk.currentPlaybackTime - lyricOffset" :lyrics="lyrics"
:richlyrics="richlyrics"></fullscreen-view> :richlyrics="richlyrics"></fullscreen-view>
</div> </div>
</transition> </transition>
<transition name="fsModeSwitch"> <transition name="fsModeSwitch">
<div class="fullscreen-view-container" v-if="appMode == 'mini'"> <div class="fullscreen-view-container" v-if="appMode == 'mini'">
<mini-view :image="currentArtUrlRaw" :time="lyriccurrenttime" :lyrics="lyrics" :richlyrics="richlyrics"> <mini-view :image="currentArtUrlRaw" :time="mk.currentPlaybackTime - lyricOffset" :lyrics="lyrics" :richlyrics="richlyrics">
</mini-view> </mini-view>
</div> </div>
</transition> </transition>

View file

@ -25,17 +25,22 @@
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h3>{{$root.getLz('term.ciderTeam')}}</h3> <h3>{{$root.getLz('term.ciderTeam')}}</h3>
<button class="md-btn teamBtn" @click="window.open(member.link)" v-for="member in team"> <div class="md-btn teamBtn" v-for="member in team" @click="window.open(member.link)">
<img :src="member.avatar"/> <img :src="member.avatar"/>
<div class="row" style="width:100%;"> <div class="row" style="width:100%;">
<div class="col" style="text-align: left"> <div class="col" style="text-align: left;">
{{ member.name }} {{ member.name }}
</div> </div>
<div class="col" style="text-align: right">
<button @click.stop="window.open(member.twitter)" class="social-btn" v-if="member.twitter">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="white" style=""><path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"></path></svg>
</button>
</div>
<div class="col-auto"> <div class="col-auto">
<b>{{ member.role }}</b> <b>{{ member.role }}</b>
</div> </div>
</div> </div>
</button> </div>
</div> </div>
</div> </div>
</div> </div>
@ -64,25 +69,29 @@
name: 'cryptofyre', name: 'cryptofyre',
link: 'https://github.com/cryptofyre', link: 'https://github.com/cryptofyre',
role: app.getLz('term.developer'), role: app.getLz('term.developer'),
avatar: 'https://avatars.githubusercontent.com/u/33162551?v=4' avatar: 'https://avatars.githubusercontent.com/u/33162551?v=4',
twitter: 'https://twitter.com/cryptofyre'
}, },
{ {
name: 'Core', name: 'Core',
link: 'https://github.com/coredev-uk', link: 'https://github.com/coredev-uk',
role: app.getLz('term.developer'), role: app.getLz('term.developer'),
avatar: 'https://avatars.githubusercontent.com/u/64542347?v=4' avatar: 'https://avatars.githubusercontent.com/u/64542347?v=4',
twitter: 'https://twitter.com/core_hdd'
}, },
{ {
name: 'Quacksire', name: 'Quacksire',
link: 'https://github.com/quacksire', link: 'https://github.com/quacksire',
role: app.getLz('term.developer'), role: app.getLz('term.developer'),
avatar: 'https://avatars.githubusercontent.com/u/19170969?v=4' avatar: 'https://avatars.githubusercontent.com/u/19170969?v=4',
twitter: 'https://twitter.com/duckdoquack'
}, },
{ {
name: 'booploops', name: 'booploops',
link: 'https://github.com/booploops', link: 'https://github.com/booploops',
role: app.getLz('term.developer'), role: app.getLz('term.developer'),
avatar: 'https://avatars.githubusercontent.com/u/49113086?v=4' avatar: 'https://avatars.githubusercontent.com/u/49113086?v=4',
twitter: 'https://twitter.com/boopl00ps'
}, },
{ {
name: 'vapormusic', name: 'vapormusic',
@ -94,25 +103,29 @@
name: 'crypticplank', name: 'crypticplank',
link: 'https://github.com/crypticplank', link: 'https://github.com/crypticplank',
role: app.getLz('term.developer'), role: app.getLz('term.developer'),
avatar: 'https://avatars.githubusercontent.com/u/52553007?v=4' avatar: 'https://avatars.githubusercontent.com/u/52553007?v=4',
twitter: 'https://twitter.com/crypticplank'
}, },
{ {
name: 'Maikiwi', name: 'Maikiwi',
link: 'https://github.com/maikirakiwi', link: 'https://github.com/maikirakiwi',
role: app.getLz('term.developer'), role: app.getLz('term.developer'),
avatar: 'https://avatars.githubusercontent.com/u/74925636?v=4' avatar: 'https://avatars.githubusercontent.com/u/74925636?v=4',
twitter: 'https://twitter.com/notmaikiwi'
}, },
{ {
name: 'yazninja', name: 'yazninja',
link: 'https://github.com/yazninja', link: 'https://github.com/yazninja',
role: app.getLz('term.developer'), role: app.getLz('term.developer'),
avatar: 'https://avatars.githubusercontent.com/u/71800112?v=4' avatar: 'https://avatars.githubusercontent.com/u/71800112?v=4',
twitter: 'https://twitter.com/YazNinjaa'
}, },
{ {
name: 'GamingLiamStudios', name: 'GamingLiamStudios',
link: 'https://github.com/GamingLiamStudios', link: 'https://github.com/GamingLiamStudios',
role: app.getLz('term.developer'), role: app.getLz('term.developer'),
avatar: 'https://avatars.githubusercontent.com/u/58615717?v=4' avatar: 'https://avatars.githubusercontent.com/u/58615717?v=4',
twitter: 'https://twitter.com/GLStudios_'
}, },
{ {
name: 'Amaru', name: 'Amaru',

View file

@ -527,7 +527,7 @@
if (this.data.type.includes('albums')) { if (this.data.type.includes('albums')) {
let date = this.data.attributes.releaseDate; let date = this.data.attributes.releaseDate;
if (date == null || date === "") return ""; if (date == null || date === "") return "";
return `${this.data.relationships.tracks.data[0].attributes.genreNames[0]} · ${new Date(date).getFullYear()}` return `${this.data.attributes.genreNames[0]} · ${new Date(date).getFullYear()}`
} }
}, },
async isInLibrary() { async isInLibrary() {

View file

@ -1,5 +1,7 @@
<script type="text/x-template" id="installed-themes"> //Not used for Now
<div class="content-inner github-themes-page installed-themes-page">
<!-- <script type="text/x-template" id="installed-themes">
<div class="installed-themes-page">
<div class="gh-header"> <div class="gh-header">
<div class="row"> <div class="row">
<div class="col nopadding"> <div class="col nopadding">
@ -22,7 +24,6 @@
{{$root.getLz('settings.option.visual.theme.github.openfolder')}} {{$root.getLz('settings.option.visual.theme.github.openfolder')}}
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<div class="gh-content"> <div class="gh-content">
@ -365,4 +366,4 @@
} }
} }
}) })
</script> </script> -->

View file

@ -1,13 +1,13 @@
<script type="text/x-template" id="cider-recentlyadded"> <script type="text/x-template" id="cider-recentlyadded">
<div class="content-inner"> <div class="content-inner">
<h1 class="header-text">{{$root.getLz('term.recentlyAdded')}}</h1> <h1 class="header-text">{{$root.getLz('term.recentlyAdded')}}</h1>
<div class="well itemContainer" v-if="itemSize == 'normal'"> <div class="well itemContainer collection-list-square" v-if="itemSize == 'normal'">
<mediaitem-square v-for="item in items" :item="item"></mediaitem-square> <mediaitem-square v-for="item in items" :item="item"></mediaitem-square>
</div> </div>
<div class="well itemContainer" v-else="itemSize == 'compact'"> <div class="well itemContainer collection-list-square" v-else="itemSize == 'compact'">
<mediaitem-list-item :show-meta-data="true" :show-library-status="false" v-for="item in items" :item="item"></mediaitem-list-item> <mediaitem-list-item :show-meta-data="true" :show-library-status="false" v-for="item in items" :item="item"></mediaitem-list-item>
</div> </div>
<div class="well itemContainer" v-show="loading"> <div class="well itemContainer collection-list-square" v-show="loading">
<div class="spinner"></div> <div class="spinner"></div>
</div> </div>
<button v-if="nextUrl && !loading" style="opacity:0;height: 32px;" v-observe-visibility="{callback: visibilityChanged}">{{$root.getLz('term.showMore')}} <button v-if="nextUrl && !loading" style="opacity:0;height: 32px;" v-observe-visibility="{callback: visibilityChanged}">{{$root.getLz('term.showMore')}}

View file

@ -1,5 +1,7 @@
<script type="text/x-template" id="plugins-github"> //Not used for Now
<div class="content-inner github-themes-page">
<!-- <script type="text/x-template" id="plugins-github">
<div class="github-themes-page">
<div class="gh-header"> <div class="gh-header">
<div class="row"> <div class="row">
<div class="col nopadding"> <div class="col nopadding">
@ -186,3 +188,4 @@
} }
}) })
</script> </script>
-->

View file

@ -614,21 +614,18 @@
<span>{{$root.getLz('settings.header.lyrics')}}</span> <span>{{$root.getLz('settings.header.lyrics')}}</span>
</div> </div>
<div class="settings-option-body"> <div class="settings-option-body">
<div style="opacity: 0.5; pointer-events: none;">
<div class="md-option-line"> <div class="md-option-line">
<div class="md-option-segment"> <div class="md-option-segment">
{{$root.getLz('settings.option.lyrics.enableMusixmatch')}} {{$root.getLz('settings.option.lyrics.enableMusixmatch')}}
</div> </div>
<div class="md-option-segment md-option-segment_auto"> <div class="md-option-segment md-option-segment_auto">
<label> <label>
<input type="checkbox" switch checked/> <input type="checkbox" v-model="app.cfg.lyrics.enable_mxm" switch />
</label> </label>
<!-- <input type="checkbox" v-model="app.cfg.lyrics.enable_mxm" switch /> -->
</div>
</div> </div>
</div> </div>
<div class="md-option-line"> <div class="md-option-line">
<!-- <div class="md-option-line" v-if="app.cfg.lyrics.enable_mxm"> --> <div class="md-option-line" v-if="app.cfg.lyrics.enable_mxm">
<div class="md-option-segment"> <div class="md-option-segment">
{{$root.getLz('settings.option.lyrics.enableMusixmatchKaraoke')}} {{$root.getLz('settings.option.lyrics.enableMusixmatchKaraoke')}}
</div> </div>
@ -638,6 +635,7 @@
</label> </label>
</div> </div>
</div> </div>
</div>
<div class="md-option-line"> <div class="md-option-line">
<div class="md-option-segment"> <div class="md-option-segment">
{{$root.getLz('settings.option.lyrics.musixmatchPreferredLanguage')}} {{$root.getLz('settings.option.lyrics.musixmatchPreferredLanguage')}}
@ -646,271 +644,66 @@
<label> <label>
<select class="md-select" v-model="app.cfg.lyrics.mxm_language"> <select class="md-select" v-model="app.cfg.lyrics.mxm_language">
<option value='disabled'>Disabled</option> <option value='disabled'>Disabled</option>
<option value='ab'>Abkhazian</option> <option value='afrikaans'>Afrikaans</option>
<option value='aa'>Afar</option> <option value='albanian'>Albanian</option>
<option value='af'>Afrikaans</option> <option value='arab'>Arabic</option>
<option value='ak'>Akan</option> <option value='armenian'>Armenian</option>
<option value='sq'>Albanian</option> <option value='azerbaijani'>Azerbaijani</option>
<option value='am'>Amharic</option> <option value='bengali'>Bengali</option>
<option value='ar'>Arabic</option> <option value='bosnian'>Bosnian</option>
<option value='an'>Aragonese</option> <option value='bulgarian'>Bulgarian</option>
<option value='hy'>Armenian</option> <option value='simplified chinese'>Chinese (Simplified)</option>
<option value='as'>Assamese</option> <option value='traditional chinese'>Chinese (Traditional)</option>
<option value='a5'>Assamese-romaji</option> <option value='croatian'>Croatian</option>
<option value='a3'>Asturian</option> <option value='czech'>Czech</option>
<option value='av'>Avaric</option> <option value='danish'>Danish</option>
<option value='ae'>Avestan</option> <option value='estonian'>Estonian</option>
<option value='ay'>Aymara</option> <option value='english'>English</option>
<option value='az'>Azerbaijani</option> <option value='farsi'>Farsi</option>
<option value='bm'>Bambara</option> <option value='filipino'>Filipino</option>
<option value='ba'>Bashkir</option> <option value='french'>French</option>
<option value='eu'>Basque</option> <option value='georgian'>Georgian</option>
<option value='b1'>Bavarian</option> <option value='german'>German</option>
<option value='be'>Belarusian</option> <option value='greek'>Greek</option>
<option value='bn'>Bengali</option> <option value='gujarati'>Gujarati</option>
<option value='b5'>Bengali-romaji</option> <option value='haitian-creole'>Haitian-Creole</option>
<option value='bh'>Bihari languages</option> <option value='hebrew'>Hebrew</option>
<option value='b3'>Bishnupriya</option> <option value='hindi'>Hindi</option>
<option value='bi'>Bislama</option> <option value='hungarian'>Hungarian</option>
<option value='bs'>Bosnian</option> <option value='icelandic'>Icelandic</option>
<option value='br'>Breton</option> <option value='italian'>Italian</option>
<option value='bg'>Bulgarian</option> <option value='japanese'>Japanese</option>
<option value='my'>Burmese</option> <option value='japanese-romaji'>Romanized Japanese</option>
<option value='ca'>Catalan</option> <option value='kannada'>Kannada</option>
<option value='c2'>Cebuano</option> <option value='kazakh'>Kazakh</option>
<option value='b2'>Central bikol</option> <option value='korean-romaji'>Romanized Korean</option>
<option value='c3'>Central kurdish</option> <option value='lao'>Lao</option>
<option value='ch'>Chamorro</option> <option value='latvian'>Latvian</option>
<option value='c1'>Chavacano</option> <option value='lithuanian'>Lithuanian</option>
<option value='ce'>Chechen</option> <option value='macedonian'>Macedonian</option>
<option value='ny'>Chichewa</option> <option value='malay'>Malay</option>
<option value='zh'>Chinese (simplified)</option> <option value='malayalam'>Malayalam</option>
<option value='z1'>Chinese (traditional)</option> <option value='mongolian'>Mongolian</option>
<option value='rz'>Chinese-romaji</option> <option value='nepali'>Nepali</option>
<option value='cu'>Church slavic</option> <option value='norwegian'>Norwegian</option>
<option value='cv'>Chuvash</option> <option value='panjabi'>Panjabi</option>
<option value='kw'>Cornish</option> <option value='polish'>Polish</option>
<option value='co'>Corsican</option> <option value='portuguese'>Portuguese</option>
<option value='cr'>Cree</option> <option value='romanian'>Romanian</option>
<option value='c4'>Creoles and pidgins</option> <option value='russian'>Russian</option>
<option value='c5'>Creoles and pidgins, english based</option> <option value='serbian'>Serbian</option>
<option value='c6'>Creoles and pidgins, french-based</option> <option value='slovak'>Slovak</option>
<option value='c7'>Creoles and pidgins, portuguese-based</option> <option value='slovenian'>Slovenian</option>
<option value='hr'>Croatian</option> <option value='spanish'>Spanish</option>
<option value='cs'>Czech</option> <option value='suomi'>Suomi</option>
<option value='da'>Danish</option> <option value='swedish'>Swedish</option>
<option value='d1'>Dimli (individual language)</option> <option value='tamil'>Tamil</option>
<option value='dv'>Divehi</option> <option value='telugu'>Telugu</option>
<option value='d3'>Dotyali</option> <option value='turkish'>Turkish</option>
<option value='nl'>Dutch</option> <option value='ukrainian'>Ukrainian</option>
<option value='dz'>Dzongkha</option> <option value='urdu'>Urdu</option>
<option value='m2'>Eastern mari</option> <option value='uzbek'>Uzbek</option>
<option value='a2'>Egyptian arabic</option> <option value='vietnamese'>Vietnamese</option>
<option value='e1'>Emilian-romagnol</option>
<option value='en'>English</option>
<option value='m6'>Erzya</option>
<option value='eo'>Esperanto</option>
<option value='et'>Estonian</option>
<option value='ee'>Ewe</option>
<option value='fo'>Faroese</option>
<option value='h1'>Fiji hindi</option>
<option value='fj'>Fijian</option>
<option value='f1'>Filipino</option>
<option value='fi'>Finnish</option>
<option value='fr'>French</option>
<option value='f2'>Frisian, northern</option>
<option value='fy'>Frisian, western</option>
<option value='ff'>Fulah</option>
<option value='gl'>Galician</option>
<option value='lg'>Ganda</option>
<option value='ka'>Georgian</option>
<option value='de'>German</option>
<option value='n2'>German, low</option>
<option value='g1'>Goan konkani</option>
<option value='el'>Greek</option>
<option value='e2'>Greek-romaji</option>
<option value='kl'>Greenlandic</option>
<option value='gn'>Guarani</option>
<option value='gu'>Gujarati</option>
<option value='g2'>Gujarati-romaji</option>
<option value='ht'>Haitian creole</option>
<option value='ha'>Hausa</option>
<option value='he'>Hebrew</option>
<option value='hz'>Herero</option>
<option value='hi'>Hindi</option>
<option value='h3'>Hindi-romaji</option>
<option value='ho'>Hiri motu</option>
<option value='hu'>Hungarian</option>
<option value='is'>Icelandic</option>
<option value='io'>Ido</option>
<option value='ig'>Igbo</option>
<option value='i1'>Iloko</option>
<option value='id'>Indonesian</option>
<option value='ia'>Interlingua</option>
<option value='ie'>Interlingue</option>
<option value='iu'>Inuktitut</option>
<option value='ik'>Inupiaq</option>
<option value='ga'>Irish</option>
<option value='it'>Italian</option>
<option value='ja'>Japanese</option>
<option value='rj'>Japanese-romaji</option>
<option value='jv'>Javanese</option>
<option value='x1'>Kalmyk</option>
<option value='kn'>Kannada</option>
<option value='k2'>Kannada-romaji</option>
<option value='kr'>Kanuri</option>
<option value='k1'>Karachay-balkar</option>
<option value='ks'>Kashmiri</option>
<option value='kk'>Kazakh</option>
<option value='km'>Khmer, central</option>
<option value='ki'>Kikuyu</option>
<option value='rw'>Kinyarwanda</option>
<option value='ky'>Kirghiz</option>
<option value='kv'>Komi</option>
<option value='kg'>Kongo</option>
<option value='ko'>Korean</option>
<option value='rk'>Korean-romaji</option>
<option value='kj'>Kuanyama</option>
<option value='ku'>Kurdish</option>
<option value='lo'>Lao</option>
<option value='la'>Latin</option>
<option value='lv'>Latvian</option>
<option value='l1'>Lezghian</option>
<option value='li'>Limburgish</option>
<option value='ln'>Lingala</option>
<option value='lt'>Lithuanian</option>
<option value='j1'>Lojban</option>
<option value='l2'>Lombard</option>
<option value='lu'>Luba-katanga</option>
<option value='lb'>Luxembourgish</option>
<option value='mk'>Macedonian</option>
<option value='m1'>Maithili</option>
<option value='mg'>Malagasy</option>
<option value='ms'>Malay</option>
<option value='ml'>Malayalam</option>
<option value='m8'>Malayalam-romaji</option>
<option value='mt'>Maltese</option>
<option value='gv'>Manx</option>
<option value='mi'>Maori</option>
<option value='mr'>Marathi</option>
<option value='m9'>Marathi-romaji</option>
<option value='mh'>Marshallese</option>
<option value='m7'>Mazanderani</option>
<option value='m3'>Minangkabau</option>
<option value='x2'>Mingrelian</option>
<option value='m5'>Mirandese</option>
<option value='mo'>Moldavian</option>
<option value='mn'>Mongolian</option>
<option value='n4'>Nahuatl</option>
<option value='na'>Nauru</option>
<option value='nv'>Navajo</option>
<option value='nd'>Ndebele, north</option>
<option value='nr'>Ndebele, south</option>
<option value='ng'>Ndonga</option>
<option value='n1'>Neapolitan</option>
<option value='n3'>Nepal bhasa</option>
<option value='ne'>Nepali</option>
<option value='n5'>Nepali-romaji</option>
<option value='l3'>Northern luri</option>
<option value='no'>Norwegian</option>
<option value='nb'>Norwegian bokmål</option>
<option value='nn'>Norwegian nynorsk</option>
<option value='oc'>Occitan</option>
<option value='oj'>Ojibwa</option>
<option value='or'>Oriya</option>
<option value='o1'>Oriya-romaji</option>
<option value='om'>Oromo</option>
<option value='os'>Ossetian</option>
<option value='pi'>Pali</option>
<option value='p1'>Pampanga</option>
<option value='pa'>Panjabi</option>
<option value='p5'>Panjabi-romaji</option>
<option value='fa'>Persian</option>
<option value='p2'>Pfaelzisch</option>
<option value='p3'>Piemontese</option>
<option value='pl'>Polish</option>
<option value='pt'>Portuguese</option>
<option value='ps'>Pushto</option>
<option value='qu'>Quechua</option>
<option value='ro'>Romanian</option>
<option value='rm'>Romansh</option>
<option value='rn'>Rundi</option>
<option value='b4'>Russia buriat</option>
<option value='ru'>Russian</option>
<option value='r2'>Russian-romaji</option>
<option value='r1'>Rusyn</option>
<option value='se'>Sami, northern</option>
<option value='sm'>Samoan</option>
<option value='sg'>Sango</option>
<option value='sa'>Sanskrit</option>
<option value='s4'>Sanskrit-romaji</option>
<option value='sc'>Sardinian</option>
<option value='s3'>Scots</option>
<option value='gd'>Scottish gaelic</option>
<option value='sr'>Serbian</option>
<option value='sh'>Serbo-croatian</option>
<option value='sn'>Shona</option>
<option value='ii'>Sichuan yi</option>
<option value='s2'>Sicilian</option>
<option value='sd'>Sindhi</option>
<option value='si'>Sinhala</option>
<option value='sk'>Slovak</option>
<option value='sl'>Slovenian</option>
<option value='so'>Somali</option>
<option value='d2'>Sorbian, lower</option>
<option value='h2'>Sorbian, upper</option>
<option value='st'>Sotho, southern</option>
<option value='a4'>South azerbaijani</option>
<option value='es'>Spanish</option>
<option value='su'>Sundanese</option>
<option value='sw'>Swahili</option>
<option value='ss'>Swati</option>
<option value='sv'>Swedish</option>
<option value='tl'>Tagalog</option>
<option value='ty'>Tahitian</option>
<option value='tg'>Tajik</option>
<option value='ta'>Tamil</option>
<option value='t2'>Tamil-romaji</option>
<option value='tt'>Tatar</option>
<option value='te'>Telugu</option>
<option value='t3'>Telugu-romaji</option>
<option value='th'>Thai</option>
<option value='t4'>Thai-romaji</option>
<option value='bo'>Tibetan</option>
<option value='ti'>Tigrinya</option>
<option value='to'>Tonga (tonga islands)</option>
<option value='a1'>Tosk albanian</option>
<option value='ts'>Tsonga</option>
<option value='tn'>Tswana</option>
<option value='tr'>Turkish</option>
<option value='tk'>Turkmen</option>
<option value='t1'>Tuvinian</option>
<option value='tw'>Twi</option>
<option value='ug'>Uighur</option>
<option value='uk'>Ukrainian</option>
<option value='ur'>Urdu</option>
<option value='u1'>Urdu-romaji</option>
<option value='uz'>Uzbek</option>
<option value='ve'>Venda</option>
<option value='v1'>Venetian</option>
<option value='v2'>Veps</option>
<option value='vi'>Vietnamese</option>
<option value='v3'>Vlaams</option>
<option value='vo'>Volapük</option>
<option value='wa'>Walloon</option>
<option value='w1'>Waray</option>
<option value='cy'>Welsh</option>
<option value='m4'>Western mari</option>
<option value='p4'>Western panjabi</option>
<option value='wo'>Wolof</option>
<option value='w2'>Wu chinese</option>
<option value='xh'>Xhosa</option>
<option value='s1'>Yakut</option>
<option value='yi'>Yiddish</option>
<option value='yo'>Yoruba</option>
<option value='y1'>Yue chinese</option>
<option value='za'>Zhuang</option>
<option value='zu'>Zulu</option>
</select> </select>
</label> </label>
</div> </div>

View file

@ -1,5 +1,7 @@
<script type="text/x-template" id="themes-github"> //Not used for Now
<div class="content-inner github-themes-page">
<!-- <script type="text/x-template" id="themes-github">
<div class="github-themes-page">
<div class="gh-header"> <div class="gh-header">
<div class="row"> <div class="row">
<div class="col nopadding"> <div class="col nopadding">
@ -195,3 +197,4 @@
} }
}) })
</script> </script>
-->

View file

@ -279,6 +279,12 @@ input[type=range].md-slider::-webkit-slider-runnable-track {
width: auto; width: auto;
} }
@media only screen and (min-width: 1133px) and (max-width: 1241px) {
.row .col-auto {
display: none !important;
}
}
.col-1 { .col-1 {
flex: 0 0 auto; flex: 0 0 auto;
width: 8.33333333%; width: 8.33333333%;