Skip to content

Commit de061c8

Browse files
committed
feat: make new collapsible section headers sticky
1 parent c372bbc commit de061c8

9 files changed

Lines changed: 126 additions & 126 deletions

File tree

shared/feature/details/src/commonMain/kotlin/ly/david/musicsearch/shared/feature/details/area/AreaSection.kt

Lines changed: 0 additions & 45 deletions
This file was deleted.

shared/feature/details/src/commonMain/kotlin/ly/david/musicsearch/shared/feature/details/artist/ArtistDetailsTabUi.kt

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ import ly.david.musicsearch.shared.domain.getNameWithDisambiguation
1515
import ly.david.musicsearch.shared.domain.listitem.RelationListItemModel
1616
import ly.david.musicsearch.shared.domain.network.MusicBrainzEntityType
1717
import ly.david.musicsearch.shared.domain.network.MusicBrainzItemClickHandler
18-
import ly.david.musicsearch.shared.feature.details.area.AreaSection
1918
import ly.david.musicsearch.shared.feature.details.utils.CollapsibleSection
2019
import ly.david.musicsearch.shared.feature.details.utils.DetailsTabUi
2120
import ly.david.musicsearch.shared.feature.details.utils.DetailsTabUiEvent
2221
import ly.david.musicsearch.shared.feature.details.utils.DetailsTabUiState
2322
import ly.david.musicsearch.shared.feature.details.utils.LastListenedListItemWithMoreActions
23+
import ly.david.musicsearch.shared.feature.details.utils.areaSection
2424
import ly.david.musicsearch.ui.common.artist.getDisplayString
2525
import ly.david.musicsearch.ui.common.component.ClickableItem
2626
import ly.david.musicsearch.ui.common.icons.ChevronRight
@@ -72,17 +72,15 @@ internal fun ArtistDetailsTabUi(
7272
},
7373
bringYourOwnLabelsSection = {
7474
artist.run {
75-
item {
76-
AreaSection(
77-
areaListItemModel = areaListItemModel,
78-
filterText = filterText,
79-
onItemClick = onItemClick,
80-
collapsed = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Area),
81-
onCollapseExpand = {
82-
eventSink(DetailsTabUiEvent.ToggleCollapseExpandSection(CollapsibleSection.Area))
83-
},
84-
)
85-
}
75+
areaSection(
76+
areaListItemModel = areaListItemModel,
77+
filterText = filterText,
78+
onItemClick = onItemClick,
79+
collapsed = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Area),
80+
onCollapseExpand = {
81+
eventSink(DetailsTabUiEvent.ToggleCollapseExpandSection(CollapsibleSection.Area))
82+
},
83+
)
8684

8785
// TODO: begin area, end area
8886

shared/feature/details/src/commonMain/kotlin/ly/david/musicsearch/shared/feature/details/label/LabelDetailsTabUi.kt

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import ly.david.musicsearch.shared.domain.common.ifNotNull
88
import ly.david.musicsearch.shared.domain.common.ifNotNullOrEmpty
99
import ly.david.musicsearch.shared.domain.details.LabelDetailsModel
1010
import ly.david.musicsearch.shared.domain.network.MusicBrainzItemClickHandler
11-
import ly.david.musicsearch.shared.feature.details.area.AreaSection
1211
import ly.david.musicsearch.shared.feature.details.utils.CollapsibleSection
1312
import ly.david.musicsearch.shared.feature.details.utils.DetailsTabUi
1413
import ly.david.musicsearch.shared.feature.details.utils.DetailsTabUiEvent
1514
import ly.david.musicsearch.shared.feature.details.utils.DetailsTabUiState
15+
import ly.david.musicsearch.shared.feature.details.utils.areaSection
1616
import ly.david.musicsearch.ui.common.label.getDisplayString
1717
import ly.david.musicsearch.ui.common.text.TextWithHeading
1818
import musicsearch.ui.common.generated.resources.Res
@@ -92,19 +92,15 @@ internal fun LabelDetailsTabUi(
9292
}
9393
},
9494
bringYourOwnLabelsSection = {
95-
item {
96-
label.area?.let { area ->
97-
AreaSection(
98-
areaListItemModel = area,
99-
filterText = filterText,
100-
onItemClick = onItemClick,
101-
collapsed = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Area),
102-
onCollapseExpand = {
103-
eventSink(DetailsTabUiEvent.ToggleCollapseExpandSection(CollapsibleSection.Area))
104-
},
105-
)
106-
}
107-
}
95+
areaSection(
96+
areaListItemModel = label.area,
97+
filterText = filterText,
98+
onItemClick = onItemClick,
99+
collapsed = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Area),
100+
onCollapseExpand = {
101+
eventSink(DetailsTabUiEvent.ToggleCollapseExpandSection(CollapsibleSection.Area))
102+
},
103+
)
108104
},
109105
)
110106
}

shared/feature/details/src/commonMain/kotlin/ly/david/musicsearch/shared/feature/details/place/PlaceDetailsTabUi.kt

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ import androidx.compose.material3.SnackbarHostState
44
import androidx.compose.runtime.Composable
55
import androidx.compose.ui.Modifier
66
import ly.david.musicsearch.shared.domain.common.ifNotEmpty
7-
import ly.david.musicsearch.shared.domain.common.ifNotNull
87
import ly.david.musicsearch.shared.domain.details.PlaceDetailsModel
98
import ly.david.musicsearch.shared.domain.network.MusicBrainzItemClickHandler
10-
import ly.david.musicsearch.shared.feature.details.area.AreaSection
119
import ly.david.musicsearch.shared.feature.details.utils.CollapsibleSection
1210
import ly.david.musicsearch.shared.feature.details.utils.DetailsTabUi
1311
import ly.david.musicsearch.shared.feature.details.utils.DetailsTabUiEvent
1412
import ly.david.musicsearch.shared.feature.details.utils.DetailsTabUiState
13+
import ly.david.musicsearch.shared.feature.details.utils.areaSection
1514
import ly.david.musicsearch.ui.common.listitem.ListSeparatorHeader
1615
import ly.david.musicsearch.ui.common.place.CoordinateListItem
1716
import ly.david.musicsearch.ui.common.place.getDisplayString
@@ -74,19 +73,15 @@ internal fun PlaceDetailsTabUi(
7473
}
7574
},
7675
bringYourOwnLabelsSection = {
77-
place.area?.ifNotNull { area ->
78-
item {
79-
AreaSection(
80-
areaListItemModel = area,
81-
filterText = filterText,
82-
onItemClick = onItemClick,
83-
collapsed = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Area),
84-
onCollapseExpand = {
85-
eventSink(DetailsTabUiEvent.ToggleCollapseExpandSection(CollapsibleSection.Area))
86-
},
87-
)
88-
}
89-
}
76+
areaSection(
77+
areaListItemModel = place.area,
78+
filterText = filterText,
79+
onItemClick = onItemClick,
80+
collapsed = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Area),
81+
onCollapseExpand = {
82+
eventSink(DetailsTabUiEvent.ToggleCollapseExpandSection(CollapsibleSection.Area))
83+
},
84+
)
9085

9186
val coordinates = place.coordinates
9287
val showCoordinates = coordinates.latitude != null && coordinates.longitude != null

shared/feature/details/src/commonMain/kotlin/ly/david/musicsearch/shared/feature/details/release/ReleaseDetailsTabUi.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ private fun LazyListScope.releaseLabelsSection(
248248
).any { it?.lowercase()?.contains(searchText) == true }
249249
}.toPersistentList()
250250
labels.ifNotNullOrEmpty {
251-
item {
251+
stickyHeader {
252252
val numberOfFilteredItems = getNumberOfFilteredItems(
253253
filteredCount = filteredLabels.size,
254254
total = labels.size,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package ly.david.musicsearch.shared.feature.details.utils
2+
3+
import androidx.compose.foundation.lazy.LazyListScope
4+
import ly.david.musicsearch.shared.domain.listitem.AreaListItemModel
5+
import ly.david.musicsearch.shared.domain.network.MusicBrainzEntityType
6+
import ly.david.musicsearch.shared.domain.network.MusicBrainzItemClickHandler
7+
import ly.david.musicsearch.ui.common.area.AreaListItem
8+
import ly.david.musicsearch.ui.common.listitem.CollapsibleListSeparatorHeader
9+
import ly.david.musicsearch.ui.common.locale.getAnnotatedName
10+
import musicsearch.ui.common.generated.resources.Res
11+
import musicsearch.ui.common.generated.resources.area
12+
import org.jetbrains.compose.resources.stringResource
13+
14+
internal fun LazyListScope.areaSection(
15+
areaListItemModel: AreaListItemModel?,
16+
filterText: String = "",
17+
onItemClick: MusicBrainzItemClickHandler = { _, _ -> },
18+
collapsed: Boolean = false,
19+
onCollapseExpand: () -> Unit = {},
20+
) {
21+
areaListItemModel?.run {
22+
stickyHeader {
23+
CollapsibleListSeparatorHeader(
24+
text = stringResource(Res.string.area),
25+
collapsed = collapsed,
26+
onClick = onCollapseExpand,
27+
)
28+
}
29+
30+
item {
31+
if (getAnnotatedName().contains(filterText, ignoreCase = true) && !collapsed) {
32+
AreaListItem(
33+
area = this@run,
34+
filterText = filterText,
35+
showType = false,
36+
showIcon = false,
37+
showEditCollection = false,
38+
onAreaClick = {
39+
onItemClick(
40+
MusicBrainzEntityType.AREA,
41+
id,
42+
)
43+
},
44+
)
45+
}
46+
}
47+
}
48+
}

shared/feature/details/src/commonMain/kotlin/ly/david/musicsearch/shared/feature/details/utils/DetailsTabUi.kt

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import androidx.compose.foundation.layout.size
66
import androidx.compose.foundation.lazy.LazyColumn
77
import androidx.compose.foundation.lazy.LazyListScope
88
import androidx.compose.material3.ExperimentalMaterial3Api
9+
import androidx.compose.material3.HorizontalDivider
910
import androidx.compose.material3.Icon
11+
import androidx.compose.material3.MaterialTheme
1012
import androidx.compose.material3.SnackbarDuration
1113
import androidx.compose.material3.SnackbarHostState
1214
import androidx.compose.material3.SnackbarResult
@@ -54,7 +56,7 @@ import ly.david.musicsearch.ui.common.screen.TagDetailsScreen
5456
import ly.david.musicsearch.ui.common.screen.showInBottomSheetForResult
5557
import ly.david.musicsearch.ui.common.snackbar.FeedbackSnackbarVisuals
5658
import ly.david.musicsearch.ui.common.theme.STANDARD_ICON_SIZE
57-
import ly.david.musicsearch.ui.common.wikimedia.WikipediaSection
59+
import ly.david.musicsearch.ui.common.wikimedia.wikipediaSection
5860
import musicsearch.ui.common.generated.resources.Res
5961
import musicsearch.ui.common.generated.resources.area
6062
import musicsearch.ui.common.generated.resources.artist
@@ -118,6 +120,8 @@ internal fun <T : MusicBrainzDetailsModel> DetailsTabUi(
118120
state = detailsTabUiState.lazyListState,
119121
) {
120122
detailsModel.run {
123+
val hideInformation = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Information)
124+
121125
item {
122126
if (filterText.isBlank()) {
123127
LargeImage(
@@ -127,16 +131,21 @@ internal fun <T : MusicBrainzDetailsModel> DetailsTabUi(
127131
},
128132
)
129133
}
134+
// To reserve space for the async image
135+
// Without this, the image would load off the screen
136+
HorizontalDivider(
137+
color = MaterialTheme.colorScheme.surfaceVariant,
138+
)
139+
}
130140

131-
val hideInformation = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Information)
132-
141+
stickyHeader {
133142
val numberOfImages = detailsTabUiState.numberOfImages
134143
val hasNoImages = numberOfImages == null
135144
val endContent: @Composable (() -> Unit)? = if (hasNoImages) {
136145
null
137146
} else {
138147
{
139-
Surface(modifier = Modifier) {
148+
Surface {
140149
Row(
141150
modifier = Modifier
142151
.padding(
@@ -170,7 +179,8 @@ internal fun <T : MusicBrainzDetailsModel> DetailsTabUi(
170179
endContent = endContent,
171180
verticalPadding = if (hasNoImages) 8.dp else 0.dp,
172181
)
173-
182+
}
183+
item {
174184
if (!hideInformation) {
175185
entityInfoSection()
176186
}
@@ -243,16 +253,14 @@ internal fun <T : MusicBrainzDetailsModel> DetailsTabUi(
243253
},
244254
)
245255

246-
item {
247-
WikipediaSection(
248-
extract = detailsTabUiState.wikipediaExtract,
249-
filterText = filterText,
250-
collapsed = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Wikipedia),
251-
onCollapseExpand = {
252-
eventSink(DetailsTabUiEvent.ToggleCollapseExpandSection(CollapsibleSection.Wikipedia))
253-
},
254-
)
255-
}
256+
wikipediaSection(
257+
extract = detailsTabUiState.wikipediaExtract,
258+
filterText = filterText,
259+
collapsed = detailsTabUiState.isSectionCollapsed.contains(CollapsibleSection.Wikipedia),
260+
onCollapseExpand = {
261+
eventSink(DetailsTabUiEvent.ToggleCollapseExpandSection(CollapsibleSection.Wikipedia))
262+
},
263+
)
256264

257265
bringYourOwnLabelsSection()
258266

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ly.david.musicsearch.ui.common.wikimedia
22

3+
import androidx.compose.foundation.lazy.LazyColumn
34
import androidx.compose.material3.Surface
45
import androidx.compose.runtime.Composable
56
import androidx.compose.ui.tooling.preview.PreviewLightDark
@@ -11,17 +12,19 @@ import ly.david.musicsearch.ui.common.preview.PreviewTheme
1112
internal fun PreviewWikipediaSection() {
1213
PreviewTheme {
1314
Surface {
14-
WikipediaSection(
15-
extract = WikipediaExtract(
16-
extract = "Tricot (Japanese: \u30c8\u30ea\u30b3, Hepburn: toriko, ) is a Japanese rock band " +
17-
"from Kyoto. The band was formed in 2010 by vocalist and guitarist " +
18-
"Ikumi \"Ikkyu\" Nakajima, guitarist Motoko \"Motifour\" Kida, and bassist " +
19-
"Hiromi \"Hirohiro\" Sagane. Known for their intricate rhythms and visual identity, " +
20-
"they have released seven studio albums. Their musical style has been described by " +
21-
"Rolling Stone as \"adrenalized math rock sped up and given pop's candy coating\".",
22-
wikipediaUrl = "https://en.wikipedia.org/wiki/Tricot_(band)",
23-
),
24-
)
15+
LazyColumn {
16+
wikipediaSection(
17+
extract = WikipediaExtract(
18+
extract = "Tricot (Japanese: \u30c8\u30ea\u30b3, Hepburn: toriko, ) is a Japanese rock band " +
19+
"from Kyoto. The band was formed in 2010 by vocalist and guitarist " +
20+
"Ikumi \"Ikkyu\" Nakajima, guitarist Motoko \"Motifour\" Kida, and bassist " +
21+
"Hiromi \"Hirohiro\" Sagane. Known for their intricate rhythms and visual identity, " +
22+
"they have released seven studio albums. Their musical style has been described by " +
23+
"Rolling Stone as \"adrenalized math rock sped up and given pop's candy coating\".",
24+
wikipediaUrl = "https://en.wikipedia.org/wiki/Tricot_(band)",
25+
),
26+
)
27+
}
2528
}
2629
}
2730
}

0 commit comments

Comments
 (0)