diff --git a/desktop/src/jvmMain/kotlin/Api.kt b/desktop/src/jvmMain/kotlin/Api.kt new file mode 100644 index 00000000..bfd30ae7 --- /dev/null +++ b/desktop/src/jvmMain/kotlin/Api.kt @@ -0,0 +1,34 @@ +import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory +import dev.msfjarvis.claw.api.LobstersApi +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import okhttp3.MediaType +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.create + +@OptIn(ExperimentalSerializationApi::class) +class Api { + private fun getOkHttpClient(): OkHttpClient { + return OkHttpClient.Builder() + .addNetworkInterceptor { chain -> + val request = chain.request() + println("LobstersApi: ${request.method()}: ${request.url()}") + chain.proceed(request) + } + .build() + } + + private fun getRetrofit( + okHttpClient: OkHttpClient, + ): Retrofit { + val contentType = MediaType.get("application/json") + return Retrofit.Builder() + .client(okHttpClient) + .baseUrl(LobstersApi.BASE_URL) + .addConverterFactory(Json.asConverterFactory(contentType)) + .build() + } + + val api: LobstersApi = getRetrofit(getOkHttpClient()).create() +} diff --git a/desktop/src/jvmMain/kotlin/Paging.kt b/desktop/src/jvmMain/kotlin/Paging.kt new file mode 100644 index 00000000..069e0144 --- /dev/null +++ b/desktop/src/jvmMain/kotlin/Paging.kt @@ -0,0 +1,31 @@ +import androidx.paging.PagingConfig +import androidx.paging.cachedIn +import com.kuuurt.paging.multiplatform.Pager +import com.kuuurt.paging.multiplatform.PagingResult +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.FlowPreview + +@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class) +class Paging( + private val coroutineScope: CoroutineScope, +) { + private val api = Api() + private val pager = + Pager( + clientScope = coroutineScope, + config = PagingConfig(20), + initialKey = 1, + getItems = { currentKey, _ -> + val items = api.api.getHottestPosts(currentKey) + PagingResult( + items = items, + currentKey = currentKey, + prevKey = { if (currentKey == 1) null else currentKey - 1 }, + nextKey = { currentKey + 1 }, + ) + } + ) + val pagingData + get() = pager.pagingData.cachedIn(coroutineScope) +} diff --git a/desktop/src/jvmMain/kotlin/main.kt b/desktop/src/jvmMain/kotlin/main.kt index 957ac593..e5ef9c0b 100644 --- a/desktop/src/jvmMain/kotlin/main.kt +++ b/desktop/src/jvmMain/kotlin/main.kt @@ -3,9 +3,9 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.rememberScrollbarAdapter +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -14,21 +14,36 @@ 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.TEST_POST 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() val urlLauncher = UrlLauncher() val state = rememberWindowState( placement = WindowPlacement.Floating, position = WindowPosition.Aligned(Alignment.Center), ) - val itemsList = (0 until 10).toList() AuroraWindow( skin = ceruleanSkin(), title = "Claw", @@ -41,18 +56,24 @@ fun main() = application { modifier = Modifier.fillMaxSize(), ) { val listState = rememberLazyListState() - LazyColumn( - state = listState, - ) { - itemsIndexed(itemsList) { _, _ -> - LobstersCard( - post = TEST_POST, - isSaved = false, - viewPost = { urlLauncher.launch(TEST_POST.url.ifEmpty { TEST_POST.commentsUrl }) }, - viewComments = { urlLauncher.launch(TEST_POST.commentsUrl) }, - toggleSave = {}, - modifier = Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp), - ) + if (items.itemCount == 0) { + Box(modifier = Modifier.fillMaxSize()) + } else { + LazyColumn( + state = listState, + ) { + items(items) { item -> + if (item != null) { + LobstersCard( + post = item.toDbModel(), + isSaved = false, + viewPost = { urlLauncher.launch(item.url.ifEmpty { item.commentsUrl }) }, + viewComments = { urlLauncher.launch(item.commentsUrl) }, + toggleSave = {}, + modifier = Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp), + ) + } + } } } AuroraVerticalScrollbar(