mirror of
https://github.com/InsanusMokrassar/KotlinPublicationScriptsBuilder.git
synced 2024-11-27 12:38:54 +00:00
partially go over with compose
This commit is contained in:
parent
283bc5acb4
commit
70baa30127
@ -7,10 +7,10 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.2.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
|
||||
classpath libs.buildscript.kt.gradle
|
||||
classpath libs.buildscript.kt.serialization
|
||||
classpath libs.buildscript.jb.dokka
|
||||
classpath libs.buildscript.gh.release
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
alias(libs.plugins.jb.compose)
|
||||
}
|
||||
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
@ -9,10 +10,16 @@ kotlin {
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||
api "dev.inmo:micro_utils.coroutines:$micro_utils_version"
|
||||
|
||||
api "io.ktor:ktor-client-core:$ktor_version"
|
||||
api libs.kt.coroutines
|
||||
api libs.microutils.common
|
||||
api libs.microutils.coroutines
|
||||
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 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.net.URI
|
||||
|
||||
fun openLink(link: String): Boolean {
|
||||
actual fun openLink(link: String): Boolean {
|
||||
val desktop = if (Desktop.isDesktopSupported()) Desktop.getDesktop() else null
|
||||
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||
try {
|
@ -0,0 +1,2 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.utils
|
||||
|
@ -1,17 +1,13 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id("org.jetbrains.compose") version "$compose_version"
|
||||
alias(libs.plugins.jb.compose)
|
||||
}
|
||||
|
||||
apply from: "$mppJavaProjectPresetPath"
|
||||
|
||||
kotlin {
|
||||
jvm {
|
||||
compilations.main.kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
}
|
||||
jvm()
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
@ -22,7 +18,7 @@ kotlin {
|
||||
jvmMain {
|
||||
dependencies {
|
||||
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
|
||||
|
||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
|
||||
import java.io.File
|
||||
import javax.swing.JFileChooser
|
||||
|
@ -3,14 +3,12 @@ org.gradle.parallel=true
|
||||
kotlin.js.generate.externals=true
|
||||
kotlin.incremental=true
|
||||
kotlin.incremental.js=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
kotlin_version=1.7.20
|
||||
kotlin_coroutines_version=1.6.4
|
||||
kotlin_serialisation_core_version=1.4.1
|
||||
ktor_version=2.1.3
|
||||
micro_utils_version=0.14.1
|
||||
micro_utils_version=0.14.2
|
||||
|
||||
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