mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 14:07:05 +05:30
feat: load link metadata lazily
This commit is contained in:
parent
4337a19abc
commit
79aba9a187
7 changed files with 50 additions and 61 deletions
|
@ -206,6 +206,7 @@ fun LobstersApp(
|
||||||
CommentsPage(
|
CommentsPage(
|
||||||
postId = postId,
|
postId = postId,
|
||||||
getDetails = viewModel::getPostComments,
|
getDetails = viewModel::getPostComments,
|
||||||
|
getLinkMetadata = viewModel::getLinkMetadata,
|
||||||
postActions = postActions,
|
postActions = postActions,
|
||||||
htmlConverter = htmlConverter,
|
htmlConverter = htmlConverter,
|
||||||
)
|
)
|
||||||
|
|
|
@ -27,7 +27,7 @@ class ClawViewModel
|
||||||
constructor(
|
constructor(
|
||||||
private val api: LobstersApi,
|
private val api: LobstersApi,
|
||||||
private val savedPostsRepository: SavedPostsRepository,
|
private val savedPostsRepository: SavedPostsRepository,
|
||||||
private val postDetailsRepository: PostDetailsRepository,
|
private val linkMetadataRepository: LinkMetadataRepository,
|
||||||
private val pagingSourceFactory: LobstersPagingSource.Factory,
|
private val pagingSourceFactory: LobstersPagingSource.Factory,
|
||||||
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
|
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
@ -76,18 +76,18 @@ constructor(
|
||||||
|
|
||||||
suspend fun getPostComments(postId: String) =
|
suspend fun getPostComments(postId: String) =
|
||||||
withContext(ioDispatcher) {
|
withContext(ioDispatcher) {
|
||||||
val details =
|
when (val result = api.getPostDetails(postId)) {
|
||||||
when (val result = api.getPostDetails(postId)) {
|
is Success -> result.value
|
||||||
is Success -> result.value
|
is Failure.NetworkFailure -> throw result.error
|
||||||
is Failure.NetworkFailure -> throw result.error
|
is Failure.UnknownFailure -> throw result.error
|
||||||
is Failure.UnknownFailure -> throw result.error
|
is Failure.HttpFailure,
|
||||||
is Failure.HttpFailure,
|
is Failure.ApiFailure -> throw IOException("API returned an invalid response")
|
||||||
is Failure.ApiFailure -> throw IOException("API returned an invalid response")
|
}
|
||||||
}
|
|
||||||
val extendedDetails = postDetailsRepository.getExtendedDetails(details)
|
|
||||||
extendedDetails
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getLinkMetadata(url: String) =
|
||||||
|
withContext(ioDispatcher) { linkMetadataRepository.getLinkMetadata(url) }
|
||||||
|
|
||||||
suspend fun getUserProfile(username: String) =
|
suspend fun getUserProfile(username: String) =
|
||||||
withContext(ioDispatcher) {
|
withContext(ioDispatcher) {
|
||||||
when (val result = api.getUser(username)) {
|
when (val result = api.getUser(username)) {
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package dev.msfjarvis.claw.android.viewmodel
|
||||||
|
|
||||||
|
import dev.msfjarvis.claw.metadata.MetadataExtractor
|
||||||
|
import dev.msfjarvis.claw.model.LinkMetadata
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class LinkMetadataRepository
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
private val metadataExtractor: MetadataExtractor,
|
||||||
|
) {
|
||||||
|
suspend fun getLinkMetadata(url: String): LinkMetadata {
|
||||||
|
return metadataExtractor.getExtractedMetadata(url)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
package dev.msfjarvis.claw.android.viewmodel
|
|
||||||
|
|
||||||
import dev.msfjarvis.claw.metadata.MetadataExtractor
|
|
||||||
import dev.msfjarvis.claw.model.ExtendedPostDetails
|
|
||||||
import dev.msfjarvis.claw.model.LobstersPostDetails
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class PostDetailsRepository
|
|
||||||
@Inject
|
|
||||||
constructor(
|
|
||||||
private val metadataExtractor: MetadataExtractor,
|
|
||||||
) {
|
|
||||||
suspend fun getExtendedDetails(details: LobstersPostDetails): ExtendedPostDetails {
|
|
||||||
val metadata = metadataExtractor.getExtractedMetadata(details.url)
|
|
||||||
return ExtendedPostDetails(
|
|
||||||
title = details.title,
|
|
||||||
linkMetadata = metadata,
|
|
||||||
description = details.description,
|
|
||||||
submitter = details.submitter,
|
|
||||||
tags = details.tags,
|
|
||||||
comments = details.comments,
|
|
||||||
commentsUrl = details.commentsUrl,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,6 +23,7 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
@ -40,19 +41,26 @@ import dev.msfjarvis.claw.common.res.ClawIcons
|
||||||
import dev.msfjarvis.claw.common.ui.NetworkImage
|
import dev.msfjarvis.claw.common.ui.NetworkImage
|
||||||
import dev.msfjarvis.claw.common.ui.ThemedRichText
|
import dev.msfjarvis.claw.common.ui.ThemedRichText
|
||||||
import dev.msfjarvis.claw.model.Comment
|
import dev.msfjarvis.claw.model.Comment
|
||||||
import dev.msfjarvis.claw.model.ExtendedPostDetails
|
|
||||||
import dev.msfjarvis.claw.model.LinkMetadata
|
import dev.msfjarvis.claw.model.LinkMetadata
|
||||||
|
import dev.msfjarvis.claw.model.LobstersPostDetails
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.temporal.TemporalAccessor
|
import java.time.temporal.TemporalAccessor
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentsHeader(
|
fun CommentsHeader(
|
||||||
postDetails: ExtendedPostDetails,
|
postDetails: LobstersPostDetails,
|
||||||
|
getLinkMetadata: suspend (String) -> LinkMetadata,
|
||||||
postActions: PostActions,
|
postActions: PostActions,
|
||||||
htmlConverter: HTMLConverter,
|
htmlConverter: HTMLConverter,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val uriHandler = LocalUriHandler.current
|
val uriHandler = LocalUriHandler.current
|
||||||
|
val linkMetadata by
|
||||||
|
produceState(
|
||||||
|
initialValue = LinkMetadata(postDetails.url, null, null),
|
||||||
|
) {
|
||||||
|
value = getLinkMetadata(postDetails.url)
|
||||||
|
}
|
||||||
|
|
||||||
Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) {
|
Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) {
|
||||||
Column(
|
Column(
|
||||||
|
@ -63,13 +71,11 @@ fun CommentsHeader(
|
||||||
TagRow(tags = postDetails.tags)
|
TagRow(tags = postDetails.tags)
|
||||||
Spacer(Modifier.height(4.dp))
|
Spacer(Modifier.height(4.dp))
|
||||||
|
|
||||||
if (postDetails.linkMetadata.url.isNotBlank()) {
|
if (linkMetadata.url.isNotBlank()) {
|
||||||
PostLink(
|
PostLink(
|
||||||
linkMetadata = postDetails.linkMetadata,
|
linkMetadata = linkMetadata,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier.clickable {
|
Modifier.clickable { postActions.viewPost(linkMetadata.url, postDetails.commentsUrl) },
|
||||||
postActions.viewPost(postDetails.linkMetadata.url, postDetails.commentsUrl)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(4.dp))
|
Spacer(Modifier.height(4.dp))
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,13 @@ import dev.msfjarvis.claw.common.NetworkState.Success
|
||||||
import dev.msfjarvis.claw.common.posts.PostActions
|
import dev.msfjarvis.claw.common.posts.PostActions
|
||||||
import dev.msfjarvis.claw.common.ui.NetworkError
|
import dev.msfjarvis.claw.common.ui.NetworkError
|
||||||
import dev.msfjarvis.claw.common.ui.ProgressBar
|
import dev.msfjarvis.claw.common.ui.ProgressBar
|
||||||
import dev.msfjarvis.claw.model.ExtendedPostDetails
|
import dev.msfjarvis.claw.model.LinkMetadata
|
||||||
|
import dev.msfjarvis.claw.model.LobstersPostDetails
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun CommentsPageInternal(
|
private fun CommentsPageInternal(
|
||||||
details: ExtendedPostDetails,
|
details: LobstersPostDetails,
|
||||||
|
getLinkMetadata: suspend (String) -> LinkMetadata,
|
||||||
postActions: PostActions,
|
postActions: PostActions,
|
||||||
htmlConverter: HTMLConverter,
|
htmlConverter: HTMLConverter,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
@ -38,6 +40,7 @@ private fun CommentsPageInternal(
|
||||||
item {
|
item {
|
||||||
CommentsHeader(
|
CommentsHeader(
|
||||||
postDetails = details,
|
postDetails = details,
|
||||||
|
getLinkMetadata = getLinkMetadata,
|
||||||
postActions = postActions,
|
postActions = postActions,
|
||||||
htmlConverter = htmlConverter,
|
htmlConverter = htmlConverter,
|
||||||
)
|
)
|
||||||
|
@ -73,11 +76,12 @@ private fun CommentsPageInternal(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST", "LongParameterList")
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentsPage(
|
fun CommentsPage(
|
||||||
postId: String,
|
postId: String,
|
||||||
getDetails: suspend (String) -> ExtendedPostDetails,
|
getDetails: suspend (String) -> LobstersPostDetails,
|
||||||
|
getLinkMetadata: suspend (String) -> LinkMetadata,
|
||||||
postActions: PostActions,
|
postActions: PostActions,
|
||||||
htmlConverter: HTMLConverter,
|
htmlConverter: HTMLConverter,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
@ -94,7 +98,8 @@ fun CommentsPage(
|
||||||
when (postDetails) {
|
when (postDetails) {
|
||||||
is Success<*> -> {
|
is Success<*> -> {
|
||||||
CommentsPageInternal(
|
CommentsPageInternal(
|
||||||
details = (postDetails as Success<ExtendedPostDetails>).data,
|
details = (postDetails as Success<LobstersPostDetails>).data,
|
||||||
|
getLinkMetadata = getLinkMetadata,
|
||||||
postActions = postActions,
|
postActions = postActions,
|
||||||
htmlConverter = htmlConverter,
|
htmlConverter = htmlConverter,
|
||||||
modifier = modifier.fillMaxSize(),
|
modifier = modifier.fillMaxSize(),
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
@file:Suppress("LongParameterList")
|
|
||||||
|
|
||||||
package dev.msfjarvis.claw.model
|
|
||||||
|
|
||||||
class ExtendedPostDetails(
|
|
||||||
val title: String,
|
|
||||||
val linkMetadata: LinkMetadata,
|
|
||||||
val description: String,
|
|
||||||
val submitter: User,
|
|
||||||
val tags: List<String>,
|
|
||||||
val comments: List<Comment>,
|
|
||||||
val commentsUrl: String,
|
|
||||||
)
|
|
Loading…
Add table
Add a link
Reference in a new issue