diff --git a/README.md b/README.md index 46abf01..8a29cc8 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ CYP is a web-based frontend for [MPD](https://www.musicpd.org/), the Music Player Daemon. You can use it to control the playback without having to install native application(s). It works in modern web browsers, both desktop and mobile. + ## Features - Control the playback, queue, volume - Save and load playlists @@ -9,6 +10,7 @@ CYP is a web-based frontend for [MPD](https://www.musicpd.org/), the Music Playe - Display album art via native MPD calls (no need to access the library; requires MPD >= 0.21) - [Youtube-dl](https://ytdl-org.github.io/youtube-dl/index.html) intergration + ## Installation Make sure you have a working MPD setup first. @@ -21,16 +23,21 @@ node . Point your browser to http://localhost:8080 to open the interface. + ## Technology - Connected to MPD via WebSockets (using the [ws2mpd](https://github.com/ondras/ws2mpd/) bridge) + - Token-based access to the WebSocket endpoint (better than an `Origin` check) - Modern ES6+ (modules, async/await) - Responsive layout via Flexbox + - CSS Custom Properties - SVG icons (Material Design) - Dark/Light theme available - - Album art downloaded directly from MPD (and cached via localStorage) + - Can spawn Youtube-dl to download audio files + - Album art retrieved directly from MPD (and cached via localStorage) ## TODO - [ ] Bundling - [ ] Range styling + - [ ] Browser testing diff --git a/app/app.css b/app/app.css index d1db4f9..0487480 100644 --- a/app/app.css +++ b/app/app.css @@ -14,15 +14,16 @@ body { line-height: 1.25; background-color: var(--bg); color: var(--fg); - text-shadow: var(--shadow); + text-shadow: var(--text-shadow); max-width: 800px; margin: 0 auto; overflow: hidden; height: 100vh; } -body > header, -body > footer { - box-shadow: 0 0 3px #000; +header, +footer { + z-index: 1; + box-shadow: var(--box-shadow); } input, select, @@ -280,7 +281,7 @@ nav ul li.active { .component li .info .icon { color: var(--primary); margin-right: var(--icon-spacing); - filter: drop-shadow(var(--shadow)); + filter: drop-shadow(var(--text-shadow)); } .component li .info h2 { font-size: var(--font-size-large); @@ -339,7 +340,7 @@ nav ul li.active { #queue li .info .icon { color: var(--primary); margin-right: var(--icon-spacing); - filter: drop-shadow(var(--shadow)); + filter: drop-shadow(var(--text-shadow)); } #queue li .info h2 { font-size: var(--font-size-large); @@ -401,7 +402,7 @@ nav ul li.active { #library li .info .icon { color: var(--primary); margin-right: var(--icon-spacing); - filter: drop-shadow(var(--shadow)); + filter: drop-shadow(var(--text-shadow)); } #library li .info h2 { font-size: var(--font-size-large); @@ -436,7 +437,7 @@ nav ul li.active { width: 64px; } #library .art .icon { - filter: drop-shadow(var(--shadow)); + filter: drop-shadow(var(--text-shadow)); } #library .group { cursor: pointer; @@ -497,7 +498,7 @@ nav ul li.active { #fs li .info .icon { color: var(--primary); margin-right: var(--icon-spacing); - filter: drop-shadow(var(--shadow)); + filter: drop-shadow(var(--text-shadow)); } #fs li .info h2 { font-size: var(--font-size-large); @@ -576,7 +577,7 @@ nav ul li.active { #playlists li .info .icon { color: var(--primary); margin-right: var(--icon-spacing); - filter: drop-shadow(var(--shadow)); + filter: drop-shadow(var(--text-shadow)); } #playlists li .info h2 { font-size: var(--font-size-large); @@ -643,7 +644,7 @@ nav ul li.active { #yt li .info .icon { color: var(--primary); margin-right: var(--icon-spacing); - filter: drop-shadow(var(--shadow)); + filter: drop-shadow(var(--text-shadow)); } #yt li .info h2 { font-size: var(--font-size-large); @@ -759,18 +760,19 @@ nav ul li.active { --icon-spacing: 4px; --primary: rgb(var(--primary-raw)); --spacing: 8px; + --box-shadow: 0 0 3px #000; } :root[data-theme=light] { --fg: #333; --bg: #f0f0f0; --bg-alt: #e0e0e0; - --shadow: none; + --text-shadow: none; } :root[data-theme=dark] { --fg: #f0f0f0; --bg: #333; --bg-alt: #555; - --shadow: 0 1px 1px rgba(0, 0, 0, 0.8); + --text-shadow: 0 1px 1px rgba(0, 0, 0, 0.8); } :root[data-color=dodgerblue] { --primary-raw: 30, 144, 255; diff --git a/app/css/app.less b/app/css/app.less index dabf7e5..ec1b377 100644 --- a/app/css/app.less +++ b/app/css/app.less @@ -12,15 +12,16 @@ body { line-height: 1.25; background-color: var(--bg); color: var(--fg); - text-shadow: var(--shadow); + text-shadow: var(--text-shadow); max-width: 800px; margin: 0 auto; overflow: hidden; height: 100vh; +} - > header, > footer { - box-shadow: 0 0 3px #000; - } +header, footer { + z-index: 1; + box-shadow: var(--box-shadow); } input, select, button { diff --git a/app/css/component.less b/app/css/component.less index 6ce48be..363dc79 100644 --- a/app/css/component.less +++ b/app/css/component.less @@ -33,7 +33,7 @@ .icon { color: var(--primary); margin-right: var(--icon-spacing); - filter: drop-shadow(var(--shadow)); + filter: drop-shadow(var(--text-shadow)); } h2 { diff --git a/app/css/library.less b/app/css/library.less index 1212899..38c6461 100644 --- a/app/css/library.less +++ b/app/css/library.less @@ -15,7 +15,7 @@ } .art .icon { - filter: drop-shadow(var(--shadow)); + filter: drop-shadow(var(--text-shadow)); } .group { diff --git a/app/css/variables.less b/app/css/variables.less index df28b38..c15c662 100644 --- a/app/css/variables.less +++ b/app/css/variables.less @@ -3,20 +3,21 @@ --icon-spacing: 4px; --primary: rgb(var(--primary-raw)); --spacing: 8px; + --box-shadow: 0 0 3px #000; } :root[data-theme=light] { --fg: #333; --bg: #f0f0f0; --bg-alt: #e0e0e0; - --shadow: none; + --text-shadow: none; } :root[data-theme=dark] { --fg: #f0f0f0; --bg: #333; --bg-alt: #555; - --shadow: 0 1px 1px rgba(0, 0, 0, 0.8); + --text-shadow: 0 1px 1px rgba(0, 0, 0, 0.8); } :root[data-color=dodgerblue] {