mirror of
https://github.com/InsanusMokrassar/KotlinPublicationScriptsBuilder.git
synced 2024-11-23 18:48:51 +00:00
partially go over with compose
This commit is contained in:
parent
283bc5acb4
commit
70baa30127
@ -7,10 +7,10 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.2'
|
classpath libs.buildscript.kt.gradle
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath libs.buildscript.kt.serialization
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath libs.buildscript.jb.dokka
|
||||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
|
classpath libs.buildscript.gh.release
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "org.jetbrains.kotlin.multiplatform"
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
id "org.jetbrains.kotlin.plugin.serialization"
|
id "org.jetbrains.kotlin.plugin.serialization"
|
||||||
|
alias(libs.plugins.jb.compose)
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$mppProjectWithSerializationPresetPath"
|
apply from: "$mppProjectWithSerializationPresetPath"
|
||||||
@ -9,10 +10,16 @@ kotlin {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
api libs.kt.coroutines
|
||||||
api "dev.inmo:micro_utils.coroutines:$micro_utils_version"
|
api libs.microutils.common
|
||||||
|
api libs.microutils.coroutines
|
||||||
api "io.ktor:ktor-client-core:$ktor_version"
|
api libs.ktor.client
|
||||||
|
api(compose.runtime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jvmMain {
|
||||||
|
dependencies {
|
||||||
|
implementation(compose.desktop.currentOs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
expect object BuilderViewDrawer : Drawer<BuilderView>
|
||||||
|
|
||||||
|
class BuilderView : View() {
|
||||||
|
internal val projectTypeView = ProjectTypeView()
|
||||||
|
internal val mavenInfoView = MavenInfoView()
|
||||||
|
internal val licensesView = LicensesView()
|
||||||
|
|
||||||
|
internal var saveAvailableState by mutableStateOf(false)
|
||||||
|
var config: Config
|
||||||
|
get() = Config(licensesView.licenses, mavenInfoView.mavenConfig, projectTypeView.projectType)
|
||||||
|
set(value) {
|
||||||
|
licensesView.licenses = value.licenses
|
||||||
|
mavenInfoView.mavenConfig = value.mavenConfig
|
||||||
|
projectTypeView.projectType = value.type
|
||||||
|
saveAvailableState = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun build() {
|
||||||
|
with(BuilderViewDrawer) { draw() }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.Developer
|
||||||
|
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonTextField
|
||||||
|
|
||||||
|
class DeveloperState(
|
||||||
|
id: String = "",
|
||||||
|
name: String = "",
|
||||||
|
eMail: String = ""
|
||||||
|
) {
|
||||||
|
var id: String by mutableStateOf(id)
|
||||||
|
var name: String by mutableStateOf(name)
|
||||||
|
var eMail: String by mutableStateOf(eMail)
|
||||||
|
|
||||||
|
fun toDeveloper() = Developer(id, name, eMail)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Developer.toDeveloperState() = DeveloperState(id, name, eMail)
|
||||||
|
|
||||||
|
class DevelopersView : ListView<DeveloperState>("Developers info") {
|
||||||
|
var developers = mutableStateListOf<Developer>()
|
||||||
|
|
||||||
|
override val addItemText: String = "Add developer"
|
||||||
|
override val removeItemText: String = "Remove developer"
|
||||||
|
|
||||||
|
override fun createItem(): DeveloperState = DeveloperState()
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.License
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
|
||||||
|
private class LicenseState(
|
||||||
|
id: String = "",
|
||||||
|
title: String = "",
|
||||||
|
url: String? = null
|
||||||
|
) {
|
||||||
|
var id: String by mutableStateOf(id)
|
||||||
|
var title: String by mutableStateOf(title)
|
||||||
|
var url: String? by mutableStateOf(url)
|
||||||
|
|
||||||
|
fun toLicense() = License(id, title, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun License.toLicenseState() = LicenseState(id, title, url)
|
||||||
|
|
||||||
|
class LicensesView: VerticalView("Licenses") {
|
||||||
|
private var licensesListState = mutableStateListOf<LicenseState>()
|
||||||
|
var licenses: List<License>
|
||||||
|
get() = licensesListState.map { it.toLicense() }
|
||||||
|
set(value) {
|
||||||
|
licensesListState.clear()
|
||||||
|
licensesListState.addAll(value.map { it.toLicenseState() })
|
||||||
|
}
|
||||||
|
private val availableLicensesState = mutableStateListOf<License>()
|
||||||
|
private val licensesOffersToShow = mutableStateListOf<License>()
|
||||||
|
private var licenseSearchFilter by mutableStateOf("")
|
||||||
|
|
||||||
|
init {
|
||||||
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
|
val client = HttpClient()
|
||||||
|
availableLicensesState.addAll(client.getLicenses().values)
|
||||||
|
client.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val content: @Composable ColumnScope.() -> Unit = {
|
||||||
|
CommonTextField(licenseSearchFilter, "Search filter") { filterText ->
|
||||||
|
licenseSearchFilter = filterText
|
||||||
|
licensesOffersToShow.clear()
|
||||||
|
if (licenseSearchFilter.isNotEmpty()) {
|
||||||
|
licensesOffersToShow.addAll(
|
||||||
|
availableLicensesState.filter { filterText.all { symbol -> symbol.lowercaseChar() in it.title } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
licensesOffersToShow.forEach {
|
||||||
|
Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
|
||||||
|
CommonText(it.title, Modifier.clickable {
|
||||||
|
licensesListState.add(it.toLicenseState())
|
||||||
|
licenseSearchFilter = ""
|
||||||
|
licensesOffersToShow.clear()
|
||||||
|
})
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button({ licensesListState.add(LicenseState()) }, Modifier.padding(8.dp)) {
|
||||||
|
CommonText("Add empty license")
|
||||||
|
}
|
||||||
|
licensesListState.forEach { license ->
|
||||||
|
Column(Modifier.padding(8.dp)) {
|
||||||
|
CommonTextField(
|
||||||
|
license.id,
|
||||||
|
"License ID"
|
||||||
|
) { license.id = it }
|
||||||
|
CommonTextField(
|
||||||
|
license.title,
|
||||||
|
"License title"
|
||||||
|
) { license.title = it }
|
||||||
|
CommonTextField(
|
||||||
|
license.url ?: "",
|
||||||
|
"License URL"
|
||||||
|
) { license.url = it }
|
||||||
|
Button({ licensesListState.remove(license) }, Modifier.padding(8.dp)) {
|
||||||
|
CommonText("Remove")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
expect class ListViewDrawer<T>() : Drawer<ListView<T>>
|
||||||
|
|
||||||
|
abstract class ListView<T>(protected val title: String) : View() {
|
||||||
|
internal val itemsList = mutableStateListOf<T>()
|
||||||
|
|
||||||
|
internal open val addItemText: String = "Add"
|
||||||
|
internal open val removeItemText: String = "Remove"
|
||||||
|
|
||||||
|
internal abstract fun createItem(): T
|
||||||
|
@Composable
|
||||||
|
internal abstract fun buildView(item: T)
|
||||||
|
|
||||||
|
protected val drawer = ListViewDrawer<T>()
|
||||||
|
|
||||||
|
override fun build() {
|
||||||
|
DrawVertically(title) {
|
||||||
|
with(drawer) { draw() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.layout.VerticalAlignmentLine
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.*
|
||||||
|
import dev.inmo.kmppscriptbuilder.desktop.utils.*
|
||||||
|
|
||||||
|
class MavenInfoView : VerticalView("Project information") {
|
||||||
|
private var projectNameProperty by mutableStateOf("")
|
||||||
|
private var projectDescriptionProperty by mutableStateOf("")
|
||||||
|
private var projectUrlProperty by mutableStateOf("")
|
||||||
|
private var projectVcsUrlProperty by mutableStateOf("")
|
||||||
|
private var gpgSignProperty by mutableStateOf<GpgSigning>(GpgSigning.Disabled)
|
||||||
|
private var publishToMavenCentralProperty by mutableStateOf(false)
|
||||||
|
private val developersView = DevelopersView()
|
||||||
|
private val repositoriesView = RepositoriesView()
|
||||||
|
|
||||||
|
var mavenConfig: MavenConfig
|
||||||
|
get() = MavenConfig(
|
||||||
|
projectNameProperty.ifBlank { defaultProjectName },
|
||||||
|
projectDescriptionProperty.ifBlank { defaultProjectDescription },
|
||||||
|
projectUrlProperty,
|
||||||
|
projectVcsUrlProperty,
|
||||||
|
developersView.developers,
|
||||||
|
repositoriesView.repositories + if (publishToMavenCentralProperty) {
|
||||||
|
listOf(SonatypeRepository)
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
},
|
||||||
|
gpgSignProperty
|
||||||
|
)
|
||||||
|
set(value) {
|
||||||
|
projectNameProperty = value.name
|
||||||
|
projectDescriptionProperty = value.description
|
||||||
|
projectUrlProperty = value.url
|
||||||
|
projectVcsUrlProperty = value.vcsUrl
|
||||||
|
gpgSignProperty = if (value.includeGpgSigning) {
|
||||||
|
GpgSigning.Enabled
|
||||||
|
} else {
|
||||||
|
value.gpgSigning
|
||||||
|
}
|
||||||
|
publishToMavenCentralProperty = value.repositories.any { it == SonatypeRepository }
|
||||||
|
developersView.developers = value.developers
|
||||||
|
repositoriesView.repositories = value.repositories.filter { it != SonatypeRepository }
|
||||||
|
// developersView.developers = value.developers
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun addGpgSigningButton(gpgSigning: GpgSigning) {
|
||||||
|
if (gpgSignProperty == gpgSigning) {
|
||||||
|
Button({}, Modifier.padding(8.dp)) {
|
||||||
|
Text(gpgSigning.name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OutlinedButton(
|
||||||
|
{
|
||||||
|
gpgSignProperty = gpgSigning
|
||||||
|
},
|
||||||
|
Modifier.padding(8.dp)
|
||||||
|
) {
|
||||||
|
Text(gpgSigning.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val content: @Composable ColumnScope.() -> Unit = {
|
||||||
|
CommonTextField(
|
||||||
|
projectNameProperty,
|
||||||
|
"Public project name"
|
||||||
|
) { projectNameProperty = it }
|
||||||
|
CommonTextField(
|
||||||
|
projectDescriptionProperty,
|
||||||
|
"Public project description"
|
||||||
|
) { projectDescriptionProperty = it }
|
||||||
|
CommonTextField(
|
||||||
|
projectUrlProperty,
|
||||||
|
"Public project URL"
|
||||||
|
) { projectUrlProperty = it }
|
||||||
|
CommonTextField(
|
||||||
|
projectVcsUrlProperty,
|
||||||
|
"Public project VCS URL (with .git)"
|
||||||
|
) { projectVcsUrlProperty = it }
|
||||||
|
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text("Gpg Signing: ")
|
||||||
|
addGpgSigningButton(GpgSigning.Disabled)
|
||||||
|
addGpgSigningButton(GpgSigning.Optional)
|
||||||
|
addGpgSigningButton(GpgSigning.Enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
SwitchWithLabel(
|
||||||
|
"Include publication to MavenCentral",
|
||||||
|
publishToMavenCentralProperty,
|
||||||
|
placeSwitchAtTheStart = true
|
||||||
|
) { publishToMavenCentralProperty = it }
|
||||||
|
developersView.init()
|
||||||
|
repositoriesView.init()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.material.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.*
|
||||||
|
import dev.inmo.kmppscriptbuilder.desktop.utils.VerticalView
|
||||||
|
|
||||||
|
class ProjectTypeView : VerticalView("Project type") {
|
||||||
|
var projectType by mutableStateOf<ProjectType>(MultiplatformProjectType)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun addProjectTypeButton(newProjectType: ProjectType) {
|
||||||
|
if (projectType == newProjectType) {
|
||||||
|
Button({}, Modifier.padding(8.dp)) {
|
||||||
|
Text(newProjectType.name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OutlinedButton(
|
||||||
|
{
|
||||||
|
projectType = newProjectType
|
||||||
|
},
|
||||||
|
Modifier.padding(8.dp)
|
||||||
|
) {
|
||||||
|
Text(newProjectType.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val content: @Composable ColumnScope.() -> Unit = {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
addProjectTypeButton(MultiplatformProjectType)
|
||||||
|
addProjectTypeButton(JVMProjectType)
|
||||||
|
addProjectTypeButton(JSProjectType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
||||||
|
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonTextField
|
||||||
|
|
||||||
|
class RepositoryState(
|
||||||
|
name: String = "",
|
||||||
|
url: String = ""
|
||||||
|
) {
|
||||||
|
var name: String by mutableStateOf(name)
|
||||||
|
var url: String by mutableStateOf(url)
|
||||||
|
|
||||||
|
fun toRepository() = MavenPublishingRepository(name, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun MavenPublishingRepository.toRepositoryState() = RepositoryState(name, url)
|
||||||
|
|
||||||
|
class RepositoriesView : ListView<RepositoryState>("Repositories info") {
|
||||||
|
var repositories: List<MavenPublishingRepository>
|
||||||
|
get() = itemsList.map { it.toRepository() }
|
||||||
|
set(value) {
|
||||||
|
itemsList.clear()
|
||||||
|
itemsList.addAll(
|
||||||
|
value.map { it.toRepositoryState() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val addItemText: String = "Add repository"
|
||||||
|
override val removeItemText: String = "Remove repository"
|
||||||
|
|
||||||
|
override fun createItem(): RepositoryState = RepositoryState()
|
||||||
|
@Composable
|
||||||
|
override fun buildView(item: RepositoryState) {
|
||||||
|
CommonTextField(
|
||||||
|
item.name,
|
||||||
|
"Repository name"
|
||||||
|
) { item.name = it }
|
||||||
|
CommonTextField(
|
||||||
|
item.url,
|
||||||
|
"Repository url"
|
||||||
|
) { item.url = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
expect abstract class View() {
|
||||||
|
@Composable
|
||||||
|
abstract fun build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun View.DrawVertically(title: String, block: @Composable () -> Unit)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun <T : View> T.init(): T = apply {
|
||||||
|
build()
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
interface Drawer<T> {
|
||||||
|
@Composable
|
||||||
|
fun T.draw()
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun TitleText(text: String)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun CommonText(text: String)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun CommonTextField(presetText: String, hint: String, onChange: (String) -> Unit)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun SwitchWithLabel(
|
||||||
|
label: String,
|
||||||
|
checked: Boolean,
|
||||||
|
placeSwitchAtTheStart: Boolean = false,
|
||||||
|
switchEnabled: Boolean = true,
|
||||||
|
onCheckedChange: (Boolean) -> Unit
|
||||||
|
)
|
@ -0,0 +1,23 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
|
import dev.inmo.micro_utils.common.MPPFile
|
||||||
|
|
||||||
|
internal const val appExtension = "kpsb"
|
||||||
|
|
||||||
|
private var lastFile: MPPFile? = null
|
||||||
|
|
||||||
|
fun loadConfigFile(file: MPPFile): Config {
|
||||||
|
lastFile = file
|
||||||
|
return serialFormat.decodeFromString(Config.serializer(), file.text())
|
||||||
|
}
|
||||||
|
|
||||||
|
expect fun MPPFile.text(): String
|
||||||
|
|
||||||
|
expect fun loadConfig(): Config?
|
||||||
|
|
||||||
|
expect fun saveConfig(config: Config): Boolean
|
||||||
|
|
||||||
|
expect fun exportGradle(config: Config): Boolean
|
||||||
|
|
||||||
|
expect fun saveAs(config: Config): Boolean
|
@ -0,0 +1,3 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
|
expect fun openLink(link: String): Boolean
|
@ -0,0 +1,12 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
actual abstract class View {
|
||||||
|
@Composable
|
||||||
|
actual abstract fun build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun View.DrawVertically(title: String, block: @Composable () -> Unit) {
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Divider
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.TopAppBar
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.exportGradle
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.loadConfig
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.saveAs
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.saveConfig
|
||||||
|
|
||||||
|
actual object BuilderViewDrawer : Drawer<BuilderView> {
|
||||||
|
override fun BuilderView.draw() {
|
||||||
|
Box(Modifier.fillMaxSize()) {
|
||||||
|
Column() {
|
||||||
|
TopAppBar(
|
||||||
|
@Composable {
|
||||||
|
Text("Kotlin publication scripts builder", Modifier.clickable { println(config) })
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
createIcon("Open file", "images/open_file.svg") {
|
||||||
|
loadConfig()?.also {
|
||||||
|
config = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveAvailableState) {
|
||||||
|
createIcon("Save", "images/save_file.svg") {
|
||||||
|
saveConfig(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveAvailableState) {
|
||||||
|
createIcon("Export Gradle script", "images/export_gradle.svg") {
|
||||||
|
exportGradle(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createIcon("Save as", "images/save_as.svg") {
|
||||||
|
if (saveAs(config)) {
|
||||||
|
saveAvailableState = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Column(Modifier.padding(8.dp)) {
|
||||||
|
projectTypeView.init()
|
||||||
|
Divider()
|
||||||
|
licensesView.init()
|
||||||
|
Divider()
|
||||||
|
mavenInfoView.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Button
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||||
|
|
||||||
|
actual class ListViewDrawer<T> : Drawer<ListView<T>> {
|
||||||
|
override fun ListView<T>.draw() {
|
||||||
|
Button({ itemsList.add(createItem()) }) {
|
||||||
|
CommonText(addItemText)
|
||||||
|
}
|
||||||
|
itemsList.forEach { item ->
|
||||||
|
Column(Modifier.padding(8.dp)) {
|
||||||
|
buildView(item)
|
||||||
|
Button({ itemsList.remove(item) }, Modifier.padding(8.dp)) {
|
||||||
|
CommonText(removeItemText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
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.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.TitleText
|
||||||
|
|
||||||
|
actual abstract class View {
|
||||||
|
internal open val defaultModifier = Modifier.fillMaxWidth().padding(8.dp)
|
||||||
|
@Composable
|
||||||
|
actual abstract fun build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun View.DrawVertically(
|
||||||
|
title: String,
|
||||||
|
block: @Composable () -> Unit
|
||||||
|
) {
|
||||||
|
TitleText(title)
|
||||||
|
|
||||||
|
Column(defaultModifier) {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(Modifier.fillMaxWidth().height(8.dp))
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.OutlinedTextField
|
||||||
|
import androidx.compose.material.Switch
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
|
||||||
|
val commonTextFieldTextStyle = TextStyle(
|
||||||
|
fontSize = 12.sp
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun SwitchWithLabel(
|
||||||
|
label: String,
|
||||||
|
checked: Boolean,
|
||||||
|
placeSwitchAtTheStart: Boolean,
|
||||||
|
switchEnabled: Boolean,
|
||||||
|
onCheckedChange: (Boolean) -> Unit
|
||||||
|
) {
|
||||||
|
Row(Modifier.padding(0.dp, 8.dp), Arrangement.Start, Alignment.Top) {
|
||||||
|
val switchCreator = @Composable {
|
||||||
|
Switch(checked, onCheckedChange, Modifier.padding(8.dp, 0.dp), enabled = switchEnabled)
|
||||||
|
}
|
||||||
|
if (placeSwitchAtTheStart) {
|
||||||
|
switchCreator()
|
||||||
|
}
|
||||||
|
Box(Modifier.fillMaxWidth().align(Alignment.CenterVertically).clickable { }) {
|
||||||
|
CommonText(label)
|
||||||
|
}
|
||||||
|
if (!placeSwitchAtTheStart) {
|
||||||
|
switchCreator()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun CommonTextField(presetText: String, hint: String, onChange: (String) -> Unit) {
|
||||||
|
OutlinedTextField(
|
||||||
|
presetText,
|
||||||
|
onChange,
|
||||||
|
Modifier.fillMaxWidth(),
|
||||||
|
singleLine = true,
|
||||||
|
label = {
|
||||||
|
CommonText(hint)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun CommonText(text: String) {
|
||||||
|
Text(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun TitleText(text: String) {
|
||||||
|
Text(
|
||||||
|
text, Modifier.padding(0.dp, 8.dp), fontSize = 18.sp
|
||||||
|
)
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
|
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.swing.filechooser.FileFilter
|
import javax.swing.filechooser.FileFilter
|
@ -0,0 +1,80 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
||||||
|
import dev.inmo.micro_utils.common.MPPFile
|
||||||
|
import java.io.File
|
||||||
|
import javax.swing.JFileChooser
|
||||||
|
|
||||||
|
private const val appExtension = "kpsb"
|
||||||
|
|
||||||
|
private var lastFile: File? = null
|
||||||
|
|
||||||
|
fun loadConfigFile(file: File): Config {
|
||||||
|
lastFile = file
|
||||||
|
return serialFormat.decodeFromString(Config.serializer(), file.readText())
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun MPPFile.text() = readText()
|
||||||
|
|
||||||
|
actual fun loadConfig(): Config? {
|
||||||
|
val fc = JFileChooser(lastFile ?.parent)
|
||||||
|
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
||||||
|
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
|
||||||
|
return when (fc.showOpenDialog(null)) {
|
||||||
|
JFileChooser.APPROVE_OPTION -> {
|
||||||
|
val file = fc.selectedFile
|
||||||
|
lastFile = file
|
||||||
|
return serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText())
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun saveConfig(config: Config): Boolean {
|
||||||
|
return lastFile ?.also {
|
||||||
|
it.writeText(serialFormat.encodeToString(Config.serializer(), config))
|
||||||
|
} != null
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun exportGradle(config: Config): Boolean {
|
||||||
|
val fc = JFileChooser(lastFile ?.parent)
|
||||||
|
fc.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
|
||||||
|
return when (fc.showSaveDialog(null)) {
|
||||||
|
JFileChooser.APPROVE_OPTION -> {
|
||||||
|
val file = fc.selectedFile
|
||||||
|
val mavenConfigContent = config.type.buildMavenGradleConfig(
|
||||||
|
config.mavenConfig,
|
||||||
|
config.licenses
|
||||||
|
)
|
||||||
|
File(file, "publish.gradle").apply {
|
||||||
|
delete()
|
||||||
|
createNewFile()
|
||||||
|
writeText(mavenConfigContent)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun saveAs(config: Config): Boolean {
|
||||||
|
val fc = JFileChooser(lastFile ?.parent)
|
||||||
|
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
|
||||||
|
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
|
||||||
|
return when (fc.showSaveDialog(null)) {
|
||||||
|
JFileChooser.APPROVE_OPTION -> {
|
||||||
|
val file = fc.selectedFile
|
||||||
|
val resultFile = if (file.extension == "") {
|
||||||
|
File(file.parentFile, "${file.name}.$appExtension")
|
||||||
|
} else {
|
||||||
|
file
|
||||||
|
}
|
||||||
|
resultFile.writeText(serialFormat.encodeToString(Config.serializer(), config))
|
||||||
|
lastFile = resultFile
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
||||||
import java.awt.Desktop
|
import java.awt.Desktop
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
fun openLink(link: String): Boolean {
|
actual fun openLink(link: String): Boolean {
|
||||||
val desktop = if (Desktop.isDesktopSupported()) Desktop.getDesktop() else null
|
val desktop = if (Desktop.isDesktopSupported()) Desktop.getDesktop() else null
|
||||||
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||||
try {
|
try {
|
@ -0,0 +1,2 @@
|
|||||||
|
package dev.inmo.kmppscriptbuilder.core.utils
|
||||||
|
|
@ -1,17 +1,13 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "org.jetbrains.kotlin.multiplatform"
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
id "org.jetbrains.kotlin.plugin.serialization"
|
id "org.jetbrains.kotlin.plugin.serialization"
|
||||||
id("org.jetbrains.compose") version "$compose_version"
|
alias(libs.plugins.jb.compose)
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$mppJavaProjectPresetPath"
|
apply from: "$mppJavaProjectPresetPath"
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvm {
|
jvm()
|
||||||
compilations.main.kotlinOptions {
|
|
||||||
jvmTarget = "11"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -22,7 +18,7 @@ kotlin {
|
|||||||
jvmMain {
|
jvmMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(compose.desktop.currentOs)
|
implementation(compose.desktop.currentOs)
|
||||||
api "io.ktor:ktor-client-cio:$ktor_version"
|
implementation libs.ktor.client.cio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
|
package dev.inmo.kmppscriptbuilder.desktop.utils
|
||||||
|
|
||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||||
|
import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
|
||||||
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.swing.JFileChooser
|
import javax.swing.JFileChooser
|
||||||
|
@ -3,14 +3,12 @@ org.gradle.parallel=true
|
|||||||
kotlin.js.generate.externals=true
|
kotlin.js.generate.externals=true
|
||||||
kotlin.incremental=true
|
kotlin.incremental=true
|
||||||
kotlin.incremental.js=true
|
kotlin.incremental.js=true
|
||||||
android.useAndroidX=true
|
|
||||||
android.enableJetifier=true
|
|
||||||
|
|
||||||
kotlin_version=1.7.20
|
kotlin_version=1.7.20
|
||||||
kotlin_coroutines_version=1.6.4
|
kotlin_coroutines_version=1.6.4
|
||||||
kotlin_serialisation_core_version=1.4.1
|
kotlin_serialisation_core_version=1.4.1
|
||||||
ktor_version=2.1.3
|
ktor_version=2.1.3
|
||||||
micro_utils_version=0.14.1
|
micro_utils_version=0.14.2
|
||||||
|
|
||||||
compose_version=1.2.1
|
compose_version=1.2.1
|
||||||
|
|
||||||
|
41
gradle/libs.versions.toml
Normal file
41
gradle/libs.versions.toml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
[versions]
|
||||||
|
|
||||||
|
kt = "1.7.20"
|
||||||
|
kt-serialization = "1.4.1"
|
||||||
|
kt-coroutines = "1.6.4"
|
||||||
|
|
||||||
|
jb-compose = "1.2.1"
|
||||||
|
jb-dokka = "1.7.20"
|
||||||
|
microutils = "0.14.2"
|
||||||
|
|
||||||
|
ktor = "2.1.3"
|
||||||
|
|
||||||
|
gh-release = "2.4.1"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
|
||||||
|
kt-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kt" }
|
||||||
|
|
||||||
|
kt-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kt-serialization" }
|
||||||
|
|
||||||
|
kt-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kt-coroutines" }
|
||||||
|
|
||||||
|
ktor-client = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
|
||||||
|
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
|
||||||
|
|
||||||
|
microutils-common = { module = "dev.inmo:micro_utils.common", version.ref = "microutils" }
|
||||||
|
microutils-coroutines = { module = "dev.inmo:micro_utils.coroutines", version.ref = "microutils" }
|
||||||
|
|
||||||
|
|
||||||
|
kt-test-js = { module = "org.jetbrains.kotlin:kotlin-test-js", version.ref = "kt" }
|
||||||
|
kt-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kt" }
|
||||||
|
|
||||||
|
|
||||||
|
buildscript-kt-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kt" }
|
||||||
|
buildscript-kt-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kt" }
|
||||||
|
buildscript-jb-dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "jb-dokka" }
|
||||||
|
buildscript-gh-release = { module = "com.github.breadmoirai:github-release", version.ref = "gh-release" }
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
|
||||||
|
jb-compose = { id = "org.jetbrains.compose", version.ref = "jb-compose" }
|
Loading…
Reference in New Issue
Block a user