mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 12:57: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"
|
||||
agp = "7.2.1"
|
||||
androidXTest = "1.4.0"
|
||||
aurora = "1.2-SNAPSHOT"
|
||||
coil = "2.1.0"
|
||||
# @keep This is used by paparazzi-tests and Renovate
|
||||
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-uiautomator = "androidx.test.uiautomator:uiautomator:2.2.0"
|
||||
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-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" }
|
||||
|
@ -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-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "dagger" }
|
||||
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-datetime = "org.jetbrains.kotlinx:kotlinx-datetime:0.4.0"
|
||||
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" }
|
||||
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-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"
|
||||
okhttp-loggingInterceptor = "com.squareup.okhttp3:logging-interceptor:3.14.9"
|
||||
retrofit-kotlinxSerializationConverter = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
||||
|
@ -88,8 +81,7 @@ testparameterinjector = "com.google.testparameterinjector:test-parameter-injecto
|
|||
|
||||
[plugins]
|
||||
android-test = { id = "com.android.test", version.ref = "agp" }
|
||||
aurora-svg-transcoder = { id = "org.pushing-pixels.aurora.tools.svgtranscoder.gradle", version.ref = "aurora" }
|
||||
compose = "org.jetbrains.compose:1.2.0-alpha01-dev753"
|
||||
aurora-svg-transcoder = "org.pushing-pixels.aurora.tools.svgtranscoder.gradle:1.2-SNAPSHOT"
|
||||
hilt = { id = "com.google.dagger.hilt.android", version.ref = "dagger" }
|
||||
paparazzi = "app.cash.paparazzi:1.0.0"
|
||||
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue