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
|
||||
|
||||
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.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
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
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun FeedItem(feed: Feed) {
|
||||
val context = LocalContext.current
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp)
|
||||
) {
|
||||
/*CoilImage(imageRequest = {
|
||||
ImageRequest.Builder(context)
|
||||
.data(feed.url)
|
||||
.build()
|
||||
})*/
|
||||
|
||||
Text(
|
||||
text = feed.name!!,
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
fun FeedItem(
|
||||
feed: Feed,
|
||||
onClick: () -> Unit,
|
||||
onLongClick: () -> Unit,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.combinedClickable(
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick
|
||||
)
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp)
|
||||
) {
|
||||
AsyncImage(
|
||||
model = feed.iconUrl,
|
||||
contentDescription = feed.name!!,
|
||||
modifier = Modifier.size(MaterialTheme.typography.bodyLarge.toDp())
|
||||
)
|
||||
|
||||
ShortSpacer()
|
||||
|
||||
Text(
|
||||
text = feed.name!!,
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
|
@ -20,10 +22,14 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
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.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import cafe.adriel.voyager.navigator.tab.Tab
|
||||
import cafe.adriel.voyager.navigator.tab.TabOptions
|
||||
import com.readrops.db.entities.Feed
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
object FeedTab : Tab {
|
||||
|
@ -31,37 +37,66 @@ object FeedTab : Tab {
|
|||
override val options: TabOptions
|
||||
@Composable
|
||||
get() = TabOptions(
|
||||
index = 2u,
|
||||
title = "Feeds"
|
||||
index = 2u,
|
||||
title = "Feeds"
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
override fun Content() {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val viewModel = getViewModel<FeedViewModel>()
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
|
||||
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) {
|
||||
AddFeedDialog(
|
||||
onDismiss = { showDialog = false },
|
||||
onValidate = {
|
||||
showDialog = false
|
||||
viewModel.insertFeed(it)
|
||||
}
|
||||
onDismiss = { showDialog = false },
|
||||
onValidate = {
|
||||
showDialog = false
|
||||
viewModel.insertFeed(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(title = { Text(text = "Feeds") })
|
||||
}
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(text = "Feeds")
|
||||
},
|
||||
actions = {
|
||||
IconButton(
|
||||
onClick = {}
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
) { paddingValues ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
) {
|
||||
when (state) {
|
||||
is FeedsState.LoadedState -> {
|
||||
|
@ -70,10 +105,18 @@ object FeedTab : Tab {
|
|||
if (feeds.isNotEmpty()) {
|
||||
LazyColumn {
|
||||
items(
|
||||
items = feeds
|
||||
items = feeds
|
||||
) { feed ->
|
||||
FeedItem(
|
||||
feed = feed,
|
||||
feed = feed,
|
||||
onClick = {
|
||||
selectedFeed = feed
|
||||
showBottomSheet = true
|
||||
},
|
||||
onLongClick = {
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
uriHandler.openUri(feed.siteUrl!!)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -90,14 +133,14 @@ object FeedTab : Tab {
|
|||
}
|
||||
|
||||
FloatingActionButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomEnd)
|
||||
.padding(16.dp),
|
||||
onClick = { showDialog = true }
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomEnd)
|
||||
.padding(16.dp),
|
||||
onClick = { showDialog = true }
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Add,
|
||||
contentDescription = null
|
||||
imageVector = Icons.Default.Add,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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