mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-15 13:27:03 +05:30
desktop: wire in API into desktop client
This commit is contained in:
parent
2fa682048a
commit
2abbda7641
3 changed files with 101 additions and 15 deletions
34
desktop/src/jvmMain/kotlin/Api.kt
Normal file
34
desktop/src/jvmMain/kotlin/Api.kt
Normal file
|
@ -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()
|
||||||
|
}
|
31
desktop/src/jvmMain/kotlin/Paging.kt
Normal file
31
desktop/src/jvmMain/kotlin/Paging.kt
Normal file
|
@ -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)
|
||||||
|
}
|
|
@ -3,9 +3,9 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.rememberScrollbarAdapter
|
import androidx.compose.foundation.rememberScrollbarAdapter
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
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.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.TEST_POST
|
|
||||||
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 items = paging.pagingData.collectAsLazyPagingItems()
|
||||||
val urlLauncher = UrlLauncher()
|
val urlLauncher = UrlLauncher()
|
||||||
val state =
|
val state =
|
||||||
rememberWindowState(
|
rememberWindowState(
|
||||||
placement = WindowPlacement.Floating,
|
placement = WindowPlacement.Floating,
|
||||||
position = WindowPosition.Aligned(Alignment.Center),
|
position = WindowPosition.Aligned(Alignment.Center),
|
||||||
)
|
)
|
||||||
val itemsList = (0 until 10).toList()
|
|
||||||
AuroraWindow(
|
AuroraWindow(
|
||||||
skin = ceruleanSkin(),
|
skin = ceruleanSkin(),
|
||||||
title = "Claw",
|
title = "Claw",
|
||||||
|
@ -41,18 +56,24 @@ fun main() = application {
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
LazyColumn(
|
if (items.itemCount == 0) {
|
||||||
state = listState,
|
Box(modifier = Modifier.fillMaxSize())
|
||||||
) {
|
} else {
|
||||||
itemsIndexed(itemsList) { _, _ ->
|
LazyColumn(
|
||||||
LobstersCard(
|
state = listState,
|
||||||
post = TEST_POST,
|
) {
|
||||||
isSaved = false,
|
items(items) { item ->
|
||||||
viewPost = { urlLauncher.launch(TEST_POST.url.ifEmpty { TEST_POST.commentsUrl }) },
|
if (item != null) {
|
||||||
viewComments = { urlLauncher.launch(TEST_POST.commentsUrl) },
|
LobstersCard(
|
||||||
toggleSave = {},
|
post = item.toDbModel(),
|
||||||
modifier = Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp),
|
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(
|
AuroraVerticalScrollbar(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue