diff --git a/app/src/main/java/com/capyreader/app/ui/articles/AddFeedButton.kt b/app/src/main/java/com/capyreader/app/ui/articles/AddFeedButton.kt index c7070a4f..49f91520 100644 --- a/app/src/main/java/com/capyreader/app/ui/articles/AddFeedButton.kt +++ b/app/src/main/java/com/capyreader/app/ui/articles/AddFeedButton.kt @@ -4,21 +4,25 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.rounded.Add import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.capyreader.app.R @Composable fun AddFeedButton( onComplete: (feedID: String) -> Unit, + iconOnly: Boolean = false, ) { val (isDialogOpen, setDialogOpen) = rememberSaveable { mutableStateOf(false) } @@ -26,17 +30,28 @@ fun AddFeedButton( setDialogOpen(false) } - OutlinedButton( - onClick = { setDialogOpen(true) }, - ) { - Box(Modifier.padding(end = 8.dp)) { + val onClick = { setDialogOpen(true) } + + if (iconOnly) { + IconButton( + onClick = onClick, + ) { Icon( - imageVector = Icons.Filled.Add, - contentDescription = null, - modifier = Modifier.size(18.dp) + painterResource(R.drawable.icon_add), + contentDescription = stringResource(R.string.nav_add_feed) ) } - Text(stringResource(R.string.nav_add_feed)) + } else { + OutlinedButton(onClick = onClick) { + Box(Modifier.padding(end = 8.dp)) { + Icon( + imageVector = Icons.Rounded.Add, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + } + Text(stringResource(R.string.nav_add_feed)) + } } if (isDialogOpen) { @@ -49,3 +64,12 @@ fun AddFeedButton( ) } } + +@Composable +@Preview +fun AddFeedButtonPreview() { + AddFeedButton( + onComplete = {}, + iconOnly = true + ) +} diff --git a/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt b/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt index 53ae9353..9143bcbd 100644 --- a/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt +++ b/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt @@ -269,6 +269,38 @@ fun ArticleLayout( } } + fun selectFilter() { + if (!filter.hasArticlesSelected()) { + openNextList { onSelectArticleFilter() } + } else { + closeDrawer() + } + } + + fun selectStatus(status: ArticleStatus) { + coroutineScope.launchUI { + openNextStatus { onSelectStatus(status) } + } + } + + fun selectFeed(feed: Feed, folderTitle: String?) { + coroutineScope.launch { + if (!filter.isFeedSelected(feed)) { + openNextList { onSelectFeed(feed.id, folderTitle) } + } else { + closeDrawer() + } + } + } + + fun selectFolder(folder: Folder) { + if (!filter.isFolderSelect(folder)) { + openNextList { onSelectFolder(folder.title) } + } else { + closeDrawer() + } + } + ArticleHandler { selectArticle(it) } @@ -280,38 +312,14 @@ fun ArticleLayout( FeedList( folders = folders, feeds = feeds, - onSelectFolder = { - if (!filter.isFolderSelect(it)) { - openNextList { onSelectFolder(it.title) } - } else { - closeDrawer() - } - }, - onSelectFeed = { feed, folderTitle -> - coroutineScope.launch { - if (!filter.isFeedSelected(feed)) { - openNextList { onSelectFeed(feed.id, folderTitle) } - } else { - closeDrawer() - } - } - }, + onSelectFolder = ::selectFolder, + onSelectFeed = ::selectFeed, onFeedAdded = { onFeedAdded(it) }, onNavigateToSettings = onNavigateToSettings, - onFilterSelect = { - if (!filter.hasArticlesSelected()) { - openNextList { onSelectArticleFilter() } - } else { - closeDrawer() - } - }, + onFilterSelect = ::selectFilter, filter = filter, statusCount = statusCount, - onSelectStatus = { - coroutineScope.launchUI { - openNextStatus { onSelectStatus(it) } - } - } + onSelectStatus = ::selectStatus ) }, listPane = { diff --git a/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusBar.kt b/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusBar.kt new file mode 100644 index 00000000..df78527d --- /dev/null +++ b/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusBar.kt @@ -0,0 +1,46 @@ +package com.capyreader.app.ui.articles + +import androidx.compose.material3.SegmentedButton +import androidx.compose.material3.SegmentedButtonDefaults +import androidx.compose.material3.SingleChoiceSegmentedButtonRow +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import com.jocmp.capy.ArticleStatus + +@Composable +fun ArticleStatusBar( + onSelectStatus: (status: ArticleStatus) -> Unit, + status: ArticleStatus, +) { + SingleChoiceSegmentedButtonRow { + options.forEachIndexed { index, buttonStatus -> + SegmentedButton( + shape = SegmentedButtonDefaults.itemShape(index = index, count = options.size), + onClick = { + if (buttonStatus != status) { + onSelectStatus(buttonStatus) + } + }, + icon = {}, + selected = buttonStatus == status + ) { + ArticleStatusIcon(status = buttonStatus) + } + } + } +} + +val options = listOf( + ArticleStatus.ALL, + ArticleStatus.UNREAD, + ArticleStatus.STARRED, +) + +@Composable +@Preview +fun ArticleStatusBarPreview() { + ArticleStatusBar( + onSelectStatus = {}, + status = ArticleStatus.UNREAD + ) +} diff --git a/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusIcon.kt b/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusIcon.kt index 6959c980..5443b374 100644 --- a/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusIcon.kt +++ b/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusIcon.kt @@ -1,14 +1,11 @@ package com.capyreader.app.ui.articles -import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.rounded.Notes import androidx.compose.material.icons.rounded.Star import androidx.compose.material3.Icon import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp import com.capyreader.app.R import com.jocmp.capy.ArticleStatus @@ -23,7 +20,6 @@ fun ArticleStatusIcon(status: ArticleStatus) { ArticleStatus.UNREAD -> Icon( painterResource(R.drawable.icon_circle_filled), contentDescription = null, - modifier = Modifier.padding(1.dp) ) ArticleStatus.STARRED -> Icon( diff --git a/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusMenu.kt b/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusMenu.kt deleted file mode 100644 index a892cd24..00000000 --- a/app/src/main/java/com/capyreader/app/ui/articles/ArticleStatusMenu.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.capyreader.app.ui.articles - -import androidx.compose.foundation.layout.widthIn -import androidx.compose.material3.DropdownMenu -import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.jocmp.capy.ArticleStatus -import com.capyreader.app.R - -@Composable -fun ArticleFilterMenu( - expanded: Boolean, - onDismissRequest: () -> Unit, - onSelect: (status: ArticleStatus) -> Unit -) { - val checkedSelect = { status: ArticleStatus -> - onSelect(status) - } - - DropdownMenu( - expanded = expanded, - onDismissRequest = { onDismissRequest() }, - modifier = Modifier.widthIn(min = 200.dp) - ) { - DropdownMenuItem( - leadingIcon = { - ArticleStatusIcon(status = ArticleStatus.ALL) - }, - text = { Text(stringResource(R.string.filter_all)) }, - onClick = { checkedSelect(ArticleStatus.ALL) }, - ) - DropdownMenuItem( - leadingIcon = { - ArticleStatusIcon(status = ArticleStatus.UNREAD) - }, - text = { Text(stringResource(R.string.filter_unread)) }, - onClick = { checkedSelect(ArticleStatus.UNREAD) }, - ) - DropdownMenuItem( - leadingIcon = { - ArticleStatusIcon(status = ArticleStatus.STARRED) - }, - text = { Text(stringResource(id = R.string.filter_starred)) }, - onClick = { checkedSelect(ArticleStatus.STARRED) }, - ) - } -} - -@Preview -@Composable -fun ArticleFilterNavigationBarPreview() { - ArticleFilterMenu( - expanded = true, - onDismissRequest = {}, - onSelect = {} - ) -} diff --git a/app/src/main/java/com/capyreader/app/ui/articles/FeedList.kt b/app/src/main/java/com/capyreader/app/ui/articles/FeedList.kt index 70108ce4..b028a307 100644 --- a/app/src/main/java/com/capyreader/app/ui/articles/FeedList.kt +++ b/app/src/main/java/com/capyreader/app/ui/articles/FeedList.kt @@ -10,19 +10,17 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowDropDown -import androidx.compose.material.icons.filled.Settings +import androidx.compose.material.icons.rounded.Settings import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationDrawerItem -import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -70,30 +68,36 @@ fun FeedList( ) { Row( modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp), + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically ) { - TextButton( - onClick = { setMenuExpanded(true) }, - ) { - Text( - stringResource(articleStatus.navigationTitle), - style = MaterialTheme.typography.titleLarge - ) - Box(Modifier.padding(start = 8.dp)) { - Icon( - imageVector = Icons.Filled.ArrowDropDown, - contentDescription = null, - ) - } - } - ArticleFilterMenu( - expanded = isMenuExpanded, - onDismissRequest = { setMenuExpanded(false) }, - onSelect = onStatusChange, + Text( + stringResource(R.string.feed_nav_drawer_title), + style = MaterialTheme.typography.titleLarge, + modifier = Modifier + .padding( + vertical = 24.dp, + horizontal = 12.dp + ), ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + IconButton(onClick = { onNavigateToSettings() }) { + Icon( + imageVector = Icons.Rounded.Settings, + contentDescription = stringResource(R.string.settings) + ) + } + AddFeedButton( + iconOnly = true, + onComplete = { + onFeedAdded(it) + } + ) + } } - NavigationDrawerItem( icon = { ArticleStatusIcon(status = articleStatus) }, label = { @@ -147,27 +151,16 @@ fun FeedList( HorizontalDivider() - Surface( - color = MaterialTheme.colorScheme.surfaceContainerLow + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 8.dp), + horizontalArrangement = Arrangement.Center ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp, vertical = 8.dp), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - IconButton(onClick = { onNavigateToSettings() }) { - Icon( - imageVector = Icons.Filled.Settings, - contentDescription = stringResource(R.string.settings) - ) - } - AddFeedButton( - onComplete = { - onFeedAdded(it) - } - ) - } + ArticleStatusBar( + status = filter.status, + onSelectStatus = onSelectStatus, + ) } } } diff --git a/app/src/main/java/com/capyreader/app/ui/articles/FilterAppBarTitle.kt b/app/src/main/java/com/capyreader/app/ui/articles/FilterAppBarTitle.kt index c610c961..2dbc1d1a 100644 --- a/app/src/main/java/com/capyreader/app/ui/articles/FilterAppBarTitle.kt +++ b/app/src/main/java/com/capyreader/app/ui/articles/FilterAppBarTitle.kt @@ -55,7 +55,6 @@ fun FilterAppBarTitle( overflow = TextOverflow.Ellipsis ) } - } @OptIn(ExperimentalMaterial3Api::class) diff --git a/app/src/main/java/com/capyreader/app/ui/articles/list/FeedListTopBar.kt b/app/src/main/java/com/capyreader/app/ui/articles/list/FeedListTopBar.kt index 7d111c73..1dee3821 100644 --- a/app/src/main/java/com/capyreader/app/ui/articles/list/FeedListTopBar.kt +++ b/app/src/main/java/com/capyreader/app/ui/articles/list/FeedListTopBar.kt @@ -81,7 +81,7 @@ fun FeedListTopBar( contentAlignment = Alignment.Center ) { SearchTextField( - value = search.query ?: "", + value = search.query.orEmpty(), onValueChange = { search.update(it) onSearchQueryChange() diff --git a/app/src/main/res/drawable/icon_add.xml b/app/src/main/res/drawable/icon_add.xml new file mode 100644 index 00000000..e476d332 --- /dev/null +++ b/app/src/main/res/drawable/icon_add.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/icon_notes.xml b/app/src/main/res/drawable/icon_notes.xml deleted file mode 100644 index d9cdd33c..00000000 --- a/app/src/main/res/drawable/icon_notes.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cb66a801..1be530bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -227,4 +227,5 @@ Open Next Feed Failed to fetch article Failed to parse article + Feeds