Skip to content

Commit

Permalink
Comment Feature Updates (#72)
Browse files Browse the repository at this point in the history
Just making the comment screen more feature complete:
- Rendering post content if it has any
- Initial loading state
- Relative timestamps
  • Loading branch information
Rahkeen authored Jul 12, 2024
1 parent 43358df commit 4cf3fa8
Show file tree
Hide file tree
Showing 4 changed files with 287 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ private const val BASE_SEARCH_URL = "https://hn.algolia.com/api/v1/"
@Serializable
data class ItemResponse(
val id: Long,
val children: List<ItemResponse>,
@SerialName("created_at")
val createdAt: String,
val children: List<ItemResponse>,
val title: String? = null,
val author: String? = null,
val text: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ class ItemRepository(
}
}

suspend fun getItem(id: ItemId): Item {
return withContext(Dispatchers.IO) {
baseClient.api.getItem(id)
}
}

suspend fun getPage(page: Page): List<Item> {
return withContext(Dispatchers.IO) {
val result = mutableListOf<Item>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,72 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.emergetools.hackernews.data.HackerNewsSearchClient
import com.emergetools.hackernews.data.ItemResponse
import com.emergetools.hackernews.data.relativeTimeStamp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.time.OffsetDateTime

data class CommentsState(
val title: String,
val author: String,
val points: Int,
sealed interface CommentsState {
val headerState: HeaderState
val comments: List<CommentState>
) {
companion object {
val empty = CommentsState(
title = "",
author = "",
points = 0,
comments = emptyList()

data object Loading: CommentsState {
override val headerState: HeaderState = HeaderState.Loading
override val comments: List<CommentState> = listOf(
CommentState.Loading(level = 0),
CommentState.Loading(level = 0),
)
}

val headerState = HeaderState(title, author, points)
data class Content(
val title: String,
val author: String,
val points: Int,
val text: String?,
override val comments: List<CommentState>,
): CommentsState {
override val headerState = HeaderState.Content(title, author, points, text)
}
}

sealed interface CommentState {
val level: Int
val children: List<CommentState>

data class Loading(override val level: Int) : CommentState {
override val children: List<CommentState> = emptyList()
}

data class Content(
val id: Long,
val author: String,
val content: String,
val timeLabel: String,
override val children: List<CommentState>,
override val level: Int = 0,
): CommentState
}

data class CommentState(
val id: Long,
val author: String,
val content: String,
val children: List<CommentState>,
val level: Int = 0,
)
sealed interface HeaderState {
data object Loading: HeaderState
data class Content(
val title: String,
val author: String,
val points: Int,
val body: String?
): HeaderState
}

data class HeaderState(
val title: String,
val author: String,
val points: Int
)

class CommentsViewModel(
private val itemId: Long,
private val searchClient: HackerNewsSearchClient
) : ViewModel() {
private val internalState = MutableStateFlow(CommentsState.empty)
private val internalState = MutableStateFlow<CommentsState>(CommentsState.Loading)
val state = internalState.asStateFlow()

init {
Expand All @@ -60,10 +82,11 @@ class CommentsViewModel(
rootComment.createCommentState(0)
}
internalState.update {
CommentsState(
CommentsState.Content(
title = response.title ?: "",
author = response.author ?: "",
points = response.points ?: 0,
text = response.text,
comments = comments
)
}
Expand All @@ -74,13 +97,16 @@ class CommentsViewModel(
private fun ItemResponse.createCommentState(level: Int): CommentState {
Log.d("Creating CommentState()", "Level: $level, Id: $id")

return CommentState(
return CommentState.Content(
id = id,
author = author ?: "",
content = text ?: "",
children = children.map { child ->
child.createCommentState(level + 1)
},
timeLabel = relativeTimeStamp(
epochSeconds = OffsetDateTime.parse(createdAt).toInstant().epochSecond
),
level = level
)
}
Expand Down
Loading

0 comments on commit 4cf3fa8

Please sign in to comment.