mirror of https://github.com/readrops/Readrops.git
Improve feed item lookingin FeedTab and add initial feed bottom sheet
This commit is contained in:
parent
d76be31b75
commit
6b50d40800
|
@ -0,0 +1,141 @@
|
||||||
|
package com.readrops.app.compose.feeds
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Create
|
||||||
|
import androidx.compose.material.icons.filled.Delete
|
||||||
|
import androidx.compose.material3.Divider
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.res.vectorResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import coil.compose.AsyncImage
|
||||||
|
import com.readrops.app.compose.R
|
||||||
|
import com.readrops.app.compose.util.theme.LargeSpacer
|
||||||
|
import com.readrops.app.compose.util.theme.MediumSpacer
|
||||||
|
import com.readrops.app.compose.util.theme.VeryShortSpacer
|
||||||
|
import com.readrops.app.compose.util.theme.spacing
|
||||||
|
import com.readrops.db.entities.Feed
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun FeedModalBottomSheet(
|
||||||
|
feed: Feed,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onOpen: () -> Unit,
|
||||||
|
onModify: () -> Unit,
|
||||||
|
onDelete: () -> Unit,
|
||||||
|
) {
|
||||||
|
ModalBottomSheet(
|
||||||
|
onDismissRequest = { onDismissRequest() }
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.padding(
|
||||||
|
horizontal = 24.dp
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
AsyncImage(
|
||||||
|
model = feed.iconUrl,
|
||||||
|
contentDescription = feed.name!!,
|
||||||
|
modifier = Modifier.size(48.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
MediumSpacer()
|
||||||
|
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = feed.name!!,
|
||||||
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
|
)
|
||||||
|
|
||||||
|
VeryShortSpacer()
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "folder name if it exists",
|
||||||
|
style = MaterialTheme.typography.labelSmall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MediumSpacer()
|
||||||
|
|
||||||
|
Divider(
|
||||||
|
modifier = Modifier.padding(
|
||||||
|
horizontal = MaterialTheme.spacing.shortSpacing
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
MediumSpacer()
|
||||||
|
|
||||||
|
BottomSheetOption(
|
||||||
|
text = "Open",
|
||||||
|
icon = ImageVector.vectorResource(id = R.drawable.ic_open_in_browser),
|
||||||
|
onClick = onOpen
|
||||||
|
)
|
||||||
|
|
||||||
|
BottomSheetOption(
|
||||||
|
text = "Modify",
|
||||||
|
icon = Icons.Default.Create,
|
||||||
|
onClick = onModify
|
||||||
|
)
|
||||||
|
|
||||||
|
BottomSheetOption(
|
||||||
|
text = "Delete",
|
||||||
|
icon = Icons.Default.Delete,
|
||||||
|
onClick = onDelete
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
LargeSpacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BottomSheetOption(
|
||||||
|
text: String,
|
||||||
|
icon: ImageVector,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.clickable { onClick() }
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(
|
||||||
|
horizontal = 16.dp,
|
||||||
|
vertical = 8.dp
|
||||||
|
)
|
||||||
|
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = icon,
|
||||||
|
contentDescription = text
|
||||||
|
)
|
||||||
|
|
||||||
|
MediumSpacer()
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,34 +1,54 @@
|
||||||
package com.readrops.app.compose.feeds
|
package com.readrops.app.compose.feeds
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.combinedClickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import coil.compose.AsyncImage
|
||||||
|
import com.readrops.app.compose.util.theme.ShortSpacer
|
||||||
|
import com.readrops.app.compose.util.toDp
|
||||||
import com.readrops.db.entities.Feed
|
import com.readrops.db.entities.Feed
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun FeedItem(feed: Feed) {
|
fun FeedItem(
|
||||||
val context = LocalContext.current
|
feed: Feed,
|
||||||
|
onClick: () -> Unit,
|
||||||
Column(
|
onLongClick: () -> Unit,
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.combinedClickable(
|
||||||
|
onClick = onClick,
|
||||||
|
onLongClick = onLongClick
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
) {
|
) {
|
||||||
/*CoilImage(imageRequest = {
|
AsyncImage(
|
||||||
ImageRequest.Builder(context)
|
model = feed.iconUrl,
|
||||||
.data(feed.url)
|
contentDescription = feed.name!!,
|
||||||
.build()
|
modifier = Modifier.size(MaterialTheme.typography.bodyLarge.toDp())
|
||||||
})*/
|
)
|
||||||
|
|
||||||
|
ShortSpacer()
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = feed.name!!,
|
text = feed.name!!,
|
||||||
style = MaterialTheme.typography.headlineSmall
|
style = MaterialTheme.typography.bodyLarge
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,9 +7,11 @@ import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Add
|
import androidx.compose.material.icons.filled.Add
|
||||||
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
|
@ -20,10 +22,14 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
|
import androidx.compose.ui.platform.LocalUriHandler
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import cafe.adriel.voyager.navigator.tab.Tab
|
import cafe.adriel.voyager.navigator.tab.Tab
|
||||||
import cafe.adriel.voyager.navigator.tab.TabOptions
|
import cafe.adriel.voyager.navigator.tab.TabOptions
|
||||||
|
import com.readrops.db.entities.Feed
|
||||||
import org.koin.androidx.compose.getViewModel
|
import org.koin.androidx.compose.getViewModel
|
||||||
|
|
||||||
object FeedTab : Tab {
|
object FeedTab : Tab {
|
||||||
|
@ -38,10 +44,25 @@ object FeedTab : Tab {
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
|
val uriHandler = LocalUriHandler.current
|
||||||
val viewModel = getViewModel<FeedViewModel>()
|
val viewModel = getViewModel<FeedViewModel>()
|
||||||
var showDialog by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
val state by viewModel.feedsState.collectAsStateWithLifecycle()
|
val state by viewModel.feedsState.collectAsStateWithLifecycle()
|
||||||
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
var selectedFeed by remember { mutableStateOf<Feed?>(null) }
|
||||||
|
var showBottomSheet by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
if (showBottomSheet) {
|
||||||
|
FeedModalBottomSheet(
|
||||||
|
feed = selectedFeed!!,
|
||||||
|
onDismissRequest = { showBottomSheet = false },
|
||||||
|
onOpen = { uriHandler.openUri(selectedFeed!!.siteUrl!!) },
|
||||||
|
onModify = { },
|
||||||
|
onDelete = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (showDialog) {
|
if (showDialog) {
|
||||||
AddFeedDialog(
|
AddFeedDialog(
|
||||||
|
@ -55,8 +76,22 @@ object FeedTab : Tab {
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(title = { Text(text = "Feeds") })
|
TopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(text = "Feeds")
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
IconButton(
|
||||||
|
onClick = {}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.MoreVert,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -74,6 +109,14 @@ object FeedTab : Tab {
|
||||||
) { feed ->
|
) { feed ->
|
||||||
FeedItem(
|
FeedItem(
|
||||||
feed = feed,
|
feed = feed,
|
||||||
|
onClick = {
|
||||||
|
selectedFeed = feed
|
||||||
|
showBottomSheet = true
|
||||||
|
},
|
||||||
|
onLongClick = {
|
||||||
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
|
uriHandler.openUri(feed.siteUrl!!)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#727272"
|
||||||
|
android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h4v-2L5,18L5,8h14v10h-4v2h4c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.89,-2 -2,-2zM12,10l-4,4h3v6h2v-6h3l-4,-4z" />
|
||||||
|
</vector>
|
Loading…
Reference in New Issue