Merge pull request #258 from msfjarvis/comments-screen

This commit is contained in:
Harsh Shandilya 2021-10-06 12:18:46 +05:30 committed by GitHub
commit aa1bd18411
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 318 additions and 87 deletions

View file

@ -20,7 +20,10 @@ dependencies {
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
implementation(libs.androidx.coreKtx) implementation(libs.androidx.coreKtx)
implementation(libs.androidx.lifecycle.compose) implementation(libs.androidx.lifecycle.compose)
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.paging.compose) implementation(libs.androidx.paging.compose)
implementation(libs.multiplatform.markdown.android)
implementation(libs.copydown)
implementation(libs.dagger.hilt.android) implementation(libs.dagger.hilt.android)
implementation(libs.sqldelight.extensions.coroutines) implementation(libs.sqldelight.extensions.coroutines)
implementation(libs.kotlinx.serialization.json) implementation(libs.kotlinx.serialization.json)

View file

@ -1,18 +0,0 @@
package dev.msfjarvis.claw.android.ext
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPost
/** Convert a [LobstersPost] object returned by the API into a [SavedPost] for persistence. */
fun LobstersPost.toDbModel(): SavedPost {
return SavedPost(
shortId = shortId,
title = title,
url = url,
createdAt = createdAt,
commentsUrl = commentsUrl,
submitterName = submitter.username,
submitterAvatarUrl = submitter.avatarUrl,
tags = tags,
)
}

View file

@ -0,0 +1,50 @@
package dev.msfjarvis.claw.android.ui
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPost
import kotlinx.coroutines.launch
@Composable
fun HottestPosts(
items: LazyPagingItems<LobstersPost>,
listState: LazyListState,
isPostSaved: suspend (SavedPost) -> Boolean,
toggleSave: suspend (SavedPost) -> Unit,
reloadPosts: () -> Unit,
launchUrl: (String) -> Unit,
viewComments: (String) -> Unit,
modifier: Modifier,
) {
val coroutineScope = rememberCoroutineScope()
val isRefreshing = items.loadState.refresh == LoadState.Loading
SwipeRefresh(
state = rememberSwipeRefreshState(isRefreshing),
onRefresh = reloadPosts,
) {
if (items.itemCount == 0) {
Box(modifier = Modifier.fillMaxSize())
} else {
NetworkPosts(
items = items,
launchUrl = launchUrl,
listState = listState,
isSaved = isPostSaved,
viewComments = viewComments,
toggleSave = { coroutineScope.launch { toggleSave(it) } },
modifier = Modifier.padding(top = 16.dp).then(modifier),
)
}
}
}

View file

