mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-17 22:37:03 +05:30
Merge #121
121: Add sticky headers to saved posts list r=msfjarvis a=msfjarvis  Co-authored-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
commit
5971163361
4 changed files with 87 additions and 9 deletions
40
app/src/main/java/dev/msfjarvis/lobsters/ui/posts/Header.kt
Normal file
40
app/src/main/java/dev/msfjarvis/lobsters/ui/posts/Header.kt
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue