diff --git a/CHANGELOG.md b/CHANGELOG.md index 25defefbc..a8026f41a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ ## 0.4.6 * System * Automatically persist logs during (and for a short time after) updates +* Webapp + * Move home screen, player page controls to bottom of screen on mobile + * Update CSS breakpoints to scale the player page better on the smallest of screens + * Reformat Player page volume controls to be more modern ## 0.4.5 * Web App diff --git a/web/src/components/CustomMarquee/CustomMarquee.jsx b/web/src/components/CustomMarquee/CustomMarquee.jsx index 72c4befe7..9bcaa22a8 100644 --- a/web/src/components/CustomMarquee/CustomMarquee.jsx +++ b/web/src/components/CustomMarquee/CustomMarquee.jsx @@ -42,14 +42,13 @@ export default function CustomMarquee(props) { } } - let resizeTimout; + let resizeTimeout; // Your IDE will say this is unused, it's actually used to make sure the timeout below is limited to one instance at a time by taking up a specific variable function handleResize(){ if(!resizeCooldown.current){ resizeCooldown.current = true; assessMarquee() - - resizeTimout = setTimeout(()=>{resizeCooldown.current = false;}, 1000) // set a cooldown for resize checks to avoid excessive renders + resizeTimeout = setTimeout(()=>{resizeCooldown.current = false;}, 1000) } } window.addEventListener("resize", handleResize()); // Doesn't call assessMarquee directly to avoid calling thousands of times per second when resizing window diff --git a/web/src/components/GroupVolumeSlider/GroupVolumeSlider.jsx b/web/src/components/GroupVolumeSlider/GroupVolumeSlider.jsx index f1edf40cb..6196f99cb 100644 --- a/web/src/components/GroupVolumeSlider/GroupVolumeSlider.jsx +++ b/web/src/components/GroupVolumeSlider/GroupVolumeSlider.jsx @@ -89,12 +89,12 @@ const GroupVolumeSlider = ({ groupId, sourceId, groupsLeft }) => { onClick={() => setSlidersOpen(!slidersOpen)} > {slidersOpen ? ( - ) : ( - diff --git a/web/src/components/GroupVolumeSlider/GroupVolumeSlider.scss b/web/src/components/GroupVolumeSlider/GroupVolumeSlider.scss index f6975cc3d..0ce4199b8 100644 --- a/web/src/components/GroupVolumeSlider/GroupVolumeSlider.scss +++ b/web/src/components/GroupVolumeSlider/GroupVolumeSlider.scss @@ -6,6 +6,10 @@ } .group-volume-children-container { + // Equates to the height of a single volume bar (with title) * 3 on desktop + // Previously also had a mobile version (204px) but mobile doesn't always show a scrollbar when needed (unlike desktop) so it was hard to tell when there was > 3 + max-height: 168px; + overflow: auto; padding-left: 1rem; } @@ -23,5 +27,4 @@ .group-volume-slider { width: 100%; - margin: 0 1rem; } diff --git a/web/src/components/MediaControl/MediaControl.scss b/web/src/components/MediaControl/MediaControl.scss index 01e8cbc65..d116fc2c7 100644 --- a/web/src/components/MediaControl/MediaControl.scss +++ b/web/src/components/MediaControl/MediaControl.scss @@ -8,7 +8,6 @@ justify-content: center; margin-top: 1rem; margin-bottom: 1rem; - width: 90vw; } .media-inner { @@ -19,6 +18,7 @@ } .media-control { + font-size: 3.5rem; color: general.$controls-color; padding-left: 1.5rem; padding-right: 1.5rem; @@ -30,11 +30,11 @@ padding-right: 1.25rem; } - @media (min-width: 365px) and (max-width: 425px) { + @media (min-width: 365px) and (max-width: 435px) { font-size: 2.5rem; } - @media (min-width: 425px) { + @media (min-width: 435px) { font-size: 3.5rem; } } diff --git a/web/src/components/SongInfo/SongInfo.scss b/web/src/components/SongInfo/SongInfo.scss index ed3b965bf..973f47688 100644 --- a/web/src/components/SongInfo/SongInfo.scss +++ b/web/src/components/SongInfo/SongInfo.scss @@ -10,6 +10,11 @@ white-space: nowrap; overflow: hidden; + + @media (max-width: 435px){ + max-height: 50vh; + max-width: 50vh; + } } .artist-name { diff --git a/web/src/components/StreamBar/StreamBar.scss b/web/src/components/StreamBar/StreamBar.scss index 01c847eaf..655b18905 100644 --- a/web/src/components/StreamBar/StreamBar.scss +++ b/web/src/components/StreamBar/StreamBar.scss @@ -21,15 +21,26 @@ color: general.$text-color; width: 100%; max-width: 80%; // Leave space for icon - font-size: 2.5rem; font-weight: medium; white-space: nowrap; overflow: hidden; @include general.header-font; padding: 0.5rem; + @media (max-height: 500px){ + font-size: 1.5rem; + } + @media (min-height: 500px){ + font-size: 2.5rem; + } } .stream-bar-icon { - width: 4rem; - height: 4rem; + @media (max-height: 500px){ + width: 2rem; + height: 2rem; + } + @media (min-height: 500px){ + width: 4rem; + height: 4rem; + } } diff --git a/web/src/components/ZoneVolumeSlider/ZoneVolumeSlider.scss b/web/src/components/ZoneVolumeSlider/ZoneVolumeSlider.scss index 73669bc62..3402b9a45 100644 --- a/web/src/components/ZoneVolumeSlider/ZoneVolumeSlider.scss +++ b/web/src/components/ZoneVolumeSlider/ZoneVolumeSlider.scss @@ -3,4 +3,5 @@ .zone-volume-container { @include general.header-font; font-size: 1rem; + max-width: calc(100% - 47px) } diff --git a/web/src/pages/Home/Home.jsx b/web/src/pages/Home/Home.jsx index 215a53bf4..d12882577 100644 --- a/web/src/pages/Home/Home.jsx +++ b/web/src/pages/Home/Home.jsx @@ -55,11 +55,13 @@ const PresetAndAdd = ({ ); } else { return ( -
setPresetsModalOpen(true)} - > - Presets +
+
setPresetsModalOpen(true)} + > + Presets +
); } diff --git a/web/src/pages/Home/Home.scss b/web/src/pages/Home/Home.scss index 121fa8212..9c6b5aa0f 100644 --- a/web/src/pages/Home/Home.scss +++ b/web/src/pages/Home/Home.scss @@ -2,7 +2,12 @@ .home-outer { padding-top: 10px; - padding-bottom: 10px; + @media (max-width: 435px) { + padding-bottom: 85px; + } + @media (min-width: 435px) { + padding-bottom: 10px; + } display: flex; flex-direction: column; align-items: center; @@ -69,6 +74,12 @@ } .home-presets-container { + @media (max-width: 435px) { + position: fixed; + bottom: 65px; + } + + z-index: 1; // Needed to ensure that scrolling marquees do not appear on top of the presets button display: flex; flex-direction: row; diff --git a/web/src/pages/Player/Player.jsx b/web/src/pages/Player/Player.jsx index 872ee214f..887239c8b 100644 --- a/web/src/pages/Player/Player.jsx +++ b/web/src/pages/Player/Player.jsx @@ -87,6 +87,7 @@ const Player = () => { { - - - - {/* There are many sub-divs classed player-inner here because formatting was strange otherwise */} -
-
-
-
-
-
+
+ +
{!alone && !is_streamer && zones.length > 0 && ( - - - setExpanded(!expanded)}> - {expanded ? ( - - ) : ( - - )} - + +
+ + setExpanded(!expanded)}> + {expanded ? ( + + ) : ( + + )} + +
+ + {/* When expanded, take up max height to prevent constant resizes as more dropdowns expand */} +
+ +
)} -
); }; diff --git a/web/src/pages/Player/Player.scss b/web/src/pages/Player/Player.scss index 0da4b71a0..1e894f1bf 100644 --- a/web/src/pages/Player/Player.scss +++ b/web/src/pages/Player/Player.scss @@ -33,7 +33,19 @@ border-radius: 2.5%; } -.player-volume-slider { +.media-controls { + position: fixed; + z-index: 0; + bottom: 129px +} + +.player-volume-container { + position: fixed; + bottom: 65px; + z-index: 1; +} + +.player-volume-header { display: flex; flex-direction: row; align-items: center; @@ -41,6 +53,14 @@ width: 90vw; } +.player-volume-body { + display: flex; + align-items: center; + flex-direction: column; + max-height: calc(85vh - 120px); + overflow-y: auto; +} + .player-volume-expand-button { color: general.$controls-color; } @@ -52,3 +72,16 @@ @include general.header-font; padding: 0.5rem; } + +.control-gap { + // Dynamically size the gap so that the controls are always at the bottom of the screen when screen is scrolled to the top of the page + @media(min-height: 800px) { + height: 7.5vh + } + @media(min-height: 850px) { + height: 10vh + } + @media(min-height: 875px) { + height: 12.5vh + } +}