Skip to content

Commit 5023e07

Browse files
authored
Merge pull request #588 from namehillsoftware/feature/add-files-from-now-playing-file-details
[Feature] Restore Adding Files From Now Playing File Details
2 parents 2fa282e + cbdd683 commit 5023e07

File tree

10 files changed

+350
-124
lines changed

10 files changed

+350
-124
lines changed

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/browsing/ScopedViewModelRegistry.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ class ScopedViewModelRegistry(
102102
playbackServiceController,
103103
fileDetailsViewModel,
104104
fileDetailsViewModel,
105+
nowPlayingState,
106+
registerForApplicationMessages,
105107
)
106108
}
107109

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/browsing/files/details/FileDetailsState.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
package com.lasthopesoftware.bluewater.client.browsing.files.details
22

3+
import com.lasthopesoftware.bluewater.client.browsing.TrackLoadedViewState
34
import com.lasthopesoftware.bluewater.client.browsing.files.ServiceFile
45
import com.lasthopesoftware.bluewater.client.browsing.library.repository.LibraryId
56
import com.lasthopesoftware.bluewater.shared.observables.InteractionState
67
import com.lasthopesoftware.bluewater.shared.observables.LiftedInteractionState
78
import com.namehillsoftware.handoff.promises.Promise
89

9-
interface FileDetailsState {
10+
interface FileDetailsState : TrackLoadedViewState {
1011
val activeLibraryId: LibraryId?
1112
val activeServiceFile: ServiceFile?
1213

1314
val fileName: InteractionState<String>
1415
val artist: InteractionState<String>
1516
val album: InteractionState<String>
1617
val fileProperties: InteractionState<List<FileDetailsViewModel.FilePropertyViewModel>>
17-
val isLoading: InteractionState<Boolean>
1818
val coverArt: LiftedInteractionState<ByteArray>
1919
val rating: InteractionState<Int>
2020
val highlightedProperty: InteractionState<FileDetailsViewModel.FilePropertyViewModel?>

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/browsing/files/details/FileDetailsView.kt

Lines changed: 64 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.heightIn
2424
import androidx.compose.foundation.layout.padding
2525
import androidx.compose.foundation.layout.requiredHeight
2626
import androidx.compose.foundation.layout.requiredWidth
27-
import androidx.compose.foundation.layout.size
2827
import androidx.compose.foundation.layout.systemBars
2928
import androidx.compose.foundation.layout.width
3029
import androidx.compose.foundation.lazy.LazyColumn
@@ -113,124 +112,118 @@ private val viewPadding = viewPaddingUnit
113112
private val maxMenuHeight = topMenuHeight + rowPadding
114113

115114
@Composable
116-
private fun PlayableFileMenu(
115+
private fun PlayLastButton(
117116
fileDetailsState: FileDetailsState,
118-
mediaStylePalette: MediaStylePalette,
119-
playableFileDetailsState: PlayableFileDetailsState?,
117+
modifier: Modifier = Modifier,
120118
) {
121-
val modifier = Modifier.requiredWidth(topMenuIconWidth)
122-
123-
LabelledRefreshButton(
124-
onClick = {
125-
fileDetailsState.promiseLoadedActiveFile()
126-
},
127-
modifier = modifier,
128-
)
129-
130119
val addFileToPlaybackLabel = stringResource(id = R.string.btn_add_file_to_playback)
131120
ColumnMenuIcon(
132121
onClick = { fileDetailsState.addToNowPlaying() },
133-
icon = {
134-
Image(
135-
painter = painterResource(id = R.drawable.playlist_plus),
136-
colorFilter = ColorFilter.tint(mediaStylePalette.secondaryTextColor),
137-
contentDescription = addFileToPlaybackLabel,
138-
modifier = Modifier.size(topMenuIconSize),
139-
)
140-
},
122+
iconPainter = painterResource(id = R.drawable.playlist_plus),
123+
contentDescription = addFileToPlaybackLabel,
141124
label = addFileToPlaybackLabel,
142125
labelMaxLines = 1,
143126
modifier = modifier,
144127
)
128+
}
145129

130+
@Composable
131+
private fun PlayNextButton(
132+
fileDetailsState: FileDetailsState,
133+
modifier: Modifier = Modifier,
134+
) {
146135
val playFileNextPlaybackLabel = stringResource(id = R.string.btn_play_file_next)
147136
ColumnMenuIcon(
148137
onClick = { fileDetailsState.playNext() },
149-
icon = {
150-
Image(
151-
painter = painterResource(id = R.drawable.playlist_inner_plus),
152-
colorFilter = ColorFilter.tint(mediaStylePalette.secondaryTextColor),
153-
contentDescription = playFileNextPlaybackLabel,
154-
modifier = Modifier.size(topMenuIconSize),
155-
)
156-
},
138+
iconPainter = painterResource(id = R.drawable.playlist_inner_plus),
139+
contentDescription = playFileNextPlaybackLabel,
157140
label = playFileNextPlaybackLabel,
158141
labelMaxLines = 1,
159142
modifier = modifier,
160143
)
144+
}
145+
146+
@Composable
147+
private fun PlayableFileMenu(
148+
fileDetailsState: FileDetailsState,
149+
playableFileDetailsState: PlayableFileDetailsState?,
150+
) {
151+
val modifier = Modifier.requiredWidth(topMenuIconWidth)
152+
val isLoading by fileDetailsState.isLoading.subscribeAsState()
153+
154+
LabelledRefreshButton(
155+
onClick = {
156+
fileDetailsState.promiseLoadedActiveFile()
157+
},
158+
modifier = modifier,
159+
enabled = !isLoading,
160+
)
161+
162+
PlayLastButton(fileDetailsState, modifier)
163+
164+
PlayNextButton(fileDetailsState, modifier)
161165

162166
if (playableFileDetailsState != null) {
163167
val playLabel = stringResource(id = R.string.btn_play)
164168
ColumnMenuIcon(
165169
onClick = { playableFileDetailsState.play() },
166-
icon = {
167-
Image(
168-
painter = painterResource(id = R.drawable.av_play_white),
169-
colorFilter = ColorFilter.tint(mediaStylePalette.secondaryTextColor),
170-
contentDescription = playLabel,
171-
modifier = Modifier.size(topMenuIconSize),
172-
)
173-
},
170+
iconPainter = painterResource(id = R.drawable.av_next_white),
171+
contentDescription = playLabel,
174172
label = playLabel,
175173
labelMaxLines = 1,
176-
modifier = Modifier.requiredWidth(topMenuIconWidth)
174+
modifier = Modifier.requiredWidth(topMenuIconWidth),
175+
enabled = !isLoading
177176
)
178177
}
179178
}
180179

181180
@Composable
182181
private fun NowPlayingFileMenu(
183182
fileDetailsState: FileDetailsState,
184-
mediaStylePalette: MediaStylePalette,
185183
nowPlayingFileDetailsState: NowPlayingFileDetailsState,
186-
playableFileDetailsState: PlayableFileDetailsState?,
184+
playableFileDetailsState: PlayableFileDetailsState,
187185
) {
188186
val modifier = Modifier.requiredWidth(topMenuIconWidth)
187+
val isLoading by fileDetailsState.isLoading.subscribeAsState()
189188

190189
LabelledRefreshButton(
191190
onClick = {
192191
fileDetailsState.promiseLoadedActiveFile()
193192
},
194193
modifier = modifier,
194+
enabled = !isLoading,
195195
)
196196

197+
val isInPosition by nowPlayingFileDetailsState.isInPosition.subscribeAsState()
197198
val removeFileLabel = stringResource(id = R.string.btn_remove_file)
198199
ColumnMenuIcon(
199200
onClick = { nowPlayingFileDetailsState.removeFile() },
200-
icon = {
201-
Image(
202-
painter = painterResource(id = R.drawable.ic_remove_item_white_36dp),
203-
colorFilter = ColorFilter.tint(mediaStylePalette.secondaryTextColor),
204-
contentDescription = removeFileLabel,
205-
modifier = Modifier.size(topMenuIconSize),
206-
)
207-
},
201+
iconPainter = painterResource(id = R.drawable.ic_remove_item_white_36dp),
202+
contentDescription = removeFileLabel,
208203
label = removeFileLabel,
209204
labelMaxLines = 1,
210205
modifier = modifier,
206+
enabled = !isLoading && isInPosition
211207
)
212208

213-
if (playableFileDetailsState != null) {
214-
val playLabel = stringResource(id = R.string.skip_to)
215-
ColumnMenuIcon(
216-
onClick = { playableFileDetailsState.play() },
217-
icon = {
218-
Image(
219-
painter = painterResource(id = R.drawable.av_next_white),
220-
colorFilter = ColorFilter.tint(mediaStylePalette.secondaryTextColor),
221-
contentDescription = playLabel,
222-
modifier = Modifier.size(topMenuIconSize),
223-
)
224-
},
225-
label = playLabel,
226-
labelMaxLines = 1,
227-
modifier = Modifier.requiredWidth(topMenuIconWidth)
228-
)
229-
}
209+
val playLabel = stringResource(id = R.string.skip_to)
210+
ColumnMenuIcon(
211+
onClick = { playableFileDetailsState.play() },
212+
iconPainter = painterResource(id = R.drawable.av_next_white),
213+
contentDescription = playLabel,
214+
label = playLabel,
215+
labelMaxLines = 1,
216+
modifier = Modifier.requiredWidth(topMenuIconWidth),
217+
enabled = isInPosition
218+
)
219+
220+
PlayLastButton(fileDetailsState, modifier)
221+
222+
PlayNextButton(fileDetailsState, modifier)
230223
}
231224

232225
@Composable
233-
fun FileRating(viewModel: FileDetailsState, mediaStylePalette: MediaStylePalette, modifier: Modifier) {
226+
private fun FileRating(viewModel: FileDetailsState, mediaStylePalette: MediaStylePalette, modifier: Modifier) {
234227
val rating by viewModel.rating.subscribeAsState()
235228

236229
RatingBar(
@@ -242,7 +235,7 @@ fun FileRating(viewModel: FileDetailsState, mediaStylePalette: MediaStylePalette
242235
}
243236

244237
@Composable
245-
fun rememberComputedColorPalette(
238+
private fun rememberComputedColorPalette(
246239
paletteProvider: MediaStylePaletteProvider,
247240
coverArt: Bitmap?
248241
): State<MediaStylePalette> {
@@ -265,7 +258,7 @@ fun rememberComputedColorPalette(
265258
}
266259

267260
@Composable
268-
fun FilePropertyHeader(
261+
private fun FilePropertyHeader(
269262
viewModel: FileDetailsState,
270263
palette: MediaStylePalette,
271264
modifier: Modifier = Modifier,
@@ -304,7 +297,7 @@ fun FilePropertyHeader(
304297
}
305298

306299
@Composable
307-
fun FilePropertyRow(
300+
private fun FilePropertyRow(
308301
viewModel: FileDetailsState,
309302
property: FileDetailsViewModel.FilePropertyViewModel,
310303
palette: MediaStylePalette
@@ -549,7 +542,7 @@ private fun FileDetailsEditor(
549542
}
550543

551544
@Composable
552-
fun FileDetailsSingleColumn(
545+
private fun FileDetailsSingleColumn(
553546
viewModel: FileDetailsState,
554547
navigateApplication: NavigateApplication,
555548
coverArtBitmap: Bitmap?,
@@ -771,7 +764,7 @@ fun FileDetailsSingleColumn(
771764

772765
@OptIn(ExperimentalComposeUiApi::class)
773766
@Composable
774-
fun BoxWithConstraintsScope.FileDetailsTwoColumn(
767+
private fun BoxWithConstraintsScope.FileDetailsTwoColumn(
775768
viewModel: FileDetailsState,
776769
navigateApplication: NavigateApplication,
777770
coverArtBitmap: Bitmap?,
@@ -924,7 +917,6 @@ fun FileDetailsView(
924917
menuIcons = {
925918
PlayableFileMenu(
926919
viewModel,
927-
coverArtColorState,
928920
playableFileDetailsState
929921
)
930922
}
@@ -936,7 +928,6 @@ fun FileDetailsView(
936928
menuIcons = {
937929
PlayableFileMenu(
938930
viewModel,
939-
coverArtColorState,
940931
playableFileDetailsState,
941932
)
942933
}
@@ -992,7 +983,6 @@ fun FileDetailsView(
992983
menuIcons = {
993984
NowPlayingFileMenu(
994985
viewModel,
995-
coverArtColorState,
996986
nowPlayingFileDetailsSate,
997987
playableFileDetailsState,
998988
)
@@ -1005,7 +995,6 @@ fun FileDetailsView(
1005995
menuIcons = {
1006996
NowPlayingFileMenu(
1007997
viewModel,
1008-
coverArtColorState,
1009998
nowPlayingFileDetailsSate,
1010999
playableFileDetailsState,
10111000
)
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package com.lasthopesoftware.bluewater.client.browsing.files.details
22

3+
import com.lasthopesoftware.bluewater.shared.observables.InteractionState
4+
import com.namehillsoftware.handoff.promises.Promise
5+
36
interface NowPlayingFileDetailsState {
4-
fun removeFile()
7+
val isInPosition: InteractionState<Boolean>
8+
fun removeFile(): Promise<Unit>
59
}

0 commit comments

Comments
 (0)