Skip to content

Commit

Permalink
Feature: add Timeline Grouping List
Browse files Browse the repository at this point in the history
  • Loading branch information
sun5066 committed Jul 27, 2024
1 parent 1c3ab9a commit 5fa52c8
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ interface LinkDao {
suspend fun deleteRemovedAll()

@Transaction
@Query("SELECT * FROM link WHERE isRemove == 0")
@Query("SELECT * FROM link WHERE isRemove == 0 ORDER BY link.createAt DESC")
fun selectPage(): PagingSource<Int, LinkWithTags>

@Query("SELECT * FROM link WHERE pk == :id")
Expand All @@ -51,6 +51,7 @@ interface LinkDao {
)
)
AND isRemove == 0
ORDER BY link.createAt DESC
"""
)
fun selectLinksByTagName(tagName: String): PagingSource<Int, LinkWithTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class TimeLineViewModel @Inject constructor(
}
}

init {
private fun getLinks() {
intent {
val links = savedStateHandle.get<String>(INTENT_KEY_TAG_NAME)
?.let { selectLinkByTagNameUseCase.invoke(it) }
Expand All @@ -58,6 +58,10 @@ class TimeLineViewModel @Inject constructor(
reduce { state.copy(links = links.cachedIn(viewModelScope)) }
}
}

init {
getLinks()
}
}

sealed interface TimeLineAction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.compose.material.Card
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -49,6 +50,7 @@ import com.linky.design_system.ui.component.text.LinkyText
import com.linky.design_system.ui.theme.ColorFamilyGray300AndGray800
import com.linky.design_system.ui.theme.ColorFamilyGray600AndGray400
import com.linky.design_system.ui.theme.ColorFamilyGray800AndGray300
import com.linky.design_system.ui.theme.ColorFamilyGray800AndGray400
import com.linky.design_system.ui.theme.ColorFamilyGray900AndGray100
import com.linky.design_system.ui.theme.ColorFamilyWhiteAndGray900
import com.linky.design_system.ui.theme.ColorFamilyWhiteAndGray999
Expand All @@ -59,6 +61,9 @@ import com.linky.model.Link
import com.skydoves.balloon.compose.Balloon
import com.skydoves.balloon.compose.rememberBalloonBuilder
import com.skydoves.balloon.compose.setBackgroundColor
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId

@Composable
internal fun TimeLineList(
Expand All @@ -72,140 +77,175 @@ internal fun TimeLineList(
onClick: (Link) -> Unit,
onCopyLink: (Link) -> Unit,
) {
val today = remember { LocalDate.now() }
val yesterday = remember { today.minusDays(1) }
val oneWeekAgo = remember { today.minusWeeks(1) }
val oneMonthAgo = remember { today.minusMonths(1) }

val grouping by remember(links) {
derivedStateOf {
links.groupBy { link ->
val date = Instant
.ofEpochMilli(link.createAt)
.atZone(ZoneId.systemDefault())
.toLocalDate()

when {
date.isEqual(today) -> "오늘"
date.isEqual(yesterday) -> "어제"
date.isAfter(oneWeekAgo) -> "최근 일주일"
date.isAfter(oneMonthAgo) -> "최근 한 달"
else -> "오래된 데이터"
}
}
}
}

LazyColumn(
modifier = modifier,
state = state,
contentPadding = PaddingValues(16.dp)
) {
items(
items = links,
key = { it.id ?: 0L },
contentType = { "TimeLineItems" }
) { link ->
Card(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 10.dp)
.clickableRipple(enableRipple = false) { onClick.invoke(link) },
shape = RoundedCornerShape(12.dp),
backgroundColor = ColorFamilyWhiteAndGray999
) {
Column(
grouping.forEach { (groupName, groupItems) ->
item {
LinkyText(
modifier = Modifier.padding(5.dp),
text = groupName,
color = ColorFamilyGray800AndGray400,
fontWeight = FontWeight.Bold,
fontSize = 18.dp
)
}
items(
items = groupItems,
key = { it.id ?: 0L },
contentType = { "TimeLineItems" }
) { link ->
Card(
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp, bottom = 12.dp, start = 12.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
.padding(bottom = 10.dp)
.clickableRipple(enableRipple = false) { onClick.invoke(link) },
shape = RoundedCornerShape(12.dp),
backgroundColor = ColorFamilyWhiteAndGray999
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
LinkyText(
text = link.createAtFormat,
color = ColorFamilyGray800AndGray300,
fontSize = 11.dp,
fontWeight = FontWeight.Medium
)
Spacer(
modifier = Modifier
.padding(horizontal = 4.dp)
.width(1.dp)
.height(8.dp)
.background(ColorFamilyGray600AndGray400)
)
LinkyText(
text = link.readCountFormat,
color = ColorFamilyGray800AndGray300,
fontSize = 11.dp,
fontWeight = FontWeight.Medium
)
}
MenuButton(
onEdit = { onEdit.invoke(link) },
onRemove = { onRemove.invoke(link.id!!) }
)
}
Row(
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
verticalAlignment = Alignment.CenterVertically
.padding(top = 10.dp, bottom = 12.dp, start = 12.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
SubcomposeAsyncImage(
modifier = Modifier
.size(98.dp)
.clip(RoundedCornerShape(4.dp)),
imageLoader = imageLoader,
model = link.openGraphData.image,
contentScale = ContentScale.Crop,
contentDescription = "thumbnail"
)
Column(
modifier = Modifier
.height(98.dp)
.padding(horizontal = 10.dp),
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
if (link.memo.isNotEmpty()) {
LinkyText(
text = link.memo,
color = ColorFamilyGray900AndGray100,
fontSize = 15.dp,
fontWeight = FontWeight.SemiBold,
lineHeight = 20.sp
)
Spacer(modifier = Modifier.padding(bottom = 7.dp))
}
LazyRow(
horizontalArrangement = Arrangement.Start,
Row(
verticalAlignment = Alignment.CenterVertically,
) {
items(link.tags) { tag ->
TimeLineTagChip(
modifier = Modifier.padding(end = 3.dp),
tagName = tag.name,
)
}
LinkyText(
text = link.createAtFormat,
color = ColorFamilyGray800AndGray300,
fontSize = 11.dp,
fontWeight = FontWeight.Medium
)
Spacer(
modifier = Modifier
.padding(horizontal = 4.dp)
.width(1.dp)
.height(8.dp)
.background(ColorFamilyGray600AndGray400)
)
LinkyText(
text = link.readCountFormat,
color = ColorFamilyGray800AndGray300,
fontSize = 11.dp,
fontWeight = FontWeight.Medium
)
}
Spacer(
modifier = Modifier.weight(1f)
MenuButton(
onEdit = { onEdit.invoke(link) },
onRemove = { onRemove.invoke(link.id!!) }
)
// 태그
Spacer(
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
verticalAlignment = Alignment.CenterVertically
) {
SubcomposeAsyncImage(
modifier = Modifier
.fillMaxWidth()
.height(1.dp)
.background(Gray400)
.size(98.dp)
.clip(RoundedCornerShape(4.dp)),
imageLoader = imageLoader,
model = link.openGraphData.image,
contentScale = ContentScale.Crop,
contentDescription = "thumbnail"
)
Row(
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = 6.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
.height(98.dp)
.padding(horizontal = 10.dp),
) {
LinkyText(
text = link.openGraphData.title ?: "",
color = ColorFamilyGray800AndGray300,
fontSize = 12.dp,
fontWeight = FontWeight.SemiBold,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.weight(0.7f),
if (link.memo.isNotEmpty()) {
LinkyText(
text = link.memo,
color = ColorFamilyGray900AndGray100,
fontSize = 15.dp,
fontWeight = FontWeight.SemiBold,
lineHeight = 20.sp
)
Spacer(modifier = Modifier.padding(bottom = 7.dp))
}
LazyRow(
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically,
) {
items(link.tags) { tag ->
TimeLineTagChip(
modifier = Modifier.padding(end = 3.dp),
tagName = tag.name,
)
}
}
Spacer(
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.weight(0.2f))

Image(
painter = painterResource(R.drawable.ico_tag_copy),
contentDescription = "copy",
// 태그
Spacer(
modifier = Modifier
.weight(0.1f)
.clickableRipple(radius = 10.dp) { onCopyLink.invoke(link) },
.fillMaxWidth()
.height(1.dp)
.background(Gray400)
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 6.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
LinkyText(
text = link.openGraphData.title ?: "",
color = ColorFamilyGray800AndGray300,
fontSize = 12.dp,
fontWeight = FontWeight.SemiBold,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.weight(0.7f),
)
Spacer(modifier = Modifier.weight(0.2f))

Image(
painter = painterResource(R.drawable.ico_tag_copy),
contentDescription = "copy",
modifier = Modifier
.weight(0.1f)
.clickableRipple(radius = 10.dp) { onCopyLink.invoke(link) },
)
}
}
}
}
Expand Down

0 comments on commit 5fa52c8

Please sign in to comment.