diff --git a/android/build.gradle.kts b/android/build.gradle.kts index 2526dd68..9ae04a46 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -20,7 +20,10 @@ dependencies { implementation(libs.androidx.appcompat) implementation(libs.androidx.coreKtx) implementation(libs.androidx.lifecycle.compose) + implementation(libs.androidx.navigation.compose) implementation(libs.androidx.paging.compose) + implementation(libs.multiplatform.markdown.android) + implementation(libs.copydown) implementation(libs.dagger.hilt.android) implementation(libs.sqldelight.extensions.coroutines) implementation(libs.kotlinx.serialization.json) diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ext/database.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ext/database.kt deleted file mode 100644 index 9835f896..00000000 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ext/database.kt +++ /dev/null @@ -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, - ) -} diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/HottestPosts.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/HottestPosts.kt new file mode 100644 index 00000000..3cb07f20 --- /dev/null +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/HottestPosts.kt @@ -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, + 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), + ) + } + } +} diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt index 8e9c452f..f4cf8455 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt @@ -2,9 +2,6 @@ package dev.msfjarvis.claw.android.ui import androidx.compose.animation.ExperimentalAnimationApi 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.material.MaterialTheme import androidx.compose.material.Scaffold @@ -15,7 +12,6 @@ import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier 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.NestedScrollSource import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.unit.dp 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 com.google.accompanist.insets.ProvideWindowInsets import com.google.accompanist.insets.navigationBarsPadding 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.mikepenz.markdown.Markdown 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.urllauncher.UrlLauncher -import kotlinx.coroutines.launch +import io.github.furstenheim.CopyDown private const val ScrollDelta = 50 @@ -46,10 +43,11 @@ fun LobstersApp( viewModel: ClawViewModel = viewModel(), urlLauncher: UrlLauncher, ) { + val copydown = remember { CopyDown() } val systemUiController = rememberSystemUiController() val scaffoldState = rememberScaffoldState() val listState = rememberLazyListState() - val coroutineScope = rememberCoroutineScope() + val navController = rememberNavController() var isFabVisible by remember { mutableStateOf(true) } val nestedScrollConnection = remember { object : NestedScrollConnection { @@ -77,32 +75,40 @@ fun LobstersApp( systemUiController.setNavigationBarColor(color = Color.Transparent) } val items = viewModel.pagerFlow.collectAsLazyPagingItems() + Scaffold( scaffoldState = scaffoldState, topBar = { ClawAppBar(modifier = Modifier.statusBarsPadding()) }, floatingActionButton = { ClawFab( - isFabVisible = isFabVisible, + isFabVisible = isFabVisible && navController.currentDestination?.route == "hottest", listState = listState, modifier = Modifier.navigationBarsPadding(), ) }, - ) { - val isRefreshing = items.loadState.refresh == LoadState.Loading - SwipeRefresh( - state = rememberSwipeRefreshState(isRefreshing), - onRefresh = viewModel::reloadPosts, - ) { - if (items.itemCount == 0) { - Box(modifier = Modifier.fillMaxSize()) - } else { - NetworkPosts( - items = items, - launchUrl = urlLauncher::launch, - listState = listState, - isSaved = viewModel::isPostSaved, - toggleSave = { coroutineScope.launch { viewModel.toggleSave(it) } }, - modifier = Modifier.padding(top = 16.dp).nestedScroll(nestedScrollConnection), + ) { paddingValues -> + NavHost(navController, startDestination = "hottest") { + composable("hottest") { + HottestPosts( + items, + listState, + viewModel::isPostSaved, + viewModel::toggleSave, + viewModel::reloadPosts, + urlLauncher::launch, + { navController.navigate("comments/$it") }, + Modifier.nestedScroll(nestedScrollConnection), + ) + } + composable("comments/{postId}") { backStackEntry -> + CommentsPage( + postId = requireNotNull(backStackEntry.arguments?.getString("postId")), + getDetails = viewModel::getPostComments, + renderMarkdown = { source, modifier -> + val markdown = copydown.convert(source) + Markdown(markdown, modifier = modifier) + }, + paddingValues = paddingValues, ) } } diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/NetworkPosts.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/NetworkPosts.kt index 8c3e7143..03f9189a 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/NetworkPosts.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/NetworkPosts.kt @@ -13,8 +13,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.paging.compose.LazyPagingItems 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.toDbModel import dev.msfjarvis.claw.database.local.SavedPost import dev.msfjarvis.claw.model.LobstersPost import kotlinx.coroutines.launch @@ -26,6 +26,7 @@ fun NetworkPosts( launchUrl: (String) -> Unit, isSaved: suspend (SavedPost) -> Boolean, toggleSave: (SavedPost) -> Unit, + viewComments: (String) -> Unit, modifier: Modifier = Modifier, ) { val coroutineScope = rememberCoroutineScope() @@ -42,7 +43,7 @@ fun NetworkPosts( post = dbModel, isSaved = saved, viewPost = { launchUrl(item.url.ifEmpty { item.commentsUrl }) }, - viewComments = { launchUrl(item.commentsUrl) }, + viewComments = { viewComments(item.shortId) }, toggleSave = { toggleSave(dbModel) }, modifier = Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp), ) diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/viewmodel/ClawViewModel.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/viewmodel/ClawViewModel.kt index d24b16d9..01c646e6 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/viewmodel/ClawViewModel.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/viewmodel/ClawViewModel.kt @@ -7,19 +7,22 @@ import dagger.hilt.android.lifecycle.HiltViewModel import dev.msfjarvis.claw.android.paging.LobstersPagingSource import dev.msfjarvis.claw.api.LobstersApi import dev.msfjarvis.claw.database.local.SavedPost +import dev.msfjarvis.claw.model.LobstersPostDetails import javax.inject.Inject +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.last import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.withContext @OptIn(ExperimentalCoroutinesApi::class) @HiltViewModel class ClawViewModel @Inject constructor( - api: LobstersApi, + private val api: LobstersApi, private val repository: SavedPostsRepository, ) : ViewModel() { 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() { lastPagingSource?.invalidate() } diff --git a/build.gradle.kts b/build.gradle.kts index 8caa6771..7b0330bf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ buildscript { classpath("com.android.tools:r8:3.1.17-dev") classpath(kotlin("gradle-plugin", 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.google.dagger:hilt-android-gradle-plugin:2.39") } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index f72eb54a..e15d2a6d 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -16,6 +16,7 @@ kotlin { api(compose.foundation) api(compose.material) api(projects.database) + api(projects.model) } } sourceSets["androidMain"].apply { diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/NetworkState.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/NetworkState.kt new file mode 100644 index 00000000..99666597 --- /dev/null +++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/NetworkState.kt @@ -0,0 +1,7 @@ +package dev.msfjarvis.lobsters.ui.comments + +sealed class NetworkState { + class Success(val data: T) : NetworkState() + class Error(val message: String) : NetworkState() + object Loading : NetworkState() +} diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentEntry.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentEntry.kt new file mode 100644 index 00000000..3954cf4d --- /dev/null +++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentEntry.kt @@ -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]) + ) + } + } +} diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentTreeColors.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentTreeColors.kt index 6fb6159b..11401ef9 100644 --- a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentTreeColors.kt +++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/CommentTreeColors.kt @@ -24,7 +24,7 @@ object CommentTreeColor { Color(0xFFFF0097), Color(0xFF1E7145), ) - private val size = colors.size + val size = colors.size operator fun get(idx: Int): Color = colors[idx % size] } diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/Comments.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/Comments.kt new file mode 100644 index 00000000..feb0da24 --- /dev/null +++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/comments/Comments.kt @@ -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).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) } +} diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/LobstersItem.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/LobstersItem.kt index f9888fee..44751575 100644 --- a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/LobstersItem.kt +++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/LobstersItem.kt @@ -37,18 +37,6 @@ import dev.msfjarvis.claw.common.theme.titleColor import dev.msfjarvis.claw.common.ui.NetworkImage 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 @OptIn(ExperimentalMaterialApi::class) fun LobstersCard( @@ -67,16 +55,8 @@ fun LobstersCard( modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp).fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(4.dp), ) { - 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}", + PostDetails( + post = post, ) Row( 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 fun PostTitle( title: String, diff --git a/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/ext.kt b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/ext.kt new file mode 100644 index 00000000..9c6b1398 --- /dev/null +++ b/common/src/commonMain/kotlin/dev/msfjarvis/claw/common/posts/ext.kt @@ -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, + ) +} diff --git a/desktop/src/jvmMain/kotlin/main.kt b/desktop/src/jvmMain/kotlin/main.kt index e5ef9c0b..f510549d 100644 --- a/desktop/src/jvmMain/kotlin/main.kt +++ b/desktop/src/jvmMain/kotlin/main.kt @@ -14,27 +14,13 @@ import androidx.compose.ui.window.WindowPosition import androidx.compose.ui.window.application import androidx.compose.ui.window.rememberWindowState 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.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.skin.ceruleanSkin 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 { val paging = Paging(rememberCoroutineScope()) val items = paging.pagingData.collectAsLazyPagingItems() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 07e135b0..280a0cfc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,6 +23,7 @@ androidx-appcompat = "androidx.appcompat:appcompat:1.4.0-beta01" androidx-browser = "androidx.browser:browser:1.4.0-beta01" androidx-coreKtx = "androidx.core:core-ktx:1.7.0-beta02" 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" 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-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" retrofit-lib = "com.squareup.retrofit2:retrofit:2.9.0"