Feat(LibrariesScreen): Finish LibrariesScreen
Implement open source license display in LibrariesScreen
This commit is contained in:
@@ -8,6 +8,7 @@ plugins {
|
||||
alias(libs.plugins.aboutlibraries)
|
||||
alias(libs.plugins.hilt)
|
||||
alias(libs.plugins.protobuf)
|
||||
alias(libs.plugins.kotlinxSerialization)
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -98,11 +99,7 @@ aboutLibraries {
|
||||
registerAndroidTasks = false
|
||||
configPath = "libConfig"
|
||||
outputFileName = "dependencies.json"
|
||||
exclusionPatterns = listOf(
|
||||
Regex("androidx.*"),
|
||||
Regex("org.jetbrains.*"),
|
||||
Regex("com.google.guava:listenablefuture")
|
||||
).map { it.toPattern() }
|
||||
exclusionPatterns = listOf<Regex>().map { it.toPattern() }
|
||||
}
|
||||
|
||||
task("exportLibrariesToJson", AboutLibrariesTask::class) {
|
||||
@@ -158,4 +155,5 @@ dependencies {
|
||||
implementation(libs.protobuf.kotlin.lite)
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
implementation(libs.androidx.hilt.navigation.compose)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package top.fatweb.oxygen.toolbox.data.lib
|
||||
|
||||
import android.content.Context
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.serialization.json.Json
|
||||
import top.fatweb.oxygen.toolbox.R
|
||||
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
||||
import top.fatweb.oxygen.toolbox.network.Dispatcher
|
||||
import top.fatweb.oxygen.toolbox.network.OxygenDispatchers
|
||||
import javax.inject.Inject
|
||||
|
||||
class DepDataSource @Inject constructor(
|
||||
private val context: Context,
|
||||
@Dispatcher(OxygenDispatchers.IO) private val ioDispatcher: CoroutineDispatcher
|
||||
) {
|
||||
private val json = Json { ignoreUnknownKeys = true }
|
||||
|
||||
val dependencies = flow {
|
||||
val inputStream = context.resources.openRawResource(R.raw.dependencies)
|
||||
val jsonString = inputStream.bufferedReader().use { it.readText() }
|
||||
val dependencies = json.decodeFromString<Dependencies>(jsonString)
|
||||
emit(dependencies)
|
||||
}.flowOn(ioDispatcher)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package top.fatweb.oxygen.toolbox.di
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object AppModule {
|
||||
@Provides
|
||||
fun provideContext(app: Application): Context = app.applicationContext
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import top.fatweb.oxygen.toolbox.monitor.ConnectivityManagerNetworkMonitor
|
||||
import top.fatweb.oxygen.toolbox.monitor.NetworkMonitor
|
||||
import top.fatweb.oxygen.toolbox.monitor.TimeZoneBroadcastMonitor
|
||||
import top.fatweb.oxygen.toolbox.monitor.TimeZoneMonitor
|
||||
import top.fatweb.oxygen.toolbox.repository.lib.DepRepository
|
||||
import top.fatweb.oxygen.toolbox.repository.lib.LocalDepRepository
|
||||
import top.fatweb.oxygen.toolbox.repository.tool.LocalToolRepository
|
||||
import top.fatweb.oxygen.toolbox.repository.tool.ToolRepository
|
||||
import top.fatweb.oxygen.toolbox.repository.userdata.LocalUserDataRepository
|
||||
@@ -27,4 +29,7 @@ abstract class DataModule {
|
||||
|
||||
@Binds
|
||||
internal abstract fun bindsToolRepository(toolRepository: LocalToolRepository): ToolRepository
|
||||
|
||||
@Binds
|
||||
internal abstract fun bindsDepRepository(depRepository: LocalDepRepository): DepRepository
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package top.fatweb.oxygen.toolbox.model.lib
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Dependencies(
|
||||
val metadata: Metadata,
|
||||
|
||||
val libraries: List<Library>,
|
||||
|
||||
val licenses: Map<String, License>
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.toolbox.model.lib
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Developer(
|
||||
val name: String? = null,
|
||||
|
||||
val organisationUrl: String? = null
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.toolbox.model.lib
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Funding(
|
||||
val platform: String,
|
||||
|
||||
val url: String
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
package top.fatweb.oxygen.toolbox.model.lib
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Library(
|
||||
val uniqueId: String,
|
||||
|
||||
val artifactVersion: String? = null,
|
||||
|
||||
val name: String? = null,
|
||||
|
||||
val description: String? = null,
|
||||
|
||||
val website: String? = null,
|
||||
|
||||
val developers: List<Developer>,
|
||||
|
||||
val organization: Organization? = null,
|
||||
|
||||
val scm: Scm? = null,
|
||||
|
||||
val licenses: List<String>,
|
||||
|
||||
val funding: List<Funding>,
|
||||
|
||||
val tag: String? = null
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
package top.fatweb.oxygen.toolbox.model.lib
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class License(
|
||||
val name: String,
|
||||
|
||||
val url: String? = null,
|
||||
|
||||
val year: String? = null,
|
||||
|
||||
val content: String? = null,
|
||||
|
||||
val internalHash: String? = null,
|
||||
|
||||
val hash: String,
|
||||
|
||||
val spdxId: String? = null
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package top.fatweb.oxygen.toolbox.model.lib
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Metadata(
|
||||
val generated: String
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.toolbox.model.lib
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Organization(
|
||||
val name: String,
|
||||
|
||||
val url: String? = null
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package top.fatweb.oxygen.toolbox.model.lib
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Scm(
|
||||
val connection: String? = null,
|
||||
|
||||
val developerConnection: String? = null,
|
||||
|
||||
val url: String? = null
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package top.fatweb.oxygen.toolbox.repository.lib
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
||||
|
||||
interface DepRepository {
|
||||
val dependencies: Flow<Dependencies>
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package top.fatweb.oxygen.toolbox.repository.lib
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import top.fatweb.oxygen.toolbox.data.lib.DepDataSource
|
||||
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
||||
import javax.inject.Inject
|
||||
|
||||
class LocalDepRepository @Inject constructor(
|
||||
depDataSource: DepDataSource
|
||||
) : DepRepository {
|
||||
override val dependencies: Flow<Dependencies> =
|
||||
depDataSource.dependencies
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -32,7 +33,7 @@ internal fun AboutRoute(
|
||||
modifier: Modifier = Modifier, onBackClick: () -> Unit, onNavigateToLibraries: () -> Unit
|
||||
) {
|
||||
AboutScreen(
|
||||
modifier = modifier,
|
||||
modifier = modifier.safeDrawingPadding(),
|
||||
onBackClick = onBackClick,
|
||||
onNavigateToLibraries = onNavigateToLibraries
|
||||
)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package top.fatweb.oxygen.toolbox.ui.about
|
||||
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridScope
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.items
|
||||
import top.fatweb.oxygen.toolbox.ui.component.LibraryCard
|
||||
|
||||
fun LazyStaggeredGridScope.librariesPanel(
|
||||
librariesScreenUiState: LibrariesScreenUiState,
|
||||
onClickLicense: (key: String) -> Unit
|
||||
) {
|
||||
when (librariesScreenUiState) {
|
||||
LibrariesScreenUiState.Loading -> Unit
|
||||
|
||||
is LibrariesScreenUiState.Success -> {
|
||||
items(
|
||||
items = librariesScreenUiState.dependencies.libraries,
|
||||
key = { it.uniqueId }
|
||||
) {
|
||||
LibraryCard(
|
||||
library = it,
|
||||
licenses = librariesScreenUiState.dependencies.licenses.filter { entry ->
|
||||
it.licenses.contains(entry.key)
|
||||
},
|
||||
onClickLicense = onClickLicense
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,71 @@
|
||||
package top.fatweb.oxygen.toolbox.ui.about
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.activity.compose.ReportDrawnWhen
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawing
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.layout.windowInsetsBottomHeight
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
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.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import top.fatweb.oxygen.toolbox.R
|
||||
import top.fatweb.oxygen.toolbox.icon.OxygenIcons
|
||||
import top.fatweb.oxygen.toolbox.ui.component.scrollbar.DraggableScrollbar
|
||||
import top.fatweb.oxygen.toolbox.ui.component.scrollbar.rememberDraggableScroller
|
||||
import top.fatweb.oxygen.toolbox.ui.component.scrollbar.scrollbarState
|
||||
import top.fatweb.oxygen.toolbox.ui.theme.OxygenPreviews
|
||||
import top.fatweb.oxygen.toolbox.ui.theme.OxygenTheme
|
||||
|
||||
@Composable
|
||||
internal fun LibrariesRoute(
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: LibrariesScreenViewModel = hiltViewModel(),
|
||||
onBackClick: () -> Unit
|
||||
) {
|
||||
val librariesScreenUiState by viewModel.librariesScreenUiState.collectAsStateWithLifecycle()
|
||||
|
||||
LibrariesScreen(
|
||||
modifier = modifier,
|
||||
modifier = modifier.safeDrawingPadding(),
|
||||
librariesScreenUiState = librariesScreenUiState,
|
||||
onBackClick = onBackClick
|
||||
)
|
||||
}
|
||||
@@ -29,15 +73,122 @@ internal fun LibrariesRoute(
|
||||
@Composable
|
||||
internal fun LibrariesScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
librariesScreenUiState: LibrariesScreenUiState,
|
||||
onBackClick: () -> Unit
|
||||
) {
|
||||
val configuration = LocalConfiguration.current
|
||||
val context = LocalContext.current
|
||||
|
||||
val isLibrariesLoading = librariesScreenUiState is LibrariesScreenUiState.Loading
|
||||
|
||||
ReportDrawnWhen { !isLibrariesLoading }
|
||||
|
||||
val itemsAvailable = howManyItems(librariesScreenUiState)
|
||||
|
||||
val state = rememberLazyStaggeredGridState()
|
||||
val scrollbarState = state.scrollbarState(itemsAvailable = itemsAvailable)
|
||||
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
var dialogTitle by remember { mutableStateOf("") }
|
||||
var dialogContent by remember { mutableStateOf("") }
|
||||
var dialogUrl by remember { mutableStateOf("") }
|
||||
|
||||
Column(
|
||||
modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally
|
||||
modifier = modifier
|
||||
) {
|
||||
LibrariesToolBar(
|
||||
onBackClick = onBackClick
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Box(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f)
|
||||
) {
|
||||
when (librariesScreenUiState) {
|
||||
LibrariesScreenUiState.Loading -> {
|
||||
Text(text = stringResource(R.string.feature_settings_loading))
|
||||
}
|
||||
|
||||
is LibrariesScreenUiState.Success -> {
|
||||
val handleOnClickLicense = { key: String ->
|
||||
val license = librariesScreenUiState.dependencies.licenses[key]
|
||||
if (license != null) {
|
||||
showDialog = true
|
||||
dialogTitle = license.name
|
||||
dialogContent = license.content ?: ""
|
||||
dialogUrl = license.url ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
LazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Adaptive(300.dp),
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
verticalItemSpacing = 24.dp,
|
||||
state = state
|
||||
) {
|
||||
librariesPanel(
|
||||
librariesScreenUiState = librariesScreenUiState,
|
||||
onClickLicense = handleOnClickLicense
|
||||
)
|
||||
|
||||
item(span = StaggeredGridItemSpan.FullLine) {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing))
|
||||
}
|
||||
}
|
||||
|
||||
state.DraggableScrollbar(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.windowInsetsPadding(WindowInsets.systemBars)
|
||||
.padding(horizontal = 2.dp)
|
||||
.align(Alignment.CenterEnd),
|
||||
state = scrollbarState, orientation = Orientation.Vertical,
|
||||
onThumbMoved = state.rememberDraggableScroller(itemsAvailable = itemsAvailable)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showDialog) {
|
||||
AlertDialog(
|
||||
modifier = Modifier
|
||||
.widthIn(max = configuration.screenWidthDp.dp - 80.dp)
|
||||
.heightIn(max = configuration.screenHeightDp.dp - 40.dp),
|
||||
onDismissRequest = { showDialog = false },
|
||||
title = {
|
||||
Text(
|
||||
text = dialogTitle,
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column(
|
||||
modifier = Modifier.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = dialogContent
|
||||
)
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
TextButton(onClick = {
|
||||
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(dialogUrl)))
|
||||
}) {
|
||||
Text(text = stringResource(R.string.core_website))
|
||||
}
|
||||
TextButton(onClick = { showDialog = false }) {
|
||||
Text(text = stringResource(R.string.core_close))
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,3 +210,18 @@ private fun LibrariesToolBar(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun howManyItems(librariesScreenUiState: LibrariesScreenUiState) =
|
||||
when (librariesScreenUiState) {
|
||||
LibrariesScreenUiState.Loading -> 0
|
||||
|
||||
is LibrariesScreenUiState.Success -> librariesScreenUiState.dependencies.libraries.size
|
||||
}
|
||||
|
||||
@OxygenPreviews
|
||||
@Composable
|
||||
private fun LibrariesScreenLoadingPreview() {
|
||||
OxygenTheme {
|
||||
LibrariesScreen(librariesScreenUiState = LibrariesScreenUiState.Loading, onBackClick = {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package top.fatweb.oxygen.toolbox.ui.about
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
||||
import top.fatweb.oxygen.toolbox.repository.lib.DepRepository
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@HiltViewModel
|
||||
class LibrariesScreenViewModel @Inject constructor(
|
||||
depRepository: DepRepository
|
||||
) : ViewModel() {
|
||||
val librariesScreenUiState: StateFlow<LibrariesScreenUiState> =
|
||||
depRepository.dependencies
|
||||
.map {
|
||||
LibrariesScreenUiState.Success(it)
|
||||
}
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
initialValue = LibrariesScreenUiState.Loading,
|
||||
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds)
|
||||
)
|
||||
}
|
||||
|
||||
sealed interface LibrariesScreenUiState {
|
||||
data object Loading: LibrariesScreenUiState
|
||||
|
||||
data class Success(val dependencies: Dependencies) : LibrariesScreenUiState
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,9 @@
|
||||
<string name="app_description">All in One</string>
|
||||
<string name="core_ok">完成</string>
|
||||
<string name="core_back">返回</string>
|
||||
<string name="core_close">关闭</string>
|
||||
<string name="core_unknown">未知</string>
|
||||
<string name="core_website">网站</string>
|
||||
<string name="core_no_connect">⚠️ 无法连接至互联网</string>
|
||||
<string name="feature_tools_title">工具</string>
|
||||
<string name="feature_star_title">收藏</string>
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
<string name="app_description">All in One</string>
|
||||
<string name="core_ok">OK</string>
|
||||
<string name="core_back">Back</string>
|
||||
<string name="core_close">Close</string>
|
||||
<string name="core_unknown">Unknown</string>
|
||||
<string name="core_website">Website</string>
|
||||
<string name="core_no_connect">⚠️ Unable to connect to the internet</string>
|
||||
<string name="feature_tools_title">Tools</string>
|
||||
<string name="feature_star_title">Star</string>
|
||||
|
||||
@@ -6,4 +6,5 @@ plugins {
|
||||
alias(libs.plugins.aboutlibraries) apply false
|
||||
alias(libs.plugins.hilt) apply false
|
||||
alias(libs.plugins.protobuf) apply false
|
||||
alias(libs.plugins.kotlinxSerialization) apply false
|
||||
}
|
||||
@@ -4,6 +4,7 @@ kotlin = "1.9.23"
|
||||
ksp = "1.9.23-1.0.20"
|
||||
aboutlibraries = "11.1.0"
|
||||
protobufPlugin = "0.9.4"
|
||||
kotlinxSerialization = "1.9.23"
|
||||
|
||||
desugarJdkLibs = "2.0.4"
|
||||
composeBom = "2024.04.01"
|
||||
@@ -22,6 +23,7 @@ androidxDataStore = "1.1.0"
|
||||
protobuf = "3.25.2"
|
||||
androidxNavigation = "2.7.7"
|
||||
androidxHiltNavigationCompose = "1.2.0"
|
||||
kotlinxSerializationJson = "1.6.3"
|
||||
|
||||
[plugins]
|
||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||
@@ -30,6 +32,7 @@ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||
aboutlibraries = {id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutlibraries"}
|
||||
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
|
||||
protobuf = { id = "com.google.protobuf", version.ref = "protobufPlugin" }
|
||||
kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinxSerialization" }
|
||||
|
||||
[libraries]
|
||||
desugar-jdk-libs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "desugarJdkLibs"}
|
||||
@@ -73,3 +76,4 @@ protobuf-protoc = { group = "com.google.protobuf", name = "protoc", version.ref
|
||||
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "androidxNavigation" }
|
||||
androidx-navigation-testing = { group = "androidx.navigation", name = "navigation-testing", version.ref = "androidxNavigation" }
|
||||
androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "androidxHiltNavigationCompose" }
|
||||
kotlinx-serialization-json = {group="org.jetbrains.kotlinx", name="kotlinx-serialization-json", version.ref = "kotlinxSerializationJson"}
|
||||
|
||||
Reference in New Issue
Block a user