@ -2,9 +2,6 @@ package dev.msfjarvis.claw.android.ui
import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold import androidx.compose.material.Scaffold
@ -15,7 +12,6 @@ import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
@ -23,20 +19,21 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.paging.LoadState import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import com.google.accompanist.insets.ProvideWindowInsets import com.google.accompanist.insets.ProvideWindowInsets
import com.google.accompanist.insets.navigationBarsPadding import com.google.accompanist.insets.navigationBarsPadding
import com.google.accompanist.insets.statusBarsPadding import com.google.accompanist.insets.statusBarsPadding
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.mikepenz.markdown.Markdown
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
import dev.msfjarvis.claw.common.comments.CommentsPage
import dev.msfjarvis.claw.common.theme.LobstersTheme import dev.msfjarvis.claw.common.theme.LobstersTheme
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import kotlinx.coroutines.launch import io.github.furstenheim.CopyDown
private const val ScrollDelta = 50 private const val ScrollDelta = 50
@ -46,10 +43,11 @@ fun LobstersApp(
viewModel: ClawViewModel = viewModel(), viewModel: ClawViewModel = viewModel(),
urlLauncher: UrlLauncher, urlLauncher: UrlLauncher,
) { ) {
val copydown = remember { CopyDown() }
val systemUiController = rememberSystemUiController() val systemUiController = rememberSystemUiController()
val scaffoldState = rememberScaffoldState() val scaffoldState = rememberScaffoldState()
val listState = rememberLazyListState() val listState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope() val navController = rememberNavController()
var isFabVisible by remember { mutableStateOf(true) } var isFabVisible by remember { mutableStateOf(true) }
val nestedScrollConnection = remember { val nestedScrollConnection = remember {
object : NestedScrollConnection { object : NestedScrollConnection {
@ -77,32 +75,40 @@ fun LobstersApp(
systemUiController.setNavigationBarColor(color = Color.Transparent) systemUiController.setNavigationBarColor(color = Color.Transparent)
} }
val items = viewModel.pagerFlow.collectAsLazyPagingItems() val items = viewModel.pagerFlow.collectAsLazyPagingItems()
Scaffold( Scaffold(
scaffoldState = scaffoldState, scaffoldState = scaffoldState,
topBar = { ClawAppBar(modifier = Modifier.statusBarsPadding()) }, topBar = { ClawAppBar(modifier = Modifier.statusBarsPadding()) },
floatingActionButton = { floatingActionButton = {
ClawFab( ClawFab(
isFabVisible = isFabVisible, isFabVisible = isFabVisible && navController.currentDestination?.route == "hottest",
listState = listState, listState = listState,
modifier = Modifier.navigationBarsPadding(), modifier = Modifier.navigationBarsPadding(),
) )
}, },
) { ) { paddingValues ->
val isRefreshing = items.loadState.refresh == LoadState.Loading NavHost(navController, startDestination = "hottest") {
SwipeRefresh( composable("hottest") {
state = rememberSwipeRefreshState(isRefreshing), HottestPosts(
onRefresh = viewModel::reloadPosts, items,
) { listState,
if (items.itemCount == 0) { viewModel::isPostSaved,
Box(modifier = Modifier.fillMaxSize()) viewModel::toggleSave,
} else { viewModel::reloadPosts,
NetworkPosts( urlLauncher::launch,
items = items, { navController.navigate("comments/$it") },
launchUrl = urlLauncher::launch, Modifier.nestedScroll(nestedScrollConnection),
listState = listState, )
isSaved = viewModel::isPostSaved, }
toggleSave = { coroutineScope.launch { viewModel.toggleSave(it) } }, composable("comments/{postId}") { backStackEntry ->
modifier = Modifier.padding(top = 16.dp).nestedScroll(nestedScrollConnection), CommentsPage(
postId = requireNotNull(backStackEntry.arguments?.getString("postId")),
getDetails = viewModel::getPostComments,
renderMarkdown = { source, modifier ->
val markdown = copydown.convert(source)
Markdown(markdown, modifier = modifier)
},
paddingValues = paddingValues,
) )
} }
} }

View file

@ -13,8 +13,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.items import androidx.paging.compose.items
import dev.msfjarvis.claw.android.ext.toDbModel
import dev.msfjarvis.claw.common.posts.LobstersCard import dev.msfjarvis.claw.common.posts.LobstersCard
import dev.msfjarvis.claw.common.posts.toDbModel
import dev.msfjarvis.claw.database.local.SavedPost import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPost import dev.msfjarvis.claw.model.LobstersPost
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -26,6 +26,7 @@ fun NetworkPosts(
launchUrl: (String) -> Unit, launchUrl: (String) -> Unit,
isSaved: suspend (SavedPost) -> Boolean, isSaved: suspend (SavedPost) -> Boolean,
toggleSave: (SavedPost) -> Unit, toggleSave: (SavedPost) -> Unit,
viewComments: (String) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
@ -42,7 +43,7 @@ fun NetworkPosts(
post = dbModel, post = dbModel,
isSaved = saved, isSaved = saved,
viewPost = { launchUrl(item.url.ifEmpty { item.commentsUrl }) }, viewPost = { launchUrl(item.url.ifEmpty { item.commentsUrl }) },
viewComments = { launchUrl(item.commentsUrl) }, viewComments = { viewComments(item.shortId) },
toggleSave = { toggleSave(dbModel) }, toggleSave = { toggleSave(dbModel) },
modifier = Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp), modifier = Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp),
) )

View file

@ -7,19 +7,22 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import dev.msfjarvis.claw.android.paging.LobstersPagingSource import dev.msfjarvis.claw.android.paging.LobstersPagingSource
import dev.msfjarvis.claw.api.LobstersApi import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.database.local.SavedPost import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPostDetails
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.last import kotlinx.coroutines.flow.last
import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.withContext
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
@HiltViewModel @HiltViewModel
class ClawViewModel class ClawViewModel
@Inject @Inject
constructor( constructor(
api: LobstersApi, private val api: LobstersApi,
private val repository: SavedPostsRepository, private val repository: SavedPostsRepository,
) : ViewModel() { ) : ViewModel() {
var lastPagingSource: LobstersPagingSource? = null var lastPagingSource: LobstersPagingSource? = null
@ -46,6 +49,11 @@ constructor(
} }
} }
suspend fun getPostComments(postId: String): LobstersPostDetails =
withContext(Dispatchers.IO) {
return@withContext api.getPostDetails(postId)
}
fun reloadPosts() { fun reloadPosts() {
lastPagingSource?.invalidate() lastPagingSource?.invalidate()
} }

View file

@ -15,7 +15,7 @@ buildscript {
classpath("com.android.tools:r8:3.1.17-dev") classpath("com.android.tools:r8:3.1.17-dev")
classpath(kotlin("gradle-plugin", version = kotlinVersion)) classpath(kotlin("gradle-plugin", version = kotlinVersion))
classpath(kotlin("serialization", version = kotlinVersion)) classpath(kotlin("serialization", version = kotlinVersion))
classpath("com.android.tools.build:gradle:7.1.0-alpha12") classpath("com.android.tools.build:gradle:7.1.0-alpha13")
classpath("com.diffplug.spotless:spotless-plugin-gradle:5.15.0") classpath("com.diffplug.spotless:spotless-plugin-gradle:5.15.0")
classpath("com.google.dagger:hilt-android-gradle-plugin:2.39") classpath("com.google.dagger:hilt-android-gradle-plugin:2.39")
} }

View file

@ -16,6 +16,7 @@ kotlin {
api(compose.foundation) api(compose.foundation)
api(compose.material) api(compose.material)
api(projects.database) api(projects.database)
api(projects.model)
} }
} }
sourceSets["androidMain"].apply { sourceSets["androidMain"].apply {

View file

@ -0,0 +1,7 @@
package dev.msfjarvis.lobsters.ui.comments
sealed class NetworkState {
class Success<T>(val data: T) : NetworkState()
class Error(val message: String) : NetworkState()
object Loading : NetworkState()
}

View file

@ -0,0 +1,79 @@
package dev.msfjarvis.claw.common.comments
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.Divider
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import dev.msfjarvis.claw.common.posts.PostDetails
import dev.msfjarvis.claw.common.posts.SubmitterName
import dev.msfjarvis.claw.common.posts.toDbModel
import dev.msfjarvis.claw.model.Comment
import dev.msfjarvis.claw.model.LobstersPostDetails
@Composable
fun CommentsHeader(
postDetails: LobstersPostDetails,
) {
Surface {
Column(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
PostDetails(
post = postDetails.toDbModel(),
)
}
}
}
@Composable
fun CommentEntry(
comment: Comment,
renderMarkdown: @Composable (comment: String, modifier: Modifier) -> Unit,
) {
val indentLevel = comment.indentLevel.toInt() - 1
Divider(color = Color.Gray.copy(0.4f))
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
CommentTreeColors(indentLevel = indentLevel)
Column(modifier = Modifier.padding(start = 12.dp, end = 8.dp, top = 4.dp, bottom = 4.dp)) {
SubmitterName(
text = "Submitted by ${comment.user.username}",
avatarUrl = "https://lobste.rs/${comment.user.avatarUrl}",
contentDescription = "Submitted by ${comment.user.username}",
)
renderMarkdown(comment.comment, Modifier.padding(top = 8.dp))
}
}
}
@Composable
private fun CommentTreeColors(
indentLevel: Int,
modifier: Modifier = Modifier,
) {
Box(modifier = modifier) {
for (level in 1..indentLevel) {
Box(
modifier =
Modifier.padding(start = (12 + ((level - 1) * 10)).dp)
.fillMaxHeight()
.width(1.dp)
.background(CommentTreeColor[level])
)
}
}
}

View file

@ -24,7 +24,7 @@ object CommentTreeColor {
Color(0xFFFF0097), Color(0xFFFF0097),
Color(0xFF1E7145), Color(0xFF1E7145),
) )
private val size = colors.size val size = colors.size
operator fun get(idx: Int): Color = colors[idx % size] operator fun get(idx: Int): Color = colors[idx % size]
} }

