Skip to content

Commit 4cf9676

Browse files
authored
Move List settings into a separate panel (#2001)
Add a preview for the Article Row too
1 parent 78e1428 commit 4cf9676

5 files changed

Lines changed: 256 additions & 59 deletions

File tree

app/src/main/java/com/capyreader/app/ui/settings/SettingsView.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.capyreader.app.ui.isCompact
2222
import com.capyreader.app.ui.provideLinkOpener
2323
import com.capyreader.app.ui.settings.panels.AboutSettingsPanel
2424
import com.capyreader.app.ui.settings.panels.AccountSettingsPanel
25+
import com.capyreader.app.ui.settings.panels.ArticleListSettingsPanel
2526
import com.capyreader.app.ui.settings.panels.DisplaySettingsPanel
2627
import com.capyreader.app.ui.settings.panels.GeneralSettingsPanel
2728
import com.capyreader.app.ui.settings.panels.GesturesSettingPanel
@@ -105,11 +106,15 @@ fun SettingsView(
105106
SettingsPanel.Display -> DisplaySettingsPanel(
106107
onNavigateToUnreadBadges = {
107108
navigateToPanel(SettingsPanel.UnreadBadges)
109+
},
110+
onNavigateToArticleList = {
111+
navigateToPanel(SettingsPanel.ArticleList)
108112
}
109113
)
110114
SettingsPanel.Gestures -> GesturesSettingPanel()
111115
SettingsPanel.Account -> AccountSettingsPanel(onRemoveAccount = onRemoveAccount)
112116
SettingsPanel.About -> AboutSettingsPanel()
117+
SettingsPanel.ArticleList -> ArticleListSettingsPanel()
113118
SettingsPanel.UnreadBadges -> UnreadBadgesSettingsPanel(
114119
badgeStyle = viewModel.badgeStyle,
115120
updateBadgeStyle = viewModel::updateBadgeStyle,

app/src/main/java/com/capyreader/app/ui/settings/panels/ArticleListSettings.kt

Lines changed: 186 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,48 @@
11
package com.capyreader.app.ui.settings.panels
22

3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.border
5+
import androidx.compose.foundation.layout.Arrangement
6+
import androidx.compose.foundation.layout.Box
37
import androidx.compose.foundation.layout.Column
8+
import androidx.compose.foundation.layout.Row
9+
import androidx.compose.foundation.layout.Spacer
10+
import androidx.compose.foundation.layout.aspectRatio
11+
import androidx.compose.foundation.layout.fillMaxWidth
412
import androidx.compose.foundation.layout.padding
13+
import androidx.compose.foundation.layout.size
14+
import androidx.compose.foundation.layout.width
15+
import androidx.compose.material3.Icon
16+
import androidx.compose.material3.ListItemDefaults
17+
import androidx.compose.material3.MaterialTheme
518
import androidx.compose.material3.Slider
19+
import androidx.compose.material3.Text
620
import androidx.compose.runtime.Composable
721
import androidx.compose.runtime.Immutable
22+
import androidx.compose.ui.Alignment
823
import androidx.compose.ui.Modifier
24+
import androidx.compose.ui.draw.clip
25+
import androidx.compose.ui.graphics.Shape
26+
import androidx.compose.ui.res.painterResource
927
import androidx.compose.ui.res.stringResource
28+
import androidx.compose.ui.text.font.FontWeight
29+
import androidx.compose.ui.text.style.TextOverflow
1030
import androidx.compose.ui.tooling.preview.Preview
1131
import androidx.compose.ui.unit.dp
1232
import com.capyreader.app.R
1333
import com.capyreader.app.common.ImagePreview
1434
import com.capyreader.app.common.RowItem
35+
import com.capyreader.app.preferences.AppTheme
1536
import com.capyreader.app.ui.articles.ArticleListFontScale
37+
import com.capyreader.app.ui.articles.ArticleRowOptions
38+
import com.capyreader.app.ui.articles.FaviconBadge
39+
import com.capyreader.app.ui.articles.StyleProviders
40+
import com.capyreader.app.ui.articles.list.ArticleListItem
1641
import com.capyreader.app.ui.components.FormSection
1742
import com.capyreader.app.ui.components.LabelStyle
1843
import com.capyreader.app.ui.components.TextSwitch
1944
import com.capyreader.app.ui.settings.PreferenceSelect
45+
import com.capyreader.app.ui.theme.LocalAppTheme
2046
import kotlin.math.roundToInt
2147

2248
@Immutable
@@ -42,6 +68,24 @@ fun ArticleListSettings(
4268
val fontScales = ArticleListFontScale.entries
4369

4470
Column {
71+
PreviewArticleRow(options = options)
72+
73+
FormSection(
74+
title = stringResource(R.string.article_font_scale_label),
75+
labelStyle = LabelStyle.COMPACT,
76+
) {
77+
RowItem {
78+
Slider(
79+
steps = fontScales.size - 2,
80+
valueRange = 0f..(fontScales.size - 1).toFloat(),
81+
value = options.fontScale.ordinal.toFloat(),
82+
onValueChange = {
83+
options.updateFontScale(fontScales[it.roundToInt()])
84+
}
85+
)
86+
}
87+
}
88+
4589
RowItem {
4690
TextSwitch(
4791
onCheckedChange = options.updateFeedName,
@@ -75,26 +119,155 @@ fun ArticleListSettings(
75119
stringResource(id = it.translationKey)
76120
}
77121
)
122+
}
123+
}
78124

79-
FormSection(
80-
modifier = Modifier.padding(top = 16.dp),
81-
title = stringResource(R.string.article_font_scale_label),
82-
labelStyle = LabelStyle.COMPACT,
125+
@Composable
126+
private fun PreviewArticleRow(options: ArticleListOptions) {
127+
val rowOptions = ArticleRowOptions(
128+
showIcon = options.showFeedIcons,
129+
showSummary = options.showSummary,
130+
showFeedName = options.showFeedName,
131+
imagePreview = options.imagePreview,
132+
fontScale = options.fontScale,
133+
shortenTitles = options.shortenTitles,
134+
dim = false,
135+
)
136+
val colors = ListItemDefaults.colors()
137+
val overlineColor = colors.overlineContentColor
138+
139+
StyleProviders(options = rowOptions) {
140+
Column(
141+
modifier = Modifier
142+
.padding(16.dp)
143+
.border(
144+
width = 1.dp,
145+
color = MaterialTheme.colorScheme.outlineVariant,
146+
shape = MaterialTheme.shapes.medium,
147+
)
83148
) {
84-
RowItem {
85-
Slider(
86-
steps = fontScales.size - 2,
87-
valueRange = 0f..(fontScales.size - 1).toFloat(),
88-
value = options.fontScale.ordinal.toFloat(),
89-
onValueChange = {
90-
options.updateFontScale(fontScales[it.roundToInt()])
91-
}
149+
ArticleListItem(
150+
headlineContent = {
151+
Text(
152+
text = PREVIEW_TITLE,
153+
maxLines = if (options.shortenTitles) 3 else Int.MAX_VALUE,
154+
overflow = TextOverflow.Ellipsis,
155+
fontWeight = FontWeight.Bold,
92156
)
93-
}
157+
},
158+
overlineContent = {
159+
Row(
160+
horizontalArrangement = Arrangement.SpaceBetween,
161+
verticalAlignment = Alignment.CenterVertically,
162+
modifier = Modifier
163+
.fillMaxWidth()
164+
.padding(bottom = 2.dp)
165+
) {
166+
if (options.showFeedName) {
167+
Text(
168+
text = PREVIEW_FEED_NAME,
169+
color = overlineColor,
170+
maxLines = 1,
171+
overflow = TextOverflow.Ellipsis,
172+
modifier = Modifier.weight(1f)
173+
)
174+
Spacer(Modifier.width(16.dp))
175+
}
176+
Text(
177+
text = PREVIEW_TIME,
178+
color = overlineColor,
179+
maxLines = 1,
180+
)
181+
}
182+
},
183+
supportingContent = if (options.showSummary || options.imagePreview == ImagePreview.LARGE) {
184+
{
185+
Column(
186+
verticalArrangement = Arrangement.spacedBy(4.dp),
187+
modifier = Modifier.padding(vertical = 4.dp),
188+
) {
189+
if (options.showSummary) {
190+
Text(
191+
text = PREVIEW_SUMMARY,
192+
maxLines = 2,
193+
overflow = TextOverflow.Ellipsis,
194+
)
195+
}
196+
if (options.imagePreview == ImagePreview.LARGE) {
197+
PreviewImage(imagePreview = options.imagePreview)
198+
}
199+
}
200+
}
201+
} else {
202+
null
203+
},
204+
leadingContent = if (options.showFeedIcons) {
205+
{ FaviconBadge(url = null) }
206+
} else {
207+
null
208+
},
209+
trailingContent = if (options.imagePreview.showInline()) {
210+
{ PreviewImage(imagePreview = options.imagePreview) }
211+
} else {
212+
null
213+
},
214+
)
94215
}
95216
}
96217
}
97218

219+
@Composable
220+
private fun PreviewImage(imagePreview: ImagePreview) {
221+
val sizeModifier = when (imagePreview) {
222+
ImagePreview.SMALL -> Modifier.size(56.dp)
223+
ImagePreview.MEDIUM -> Modifier.size(84.dp)
224+
else -> Modifier.fillMaxWidth().aspectRatio(3 / 2f)
225+
}
226+
227+
val shape = MaterialTheme.shapes.small
228+
229+
Box(
230+
contentAlignment = Alignment.Center,
231+
modifier = sizeModifier
232+
.monochromeBorder(shape)
233+
.clip(shape)
234+
.background(MaterialTheme.colorScheme.surfaceContainer)
235+
) {
236+
Icon(
237+
painter = painterResource(R.drawable.icon_empty_list),
238+
contentDescription = null,
239+
tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
240+
modifier = Modifier.size(
241+
when (imagePreview) {
242+
ImagePreview.SMALL -> 48.dp
243+
ImagePreview.MEDIUM -> 64.dp
244+
else -> 80.dp
245+
}
246+
)
247+
)
248+
}
249+
}
250+
251+
@Composable
252+
private fun Modifier.monochromeBorder(shape: Shape): Modifier {
253+
val isMonochrome = LocalAppTheme.current.value == AppTheme.MONOCHROME
254+
255+
return if (isMonochrome) {
256+
border(
257+
width = 1.dp,
258+
color = MaterialTheme.colorScheme.outline,
259+
shape = shape,
260+
)
261+
} else {
262+
this
263+
}
264+
}
265+
266+
private const val PREVIEW_TITLE = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
267+
private const val PREVIEW_FEED_NAME = "Lorem Ipsum"
268+
private const val PREVIEW_TIME = "3h"
269+
private const val PREVIEW_SUMMARY = "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam."
270+
98271
@Preview
99272
@Composable
100273
private fun ArticleListSettingsPreview() {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.capyreader.app.ui.settings.panels
2+
3+
import androidx.compose.runtime.Composable
4+
import org.koin.androidx.compose.koinViewModel
5+
6+
@Composable
7+
fun ArticleListSettingsPanel(
8+
viewModel: DisplaySettingsViewModel = koinViewModel(),
9+
) {
10+
ArticleListSettings(
11+
options = ArticleListOptions(
12+
imagePreview = viewModel.imagePreview,
13+
showSummary = viewModel.showSummary,
14+
fontScale = viewModel.fontScale,
15+
showFeedIcons = viewModel.showFeedIcons,
16+
showFeedName = viewModel.showFeedName,
17+
shortenTitles = viewModel.shortenTitles,
18+
updateImagePreview = viewModel::updateImagePreview,
19+
updateSummary = viewModel::updateSummary,
20+
updateFeedName = viewModel::updateFeedName,
21+
updateFeedIcons = viewModel::updateFeedIcons,
22+
updateFontScale = viewModel::updateFontScale,
23+
updateShortenTitles = viewModel::updateShortenTitles,
24+
)
25+
)
26+
}

0 commit comments

Comments
 (0)