Add sticky headers to saved posts

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2021-02-27 17:33:42 +05:30
parent 1733b3124d
commit 639f814ef8
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
4 changed files with 87 additions and 9 deletions

View file

@ -0,0 +1,40 @@
package dev.msfjarvis.lobsters.ui.posts
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import dev.msfjarvis.lobsters.ui.theme.LobstersTheme
import dev.msfjarvis.lobsters.ui.theme.titleColor
import java.time.Month
import java.util.Locale
import java.time.format.TextStyle as JTextStyle
@Composable
fun MonthHeader(month: Month) {
Box(
Modifier
.fillMaxWidth()
.wrapContentHeight()
) {
Text(
text = month.getDisplayName(JTextStyle.FULL, Locale.getDefault()),
style = MaterialTheme.typography.h4.copy(color = titleColor),
modifier = Modifier.padding(horizontal = 12.dp),
)
}
}
@Preview
@Composable
fun MonthHeaderPreview() {
LobstersTheme {
MonthHeader(month = Month.JULY)
}
}

View file

@ -1,5 +1,6 @@
package dev.msfjarvis.lobsters.ui.posts package dev.msfjarvis.lobsters.ui.posts
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
@ -7,7 +8,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import dev.msfjarvis.lobsters.data.local.LobstersPost import dev.msfjarvis.lobsters.data.local.LobstersPost
import dev.msfjarvis.lobsters.ui.urllauncher.LocalUrlLauncher import dev.msfjarvis.lobsters.ui.urllauncher.LocalUrlLauncher
import dev.msfjarvis.lobsters.util.asZonedDateTime
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun SavedPosts( fun SavedPosts(
posts: List<LobstersPost>, posts: List<LobstersPost>,
@ -22,16 +25,22 @@ fun SavedPosts(
} else { } else {
LazyColumn( LazyColumn(
state = listState, state = listState,
modifier = Modifier.then(modifier) modifier = Modifier.then(modifier),
) { ) {
items(posts) { item -> val grouped = posts.groupBy { it.created_at.asZonedDateTime().month }
LobstersItem( grouped.forEach { (month, posts) ->
post = item, stickyHeader {
isSaved = true, MonthHeader(month = month)
onClick = { urlLauncher.launch(item.url.ifEmpty { item.comments_url }) }, }
onLongClick = { urlLauncher.launch(item.comments_url) }, items(posts) { item ->
onSaveButtonClick = { saveAction.invoke(item) }, LobstersItem(
) post = item,
isSaved = true,
onClick = { urlLauncher.launch(item.url.ifEmpty { item.comments_url }) },
onLongClick = { urlLauncher.launch(item.comments_url) },
onSaveButtonClick = { saveAction.invoke(item) },
)
}
} }
} }
} }

View file

@ -0,0 +1,16 @@
package dev.msfjarvis.lobsters.util
import java.text.SimpleDateFormat
import java.time.ZoneId
import java.time.ZonedDateTime
import java.util.Locale
/**
* Parses a given [String] into a [ZonedDateTime]. This method only works on dates in the format
* returned by the Lobsters API, and is not a general purpose parsing solution.
*/
fun String.asZonedDateTime(): ZonedDateTime {
val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US)
val date = checkNotNull(sdf.parse(this))
return date.toInstant().atZone(ZoneId.systemDefault())
}

View file

@ -0,0 +1,13 @@
package dev.msfjarvis.lobsters.util
import java.time.Month
import org.junit.Assert.*
import org.junit.Test
class DateExtensionsTest {
@Test
fun `parses date correctly`() {
val datetime = "2021-02-15T21:16:02.000-06:00".asZonedDateTime()
assertEquals(Month.FEBRUARY, datetime.month)
}
}