View file

@ -0,0 +1,76 @@
package dev.msfjarvis.claw.common.comments
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.lobsters.ui.comments.NetworkState
@Composable
private fun CommentsPageInternal(
details: LobstersPostDetails,
renderMarkdown: @Composable (comment: String, modifier: Modifier) -> Unit,
bottomPadding: Dp,
) {
LazyColumn(Modifier.padding(bottom = bottomPadding)) {
item { CommentsHeader(postDetails = details) }
item { Spacer(modifier = Modifier.height(8.dp)) }
items(details.comments) { item -> CommentEntry(item, renderMarkdown) }
item { Divider(color = Color.Gray.copy(0.4f)) }
}
}
@Suppress("UNCHECKED_CAST")
@Composable
fun CommentsPage(
postId: String,
getDetails: suspend (String) -> LobstersPostDetails,
renderMarkdown: @Composable (comment: String, modifier: Modifier) -> Unit,
paddingValues: PaddingValues,
) {
var postDetails: NetworkState by remember { mutableStateOf(NetworkState.Loading) }
LaunchedEffect(postId) { postDetails = NetworkState.Success(getDetails(postId)) }
when (postDetails) {
is NetworkState.Success<*> -> {
CommentsPageInternal(
(postDetails as NetworkState.Success<LobstersPostDetails>).data,
renderMarkdown,
paddingValues.calculateBottomPadding(),
)
}
is NetworkState.Error -> TODO("Handle no network scenario")
NetworkState.Loading -> ProgressBar(paddingValues.calculateBottomPadding())
}
}
@Composable
private fun ProgressBar(bottomPadding: Dp) {
Box(
modifier = Modifier.padding(bottom = bottomPadding).fillMaxSize(),
contentAlignment = Alignment.Center
) { CircularProgressIndicator(color = MaterialTheme.colors.secondary) }
}

View file

@ -37,18 +37,6 @@ import dev.msfjarvis.claw.common.theme.titleColor
import dev.msfjarvis.claw.common.ui.NetworkImage import dev.msfjarvis.claw.common.ui.NetworkImage
import dev.msfjarvis.claw.database.local.SavedPost import dev.msfjarvis.claw.database.local.SavedPost
val TEST_POST =
SavedPost(
shortId = "zqyydb",
title = "k2k20 hackathon report: Bob Beck on LibreSSL progress",
url = "https://undeadly.org/cgi?action=article;sid=20200921105847",
createdAt = "2020-09-21T07:11:14.000-05:00",
commentsUrl = "https://lobste.rs/s/zqyydb/k2k20_hackathon_report_bob_beck_on",
submitterName = "Vigdis",
submitterAvatarUrl = "https://avatars.githubusercontent.com/u/13348378?v=4",
tags = listOf("openbsd", "linux", "containers", "hack the planet", "no thanks"),
)
@Composable @Composable
@OptIn(ExperimentalMaterialApi::class) @OptIn(ExperimentalMaterialApi::class)
fun LobstersCard( fun LobstersCard(
@ -67,16 +55,8 @@ fun LobstersCard(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp).fillMaxWidth(), modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(4.dp), verticalArrangement = Arrangement.spacedBy(4.dp),
) { ) {
PostTitle( PostDetails(
title = post.title, post = post,
)
TagRow(
tags = post.tags,
)
SubmitterName(
text = "Submitted by ${post.submitterName}",
avatarUrl = "https://lobste.rs/${post.submitterAvatarUrl}",
contentDescription = "Submitted by ${post.submitterName}",
) )
Row( Row(
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
@ -98,6 +78,23 @@ fun LobstersCard(
} }
} }
@Composable
fun PostDetails(
post: SavedPost,
) {
PostTitle(
title = post.title,
)
TagRow(
tags = post.tags,
)
SubmitterName(
text = "Submitted by ${post.submitterName}",
avatarUrl = "https://lobste.rs/${post.submitterAvatarUrl}",
contentDescription = "Submitted by ${post.submitterName}",
)
}
@Composable @Composable
fun PostTitle( fun PostTitle(
title: String, title: String,

View file

@ -0,0 +1,31 @@
package dev.msfjarvis.claw.common.posts
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.LobstersPostDetails
fun LobstersPost.toDbModel(): SavedPost {
return SavedPost(
shortId = shortId,
title = title,
url = url,
createdAt = createdAt,
commentsUrl = commentsUrl,
submitterName = submitter.username,
submitterAvatarUrl = submitter.avatarUrl,
tags = tags,
)
}
fun LobstersPostDetails.toDbModel(): SavedPost {
return SavedPost(
shortId = shortId,
title = title,
url = url,
createdAt = createdAt,
commentsUrl = commentsUrl,
submitterName = submitter.username,
submitterAvatarUrl = submitter.avatarUrl,
tags = tags,
)
}

View file

@ -14,27 +14,13 @@ import androidx.compose.ui.window.WindowPosition
import androidx.compose.ui.window.application import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState import androidx.compose.ui.window.rememberWindowState
import dev.msfjarvis.claw.common.posts.LobstersCard import dev.msfjarvis.claw.common.posts.LobstersCard
import dev.msfjarvis.claw.common.posts.toDbModel
import dev.msfjarvis.claw.common.theme.LobstersTheme import dev.msfjarvis.claw.common.theme.LobstersTheme
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPost
import org.pushingpixels.aurora.component.AuroraVerticalScrollbar import org.pushingpixels.aurora.component.AuroraVerticalScrollbar
import org.pushingpixels.aurora.skin.ceruleanSkin import org.pushingpixels.aurora.skin.ceruleanSkin
import org.pushingpixels.aurora.window.AuroraWindow import org.pushingpixels.aurora.window.AuroraWindow
fun LobstersPost.toDbModel(): SavedPost {
return SavedPost(
shortId = shortId,
title = title,
url = url,
createdAt = createdAt,
commentsUrl = commentsUrl,
submitterName = submitter.username,
submitterAvatarUrl = submitter.avatarUrl,
tags = tags,
)
}
fun main() = application { fun main() = application {
val paging = Paging(rememberCoroutineScope()) val paging = Paging(rememberCoroutineScope())
val items = paging.pagingData.collectAsLazyPagingItems() val items = paging.pagingData.collectAsLazyPagingItems()

View file

@ -23,6 +23,7 @@ androidx-appcompat = "androidx.appcompat:appcompat:1.4.0-beta01"
androidx-browser = "androidx.browser:browser:1.4.0-beta01" androidx-browser = "androidx.browser:browser:1.4.0-beta01"
androidx-coreKtx = "androidx.core:core-ktx:1.7.0-beta02" androidx-coreKtx = "androidx.core:core-ktx:1.7.0-beta02"
androidx-lifecycle-compose = "androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0-rc01" androidx-lifecycle-compose = "androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0-rc01"
androidx-navigation-compose = "androidx.navigation:navigation-compose:2.4.0-alpha10"
androidx-paging-compose = "androidx.paging:paging-compose:1.0.0-alpha13" androidx-paging-compose = "androidx.paging:paging-compose:1.0.0-alpha13"
aurora-component = { module = "org.pushing-pixels:aurora-component", version.ref = "aurora" } aurora-component = { module = "org.pushing-pixels:aurora-component", version.ref = "aurora" }
@ -36,6 +37,9 @@ dagger-hilt-android = { module = "com.google.dagger:hilt-android", version.ref =
dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" } dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" }
dagger-hilt-core = { module = "com.google.dagger:hilt-core", version.ref = "hilt" } dagger-hilt-core = { module = "com.google.dagger:hilt-core", version.ref = "hilt" }
multiplatform-markdown-android = "com.mikepenz:multiplatform-markdown-renderer-android:0.0.1"
copydown = "io.github.furstenheim:copy_down:1.0"
multiplatform-paging = "dev.msfjarvis.paging:multiplatform-paging:0.4.5-SNAPSHOT" multiplatform-paging = "dev.msfjarvis.paging:multiplatform-paging:0.4.5-SNAPSHOT"
retrofit-lib = "com.squareup.retrofit2:retrofit:2.9.0" retrofit-lib = "com.squareup.retrofit2:retrofit:2.9.0"