mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 08:17:04 +05:30
all: remove unused desktop code
This commit is contained in:
parent
325a4e34f6
commit
0cb4393947
6 changed files with 1 additions and 511 deletions
|
@ -1,50 +0,0 @@
|
||||||
@file:Suppress("DSL_SCOPE_VIOLATION", "UnstableApiUsage")
|
|
||||||
|
|
||||||
import org.jetbrains.compose.compose
|
|
||||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
kotlin("multiplatform")
|
|
||||||
alias(libs.plugins.compose)
|
|
||||||
id("dev.msfjarvis.claw.kotlin-common")
|
|
||||||
}
|
|
||||||
|
|
||||||
group = "dev.msfjarvis.claw"
|
|
||||||
|
|
||||||
version = "1.0"
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
jvm { compilations.all { kotlinOptions.jvmTarget = "11" } }
|
|
||||||
sourceSets["jvmMain"].apply {
|
|
||||||
dependencies {
|
|
||||||
implementation(compose.desktop.currentOs)
|
|
||||||
implementation(projects.api)
|
|
||||||
implementation(projects.common)
|
|
||||||
implementation(libs.aurora.component)
|
|
||||||
implementation(libs.aurora.theming)
|
|
||||||
implementation(libs.aurora.window)
|
|
||||||
implementation(libs.kotlinx.coroutines.core)
|
|
||||||
implementation(libs.kotlinx.serialization.json)
|
|
||||||
implementation(libs.ktor.client.java)
|
|
||||||
implementation(libs.multiplatform.paging)
|
|
||||||
implementation(libs.retrofit.lib)
|
|
||||||
implementation(libs.retrofit.kotlinxSerializationConverter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compose.desktop {
|
|
||||||
application {
|
|
||||||
mainClass = "MainKt"
|
|
||||||
jvmArgs += listOf("-Xmx1G")
|
|
||||||
nativeDistributions {
|
|
||||||
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
|
||||||
packageName = "Claw"
|
|
||||||
packageVersion = "1.0.0"
|
|
||||||
description = "Desktop client for lobste.rs link aggregation site"
|
|
||||||
copyright = "© 2021 Harsh Shandilya. All rights reserved."
|
|
||||||
vendor = "Harsh Shandilya"
|
|
||||||
includeAllModules = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
|
||||||
import dev.msfjarvis.claw.api.LobstersApi
|
|
||||||
import io.github.aakira.napier.Napier
|
|
||||||
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 val json = Json { ignoreUnknownKeys = true }
|
|
||||||
|
|
||||||
private fun getOkHttpClient(): OkHttpClient {
|
|
||||||
return OkHttpClient.Builder()
|
|
||||||
.addNetworkInterceptor { chain ->
|
|
||||||
val request = chain.request()
|
|
||||||
Napier.d(tag = "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()
|
|
||||||
}
|
|
|
@ -1,280 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import androidx.compose.foundation.lazy.LazyItemScope
|
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
|
||||||
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.paging.CombinedLoadStates
|
|
||||||
import androidx.paging.DifferCallback
|
|
||||||
import androidx.paging.ItemSnapshotList
|
|
||||||
import androidx.paging.LoadState
|
|
||||||
import androidx.paging.LoadStates
|
|
||||||
import androidx.paging.NullPaddedList
|
|
||||||
import androidx.paging.PagingData
|
|
||||||
import androidx.paging.PagingDataDiffer
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class responsible for accessing the data from a [Flow] of [PagingData]. In order to obtain an
|
|
||||||
* instance of [LazyPagingItems] use the [collectAsLazyPagingItems] extension method of [Flow] with
|
|
||||||
* [PagingData]. This instance can be used by the [items] and [itemsIndexed] methods inside
|
|
||||||
* [LazyListScope] to display data received from the [Flow] of [PagingData].
|
|
||||||
*
|
|
||||||
* @param T the type of value used by [PagingData].
|
|
||||||
*/
|
|
||||||
class LazyPagingItems<T : Any>
|
|
||||||
internal constructor(
|
|
||||||
/** the [Flow] object which contains a stream of [PagingData] elements. */
|
|
||||||
private val flow: Flow<PagingData<T>>
|
|
||||||
) {
|
|
||||||
private val mainDispatcher = Dispatchers.Default
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains the immutable [ItemSnapshotList] of currently presented items, including any
|
|
||||||
* placeholders if they are enabled. Note that similarly to [peek] accessing the items in a list
|
|
||||||
* will not trigger any loads. Use [get] to achieve such behavior.
|
|
||||||
*/
|
|
||||||
var itemSnapshotList by mutableStateOf(ItemSnapshotList<T>(0, 0, emptyList()))
|
|
||||||
private set
|
|
||||||
|
|
||||||
/** The number of items which can be accessed. */
|
|
||||||
val itemCount: Int
|
|
||||||
get() = itemSnapshotList.size
|
|
||||||
|
|
||||||
private val differCallback: DifferCallback =
|
|
||||||
object : DifferCallback {
|
|
||||||
override fun onChanged(position: Int, count: Int) {
|
|
||||||
if (count > 0) {
|
|
||||||
updateItemSnapshotList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onInserted(position: Int, count: Int) {
|
|
||||||
if (count > 0) {
|
|
||||||
updateItemSnapshotList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRemoved(position: Int, count: Int) {
|
|
||||||
if (count > 0) {
|
|
||||||
updateItemSnapshotList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val pagingDataDiffer =
|
|
||||||
object : PagingDataDiffer<T>(differCallback = differCallback, mainDispatcher = mainDispatcher) {
|
|
||||||
override suspend fun presentNewList(
|
|
||||||
previousList: NullPaddedList<T>,
|
|
||||||
newList: NullPaddedList<T>,
|
|
||||||
lastAccessedIndex: Int,
|
|
||||||
onListPresentable: () -> Unit
|
|
||||||
): Int? {
|
|
||||||
onListPresentable()
|
|
||||||
updateItemSnapshotList()
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateItemSnapshotList() {
|
|
||||||
itemSnapshotList = pagingDataDiffer.snapshot()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the presented item at the specified position, notifying Paging of the item access to
|
|
||||||
* trigger any loads necessary to fulfill prefetchDistance.
|
|
||||||
*
|
|
||||||
* @see peek
|
|
||||||
*/
|
|
||||||
operator fun get(index: Int): T? {
|
|
||||||
pagingDataDiffer[index] // this registers the value load
|
|
||||||
return itemSnapshotList[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the presented item at the specified position, without notifying Paging of the item
|
|
||||||
* access that would normally trigger page loads.
|
|
||||||
*
|
|
||||||
* @param index Index of the presented item to return, including placeholders.
|
|
||||||
* @return The presented item at position [index], `null` if it is a placeholder
|
|
||||||
*/
|
|
||||||
fun peek(index: Int): T? {
|
|
||||||
return itemSnapshotList[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retry any failed load requests that would result in a [LoadState.Error] update to this
|
|
||||||
* [LazyPagingItems].
|
|
||||||
*
|
|
||||||
* Unlike [refresh], this does not invalidate [PagingSource], it only retries failed loads within
|
|
||||||
* the same generation of [PagingData].
|
|
||||||
*
|
|
||||||
* [LoadState.Error] can be generated from two types of load requests:
|
|
||||||
* * [PagingSource.load] returning [PagingSource.LoadResult.Error]
|
|
||||||
* * [RemoteMediator.load] returning [RemoteMediator.MediatorResult.Error]
|
|
||||||
*/
|
|
||||||
fun retry() {
|
|
||||||
pagingDataDiffer.retry()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refresh the data presented by this [LazyPagingItems].
|
|
||||||
*
|
|
||||||
* [refresh] triggers the creation of a new [PagingData] with a new instance of [PagingSource] to
|
|
||||||
* represent an updated snapshot of the backing dataset. If a [RemoteMediator] is set, calling
|
|
||||||
* [refresh] will also trigger a call to [RemoteMediator.load] with [LoadType] [REFRESH] to allow
|
|
||||||
* [RemoteMediator] to check for updates to the dataset backing [PagingSource].
|
|
||||||
*
|
|
||||||
* Note: This API is intended for UI-driven refresh signals, such as swipe-to-refresh.
|
|
||||||
* Invalidation due repository-layer signals, such as DB-updates, should instead use
|
|
||||||
* [PagingSource.invalidate].
|
|
||||||
*
|
|
||||||
* @see PagingSource.invalidate
|
|
||||||
*/
|
|
||||||
fun refresh() {
|
|
||||||
pagingDataDiffer.refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A [CombinedLoadStates] object which represents the current loading state. */
|
|
||||||
var loadState: CombinedLoadStates by
|
|
||||||
mutableStateOf(
|
|
||||||
CombinedLoadStates(
|
|
||||||
refresh = InitialLoadStates.refresh,
|
|
||||||
prepend = InitialLoadStates.prepend,
|
|
||||||
append = InitialLoadStates.append,
|
|
||||||
source = InitialLoadStates
|
|
||||||
)
|
|
||||||
)
|
|
||||||
private set
|
|
||||||
|
|
||||||
internal suspend fun collectLoadState() {
|
|
||||||
pagingDataDiffer.loadStateFlow.collect { loadState = it }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal suspend fun collectPagingData() {
|
|
||||||
flow.collectLatest { pagingDataDiffer.collectFrom(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val IncompleteLoadState = LoadState.NotLoading(false)
|
|
||||||
private val InitialLoadStates =
|
|
||||||
LoadStates(IncompleteLoadState, IncompleteLoadState, IncompleteLoadState)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collects values from this [Flow] of [PagingData] and represents them inside a [LazyPagingItems]
|
|
||||||
* instance. The [LazyPagingItems] instance can be used by the [items] and [itemsIndexed] methods
|
|
||||||
* from [LazyListScope] in order to display the data obtained from a [Flow] of [PagingData].
|
|
||||||
*
|
|
||||||
* @sample androidx.paging.compose.samples.PagingBackendSample
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
fun <T : Any> Flow<PagingData<T>>.collectAsLazyPagingItems(): LazyPagingItems<T> {
|
|
||||||
val lazyPagingItems = remember(this) { LazyPagingItems(this) }
|
|
||||||
|
|
||||||
LaunchedEffect(lazyPagingItems) { lazyPagingItems.collectPagingData() }
|
|
||||||
LaunchedEffect(lazyPagingItems) { lazyPagingItems.collectLoadState() }
|
|
||||||
|
|
||||||
return lazyPagingItems
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the [LazyPagingItems] and their content to the scope. The range from 0 (inclusive) to
|
|
||||||
* [LazyPagingItems.itemCount] (exclusive) always represents the full range of presentable items,
|
|
||||||
* because every event from [PagingDataDiffer] will trigger a recomposition.
|
|
||||||
*
|
|
||||||
* @sample androidx.paging.compose.samples.ItemsDemo
|
|
||||||
*
|
|
||||||
* @param items the items received from a [Flow] of [PagingData].
|
|
||||||
* @param key a factory of stable and unique keys representing the item. Using the same key for
|
|
||||||
* multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
|
|
||||||
* Android. If null is passed the position in the list will represent the key. When you specify the
|
|
||||||
* key the scroll position will be maintained based on the key, which means if you add/remove items
|
|
||||||
* before the current visible item the item with the given key will be kept as the first visible
|
|
||||||
* one.
|
|
||||||
* @param itemContent the content displayed by a single item. In case the item is `null`, the
|
|
||||||
* [itemContent] method should handle the logic of displaying a placeholder instead of the main
|
|
||||||
* content displayed by an item which is not `null`.
|
|
||||||
*/
|
|
||||||
fun <T : Any> LazyListScope.items(
|
|
||||||
items: LazyPagingItems<T>,
|
|
||||||
key: ((item: T) -> Any)? = null,
|
|
||||||
itemContent: @Composable LazyItemScope.(value: T?) -> Unit
|
|
||||||
) {
|
|
||||||
items(
|
|
||||||
count = items.itemCount,
|
|
||||||
key =
|
|
||||||
if (key == null) null
|
|
||||||
else
|
|
||||||
{ index ->
|
|
||||||
val item = items.peek(index)
|
|
||||||
if (item == null) {
|
|
||||||
PagingPlaceholderKey(index)
|
|
||||||
} else {
|
|
||||||
key(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) { index -> itemContent(items[index]) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the [LazyPagingItems] and their content to the scope where the content of an item is aware
|
|
||||||
* of its local index. The range from 0 (inclusive) to [LazyPagingItems.itemCount] (exclusive)
|
|
||||||
* always represents the full range of presentable items, because every event from
|
|
||||||
* [PagingDataDiffer] will trigger a recomposition.
|
|
||||||
*
|
|
||||||
* @sample androidx.paging.compose.samples.ItemsIndexedDemo
|
|
||||||
*
|
|
||||||
* @param items the items received from a [Flow] of [PagingData].
|
|
||||||
* @param key a factory of stable and unique keys representing the item. Using the same key for
|
|
||||||
* multiple items in the list is not allowed. Type of the key should be saveable via Bundle on
|
|
||||||
* Android. If null is passed the position in the list will represent the key. When you specify the
|
|
||||||
* key the scroll position will be maintained based on the key, which means if you add/remove items
|
|
||||||
* before the current visible item the item with the given key will be kept as the first visible
|
|
||||||
* one.
|
|
||||||
* @param itemContent the content displayed by a single item. In case the item is `null`, the
|
|
||||||
* [itemContent] method should handle the logic of displaying a placeholder instead of the main
|
|
||||||
* content displayed by an item which is not `null`.
|
|
||||||
*/
|
|
||||||
fun <T : Any> LazyListScope.itemsIndexed(
|
|
||||||
items: LazyPagingItems<T>,
|
|
||||||
key: ((index: Int, item: T) -> Any)? = null,
|
|
||||||
itemContent: @Composable LazyItemScope.(index: Int, value: T?) -> Unit
|
|
||||||
) {
|
|
||||||
items(
|
|
||||||
count = items.itemCount,
|
|
||||||
key =
|
|
||||||
if (key == null) null
|
|
||||||
else
|
|
||||||
{ index ->
|
|
||||||
val item = items.peek(index)
|
|
||||||
if (item == null) {
|
|
||||||
PagingPlaceholderKey(index)
|
|
||||||
} else {
|
|
||||||
key(index, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) { index -> itemContent(index, items[index]) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private data class PagingPlaceholderKey(private val index: Int)
|
|
|
@ -1,31 +0,0 @@
|
||||||
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)
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
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.rememberLazyListState
|
|
||||||
import androidx.compose.foundation.rememberScrollbarAdapter
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalUriHandler
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.window.WindowPlacement
|
|
||||||
import androidx.compose.ui.window.WindowPosition
|
|
||||||
import androidx.compose.ui.window.rememberWindowState
|
|
||||||
import dev.msfjarvis.claw.api.LobstersApi
|
|
||||||
import dev.msfjarvis.claw.common.posts.LobstersCard
|
|
||||||
import dev.msfjarvis.claw.common.posts.PostActions
|
|
||||||
import dev.msfjarvis.claw.common.posts.toDbModel
|
|
||||||
import dev.msfjarvis.claw.common.theme.DarkThemeColors
|
|
||||||
import dev.msfjarvis.claw.common.theme.LightThemeColors
|
|
||||||
import dev.msfjarvis.claw.common.theme.LobstersTheme
|
|
||||||
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
|
|
||||||
import dev.msfjarvis.claw.database.local.SavedPost
|
|
||||||
import org.pushingpixels.aurora.component.AuroraVerticalScrollbar
|
|
||||||
import org.pushingpixels.aurora.theming.ceruleanSkin
|
|
||||||
import org.pushingpixels.aurora.window.AuroraWindow
|
|
||||||
import org.pushingpixels.aurora.window.auroraApplication
|
|
||||||
|
|
||||||
fun main() = auroraApplication {
|
|
||||||
val paging = Paging(rememberCoroutineScope())
|
|
||||||
val items = paging.pagingData.collectAsLazyPagingItems()
|
|
||||||
val urlLauncher = UrlLauncher()
|
|
||||||
val state =
|
|
||||||
rememberWindowState(
|
|
||||||
placement = WindowPlacement.Floating,
|
|
||||||
position = WindowPosition.Aligned(Alignment.Center),
|
|
||||||
)
|
|
||||||
val postActions = remember {
|
|
||||||
object : PostActions {
|
|
||||||
override fun viewPost(postUrl: String, commentsUrl: String) {
|
|
||||||
urlLauncher.openUri(postUrl.ifEmpty { commentsUrl })
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun viewComments(postId: String) {
|
|
||||||
urlLauncher.openUri("${LobstersApi.BASE_URL}/s/${postId}")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun viewCommentsPage(commentsUrl: String) {
|
|
||||||
urlLauncher.openUri(commentsUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toggleSave(post: SavedPost) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AuroraWindow(
|
|
||||||
skin = ceruleanSkin(),
|
|
||||||
title = "Claw",
|
|
||||||
state = state,
|
|
||||||
undecorated = true,
|
|
||||||
onCloseRequest = ::exitApplication,
|
|
||||||
) {
|
|
||||||
val colorScheme =
|
|
||||||
if (isSystemInDarkTheme()) {
|
|
||||||
DarkThemeColors
|
|
||||||
} else {
|
|
||||||
LightThemeColors
|
|
||||||
}
|
|
||||||
LobstersTheme(
|
|
||||||
colorScheme = colorScheme,
|
|
||||||
providedValues = arrayOf(LocalUriHandler provides urlLauncher),
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
) {
|
|
||||||
val listState = rememberLazyListState()
|
|
||||||
if (items.itemCount == 0) {
|
|
||||||
Box(modifier = Modifier.fillMaxSize())
|
|
||||||
} else {
|
|
||||||
LazyColumn(
|
|
||||||
state = listState,
|
|
||||||
) {
|
|
||||||
items(items) { item ->
|
|
||||||
if (item != null) {
|
|
||||||
LobstersCard(
|
|
||||||
post = item.toDbModel(),
|
|
||||||
isSaved = false,
|
|
||||||
postActions = postActions,
|
|
||||||
modifier = Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AuroraVerticalScrollbar(
|
|
||||||
adapter = rememberScrollbarAdapter(listState),
|
|
||||||
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@
|
||||||
accompanist = "0.26.0-alpha"
|
accompanist = "0.26.0-alpha"
|
||||||
agp = "7.2.1"
|
agp = "7.2.1"
|
||||||
androidXTest = "1.4.0"
|
androidXTest = "1.4.0"
|
||||||
aurora = "1.2-SNAPSHOT"
|
|
||||||
coil = "2.1.0"
|
coil = "2.1.0"
|
||||||
# @keep This is used by paparazzi-tests and Renovate
|
# @keep This is used by paparazzi-tests and Renovate
|
||||||
composeCompiler = "1.3.0-rc01"
|
composeCompiler = "1.3.0-rc01"
|
||||||
|
@ -47,9 +46,6 @@ androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidXT
|
||||||
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidXTest" }
|
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidXTest" }
|
||||||
androidx-test-uiautomator = "androidx.test.uiautomator:uiautomator:2.2.0"
|
androidx-test-uiautomator = "androidx.test.uiautomator:uiautomator:2.2.0"
|
||||||
androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workmanager" }
|
androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workmanager" }
|
||||||
aurora-component = { module = "org.pushing-pixels:aurora-component", version.ref = "aurora" }
|
|
||||||
aurora-theming = { module = "org.pushing-pixels:aurora-theming", version.ref = "aurora" }
|
|
||||||
aurora-window = { module = "org.pushing-pixels:aurora-window", version.ref = "aurora" }
|
|
||||||
build-agp = { module = "com.android.tools.build:gradle", version.ref = "agp" }
|
build-agp = { module = "com.android.tools.build:gradle", version.ref = "agp" }
|
||||||
build-cachefix = "org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin:2.5.5"
|
build-cachefix = "org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin:2.5.5"
|
||||||
build-kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
build-kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||||
|
@ -66,15 +62,12 @@ copydown = "io.github.furstenheim:copy_down:1.0"
|
||||||
dagger-hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "dagger" }
|
dagger-hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "dagger" }
|
||||||
dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "dagger" }
|
dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "dagger" }
|
||||||
javapoet = "com.squareup:javapoet:1.13.0"
|
javapoet = "com.squareup:javapoet:1.13.0"
|
||||||
kamel-image = "com.alialbaali.kamel:kamel-image:0.4.1"
|
|
||||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
|
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
|
||||||
kotlinx-datetime = "org.jetbrains.kotlinx:kotlinx-datetime:0.4.0"
|
kotlinx-datetime = "org.jetbrains.kotlinx:kotlinx-datetime:0.4.0"
|
||||||
kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "serialization" }
|
kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "serialization" }
|
||||||
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
|
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
|
||||||
ktor-client-java = "io.ktor:ktor-client-java:2.0.3"
|
|
||||||
material_motion-core = { module = "io.github.fornewid:material-motion-compose-core", version.ref = "material_motion" }
|
material_motion-core = { module = "io.github.fornewid:material-motion-compose-core", version.ref = "material_motion" }
|
||||||
material_motion-navigation = { module = "io.github.fornewid:material-motion-compose-navigation", version.ref = "material_motion" }
|
material_motion-navigation = { module = "io.github.fornewid:material-motion-compose-navigation", version.ref = "material_motion" }
|
||||||
multiplatform-paging = "io.github.kuuuurt:multiplatform-paging:0.4.7"
|
|
||||||
napier = "io.github.aakira:napier:2.6.1"
|
napier = "io.github.aakira:napier:2.6.1"
|
||||||
okhttp-loggingInterceptor = "com.squareup.okhttp3:logging-interceptor:3.14.9"
|
okhttp-loggingInterceptor = "com.squareup.okhttp3:logging-interceptor:3.14.9"
|
||||||
retrofit-kotlinxSerializationConverter = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
retrofit-kotlinxSerializationConverter = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
||||||
|
@ -88,8 +81,7 @@ testparameterinjector = "com.google.testparameterinjector:test-parameter-injecto
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-test = { id = "com.android.test", version.ref = "agp" }
|
android-test = { id = "com.android.test", version.ref = "agp" }
|
||||||
aurora-svg-transcoder = { id = "org.pushing-pixels.aurora.tools.svgtranscoder.gradle", version.ref = "aurora" }
|
aurora-svg-transcoder = "org.pushing-pixels.aurora.tools.svgtranscoder.gradle:1.2-SNAPSHOT"
|
||||||
compose = "org.jetbrains.compose:1.2.0-alpha01-dev753"
|
|
||||||
hilt = { id = "com.google.dagger.hilt.android", version.ref = "dagger" }
|
hilt = { id = "com.google.dagger.hilt.android", version.ref = "dagger" }
|
||||||
paparazzi = "app.cash.paparazzi:1.0.0"
|
paparazzi = "app.cash.paparazzi:1.0.0"
|
||||||
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
|
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue