22@inject HomeSpeakerService svc
33@inject ILogger <Index > logger
44@inject HttpClient Http
5+ @inject PlayerStateService PlayerState
56@implements IDisposable
67
78<PageTitle >Home Speaker</PageTitle >
1213 <i class =" fas fa-headphones me-2" ></i >Now Playing
1314 </div >
1415 <div class =" now-playing-status" >
15- @if (playerStatus == null )
16+ @if (PlayerState . Status == null )
1617 {
1718 <div class =" loading-spinner mx-auto mb-2" ></div >
1819 <span class =" status-text text-muted" >Connecting .. .</span >
1920 }
20- else if (playerStatus . StilPlaying && playerStatus .CurrentSong != null )
21+ else if (PlayerState . Status . StilPlaying && PlayerState . Status .CurrentSong != null )
2122 {
2223 <div class =" song-info" >
23- <div class =" song-title" >@playerStatus .CurrentSong.Name </div >
24- @if (! string .IsNullOrEmpty (playerStatus .CurrentSong .Artist ))
24+ <div class =" song-title" >@PlayerState.Status .CurrentSong.Name </div >
25+ @if (! string .IsNullOrEmpty (PlayerState . Status .CurrentSong .Artist ))
2526 {
26- <div class =" song-artist" >@playerStatus .CurrentSong.Artist </div >
27+ <div class =" song-artist" >@PlayerState.Status .CurrentSong.Artist </div >
2728 }
28- @if (! string .IsNullOrEmpty (playerStatus .CurrentSong .Album ))
29+ @if (! string .IsNullOrEmpty (PlayerState . Status .CurrentSong .Album ))
2930 {
30- <div class =" song-album" >@playerStatus .CurrentSong.Album </div >
31+ <div class =" song-album" >@PlayerState.Status .CurrentSong.Album </div >
3132 }
3233 <div class =" progress-row mt-2" >
3334 <div class =" progress-bar-track" >
34- <div class =" progress-bar-fill" style =" width : @(playerStatus .PercentComplete.ToString(" F1 " , System.Globalization.CultureInfo.InvariantCulture))%" ></div >
35+ <div class =" progress-bar-fill" style =" width : @(PlayerState.Status .PercentComplete.ToString(" F1 " , System.Globalization.CultureInfo.InvariantCulture))%" ></div >
3536 </div >
36- <span class =" volume-badge" ><i class =" fas fa-volume-up me-1" ></i >@playerStatus .Volume </span >
37+ <span class =" volume-badge" ><i class =" fas fa-volume-up me-1" ></i >@PlayerState.Status .Volume </span >
3738 </div >
3839 </div >
3940 }
177178 font-size : 1rem ;
178179 }
179180 }
181+
182+ /* Pi 7" screen — ultra compact now-playing */
183+ @@media (max-height : 520px ) {
184+ .now-playing-card {
185+ padding : 0.4rem var (--hs-space-sm );
186+ margin-bottom : 0.5rem !important ;
187+ }
188+
189+ .now-playing-label {
190+ display : none ;
191+ }
192+
193+ .now-playing-status {
194+ min-height : 28px ;
195+ margin-bottom : 0.25rem ;
196+ flex-direction : row ;
197+ justify-content : flex-start ;
198+ gap : 0.5rem ;
199+ }
200+
201+ .song-title {
202+ font-size : 0.875rem ;
203+ white-space : nowrap ;
204+ overflow : hidden ;
205+ text-overflow : ellipsis ;
206+ max-width : 60vw ;
207+ }
208+
209+ .song-artist {
210+ font-size : 0.75rem ;
211+ display : inline ;
212+ }
213+
214+ .song-album {
215+ display : none ;
216+ }
217+
218+ .progress-row {
219+ display : none ;
220+ }
221+
222+ .idle-icon {
223+ font-size : 1rem ;
224+ }
225+
226+ .now-playing-controls {
227+ padding-top : 0.25rem ;
228+ }
229+ }
180230 </style >
181231
182232@code {
183- private GetStatusReply ? playerStatus ;
184233 private bool showTemperature ;
185234 private bool showBloodSugar ;
186235 private Timer ? refreshTimer ;
200249 logger .LogWarning (ex , " Failed to load feature flags" );
201250 }
202251
252+ PlayerState .StateChanged += OnStateChanged ;
203253 await RefreshStatusAsync ();
204254
205255 refreshTimer = new Timer (async _ =>
216266 }, null , TimeSpan .FromSeconds (5 ), TimeSpan .FromSeconds (5 ));
217267 }
218268
269+ private void OnStateChanged () => InvokeAsync (StateHasChanged );
270+
219271 private async Task RefreshStatusAsync ()
220272 {
221273 try
222274 {
223- playerStatus = await svc .GetStatusAsync ();
224- StateHasChanged ();
275+ var status = await svc .GetStatusAsync ();
276+ bool repeatMode = await svc .GetRepeatModeAsync ();
277+ PlayerState .UpdateStatus (status );
278+ PlayerState .UpdateRepeatMode (repeatMode );
279+ // StateHasChanged is triggered by the event subscription above
225280 }
226281 catch (Exception ex )
227282 {
231286
232287 public void Dispose ()
233288 {
289+ PlayerState .StateChanged -= OnStateChanged ;
234290 refreshTimer ? .Dispose ();
235291 }
236292}
0 commit comments