mirror of
https://github.com/InsanusMokrassar/KotlinPublicationScriptsBuilder.git
synced 2025-09-03 06:59:17 +00:00
total rework
This commit is contained in:
@@ -7,6 +7,9 @@ plugins {
|
||||
apply from: "$mppProjectWithSerializationPresetPath"
|
||||
|
||||
kotlin {
|
||||
js (IR) {
|
||||
binaries.executable()
|
||||
}
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
@@ -17,10 +20,27 @@ kotlin {
|
||||
api(compose.runtime)
|
||||
}
|
||||
}
|
||||
jsMain {
|
||||
dependencies {
|
||||
implementation(compose.web.core)
|
||||
api libs.ktor.client.js
|
||||
api libs.jsuikit
|
||||
}
|
||||
}
|
||||
jvmMain {
|
||||
dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
api libs.ktor.client.cio
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
compose {
|
||||
desktop {
|
||||
application {
|
||||
mainClass = "dev.inmo.kmppscriptbuilder.desktop.BuilderKt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,18 +5,26 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultDivider
|
||||
|
||||
expect object BuilderViewDrawer : Drawer<BuilderView>
|
||||
@Composable
|
||||
expect fun TopAppBar(
|
||||
config: Config,
|
||||
saveAvailable: Boolean,
|
||||
onSaveAvailable: (Boolean) -> Unit,
|
||||
onNewConfig: (Config) -> Unit
|
||||
)
|
||||
|
||||
class BuilderView : View() {
|
||||
internal val projectTypeView = ProjectTypeView()
|
||||
internal val mavenInfoView = MavenInfoView()
|
||||
internal val licensesView = LicensesView()
|
||||
internal val projectTypeView by mutableStateOf(ProjectTypeView())
|
||||
internal val mavenInfoView by mutableStateOf(MavenInfoView())
|
||||
internal val licensesView by mutableStateOf(LicensesView())
|
||||
|
||||
internal var saveAvailableState by mutableStateOf(false)
|
||||
var config: Config
|
||||
get() = Config(licensesView.licenses, mavenInfoView.mavenConfig, projectTypeView.projectType)
|
||||
get() {
|
||||
return Config(licensesView.licenses, mavenInfoView.mavenConfig, projectTypeView.projectType)
|
||||
}
|
||||
set(value) {
|
||||
licensesView.licenses = value.licenses
|
||||
mavenInfoView.mavenConfig = value.mavenConfig
|
||||
@@ -26,6 +34,20 @@ class BuilderView : View() {
|
||||
|
||||
@Composable
|
||||
override fun build() {
|
||||
with(BuilderViewDrawer) { draw() }
|
||||
TopAppBar(
|
||||
config,
|
||||
saveAvailableState,
|
||||
{
|
||||
saveAvailableState = it
|
||||
}
|
||||
) {
|
||||
config = it
|
||||
}
|
||||
|
||||
projectTypeView.build()
|
||||
DefaultDivider()
|
||||
licensesView.build()
|
||||
DefaultDivider()
|
||||
mavenInfoView.build()
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,12 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import dev.inmo.kmppscriptbuilder.core.models.Developer
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||
|
||||
class DeveloperState(
|
||||
id: String = "",
|
||||
@@ -21,11 +23,32 @@ class DeveloperState(
|
||||
private fun Developer.toDeveloperState() = DeveloperState(id, name, eMail)
|
||||
|
||||
class DevelopersView : ListView<DeveloperState>("Developers info") {
|
||||
var developers = mutableStateListOf<Developer>()
|
||||
var developers: List<Developer>
|
||||
get() = itemsList.map { it.toDeveloper() }
|
||||
set(value) {
|
||||
itemsList.apply {
|
||||
clear()
|
||||
addAll(value.map { it.toDeveloperState() })
|
||||
}
|
||||
}
|
||||
|
||||
override val addItemText: String = "Add developer"
|
||||
override val removeItemText: String = "Remove developer"
|
||||
|
||||
override fun createItem(): DeveloperState = DeveloperState()
|
||||
|
||||
@Composable
|
||||
override fun buildView(item: DeveloperState) {
|
||||
CommonTextField(
|
||||
item.id,
|
||||
"Developer username",
|
||||
) { item.id = it }
|
||||
CommonTextField(
|
||||
item.name,
|
||||
"Developer name",
|
||||
) { item.name = it }
|
||||
CommonTextField(
|
||||
item.eMail,
|
||||
"Developer E-Mail",
|
||||
) { item.eMail = it }
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,15 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import dev.inmo.kmppscriptbuilder.core.models.License
|
||||
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
import io.ktor.client.HttpClient
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -38,8 +41,14 @@ class LicensesView: VerticalView("Licenses") {
|
||||
licensesListState.addAll(value.map { it.toLicenseState() })
|
||||
}
|
||||
internal val availableLicensesState = mutableStateListOf<License>()
|
||||
internal val licensesOffersToShow = mutableStateListOf<License>()
|
||||
internal var licenseSearchFilter by mutableStateOf("")
|
||||
internal val searchFieldFocused = mutableStateOf(false)
|
||||
internal val licensesOffersToShow = derivedStateOf {
|
||||
val query = licenseSearchFilter.lowercase()
|
||||
availableLicensesState.filter {
|
||||
it.title.lowercase().contains(query)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
CoroutineScope(Dispatchers.Default).launch {
|
||||
@@ -50,6 +59,16 @@ class LicensesView: VerticalView("Licenses") {
|
||||
}
|
||||
|
||||
override val content: @Composable () -> Unit = {
|
||||
CommonTextField(
|
||||
licenseSearchFilter,
|
||||
"Search filter",
|
||||
onFocusChanged = {
|
||||
searchFieldFocused.value = it
|
||||
}
|
||||
) { filterText ->
|
||||
licenseSearchFilter = filterText
|
||||
}
|
||||
|
||||
with(LicensesDrawer) { draw() }
|
||||
}
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ abstract class ListView<T>(title: String) : VerticalView(title) {
|
||||
|
||||
protected val drawer = ListViewDrawer<T>()
|
||||
|
||||
override val content: () -> Unit = {
|
||||
override val content: @Composable () -> Unit = {
|
||||
with(drawer) {
|
||||
draw()
|
||||
}
|
||||
|
@@ -2,9 +2,17 @@ package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
|
||||
import dev.inmo.kmppscriptbuilder.core.models.MavenConfig
|
||||
import dev.inmo.kmppscriptbuilder.core.models.SonatypeRepository
|
||||
import dev.inmo.kmppscriptbuilder.core.models.defaultProjectDescription
|
||||
import dev.inmo.kmppscriptbuilder.core.models.defaultProjectName
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.ButtonsPanel
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.SwitchWithLabel
|
||||
|
||||
expect object MavenInfoDrawer : Drawer<MavenInfoView>
|
||||
expect class GpgSigningOptionDrawer : Drawer<GpgSigning>
|
||||
expect fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer
|
||||
|
||||
class MavenInfoView : VerticalView("Project information") {
|
||||
internal var projectNameProperty by mutableStateOf("")
|
||||
@@ -43,10 +51,46 @@ class MavenInfoView : VerticalView("Project information") {
|
||||
publishToMavenCentralProperty = value.repositories.any { it == SonatypeRepository }
|
||||
developersView.developers = value.developers
|
||||
repositoriesView.repositories = value.repositories.filter { it != SonatypeRepository }
|
||||
// developersView.developers = value.developers
|
||||
}
|
||||
|
||||
private val gpgSigningDrawer = GpgSigningOptionDrawerWithView(this)
|
||||
|
||||
override val content: @Composable () -> Unit = {
|
||||
with (MavenInfoDrawer) { draw() }
|
||||
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 }
|
||||
|
||||
ButtonsPanel(
|
||||
GpgSigning.Disabled,
|
||||
GpgSigning.Optional,
|
||||
GpgSigning.Enabled
|
||||
) {
|
||||
with(gpgSigningDrawer) {
|
||||
with (it) {
|
||||
draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SwitchWithLabel(
|
||||
"Include publication to MavenCentral",
|
||||
publishToMavenCentralProperty,
|
||||
placeSwitchAtTheStart = true
|
||||
) { publishToMavenCentralProperty = it }
|
||||
developersView.build()
|
||||
repositoriesView.build()
|
||||
}
|
||||
}
|
||||
|
@@ -4,16 +4,31 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import dev.inmo.kmppscriptbuilder.core.models.JSProjectType
|
||||
import dev.inmo.kmppscriptbuilder.core.models.JVMProjectType
|
||||
import dev.inmo.kmppscriptbuilder.core.models.MultiplatformProjectType
|
||||
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.ButtonsPanel
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
|
||||
expect object ProjectTypeDrawer : Drawer<ProjectTypeView>
|
||||
expect class ProjectTypeDrawer : Drawer<ProjectType>
|
||||
expect fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer
|
||||
|
||||
class ProjectTypeView : VerticalView("Project type") {
|
||||
var projectType by mutableStateOf<ProjectType>(MultiplatformProjectType)
|
||||
private val typeDrawer = ProjectTypeDrawerWithView(this)
|
||||
|
||||
override val content: @Composable () -> Unit = {
|
||||
with(ProjectTypeDrawer) { draw() }
|
||||
ButtonsPanel(
|
||||
MultiplatformProjectType,
|
||||
JVMProjectType,
|
||||
JSProjectType
|
||||
) {
|
||||
with(typeDrawer) {
|
||||
with (it) {
|
||||
draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,9 +2,11 @@ package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
|
||||
class RepositoryState(
|
||||
@@ -19,8 +21,6 @@ class RepositoryState(
|
||||
|
||||
private fun MavenPublishingRepository.toRepositoryState() = RepositoryState(name, url)
|
||||
|
||||
expect object RepositoryStateDrawer : Drawer<RepositoryState>
|
||||
|
||||
class RepositoriesView : ListView<RepositoryState>("Repositories info") {
|
||||
var repositories: List<MavenPublishingRepository>
|
||||
get() = itemsList.map { it.toRepository() }
|
||||
@@ -38,7 +38,14 @@ class RepositoriesView : ListView<RepositoryState>("Repositories info") {
|
||||
|
||||
@Composable
|
||||
override fun buildView(item: RepositoryState) {
|
||||
with(RepositoryStateDrawer) { with(item) { draw() } }
|
||||
CommonTextField(
|
||||
item.name,
|
||||
"Repository name",
|
||||
) { item.name = it }
|
||||
CommonTextField(
|
||||
item.url,
|
||||
"Repository url",
|
||||
) { item.url = it }
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
interface Drawer<T> {
|
||||
fun interface Drawer<T> {
|
||||
@Composable
|
||||
fun T.draw()
|
||||
}
|
||||
|
@@ -9,7 +9,12 @@ expect fun TitleText(text: String)
|
||||
expect fun CommonText(text: String, onClick: (() -> Unit)? = null)
|
||||
|
||||
@Composable
|
||||
expect fun CommonTextField(presetText: String, hint: String, onChange: (String) -> Unit)
|
||||
expect fun CommonTextField(
|
||||
presetText: String,
|
||||
hint: String,
|
||||
onFocusChanged: (Boolean) -> Unit = {},
|
||||
onChange: (String) -> Unit
|
||||
)
|
||||
|
||||
@Composable
|
||||
expect fun SwitchWithLabel(
|
||||
@@ -19,3 +24,18 @@ expect fun SwitchWithLabel(
|
||||
switchEnabled: Boolean = true,
|
||||
onCheckedChange: (Boolean) -> Unit
|
||||
)
|
||||
|
||||
@Composable
|
||||
expect fun <T> ButtonsPanel(
|
||||
data: Iterable<T>,
|
||||
itemDrawer: @Composable (T) -> Unit
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun <T> ButtonsPanel(
|
||||
vararg data: T,
|
||||
itemDrawer: @Composable (T) -> Unit
|
||||
) = ButtonsPanel(data.toList(), itemDrawer)
|
||||
|
||||
@Composable
|
||||
expect fun DefaultDivider()
|
||||
|
@@ -5,16 +5,7 @@ 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 openNewConfig(onParsed: (Config) -> Unit)
|
||||
|
||||
expect fun saveConfig(config: Config): Boolean
|
||||
|
||||
|
1
core/src/commonMain/resources/images/export_gradle.svg
Normal file
1
core/src/commonMain/resources/images/export_gradle.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="white" d="M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2M18 20H6V4H13V9H18V20M16 11V18.1L13.9 16L11.1 18.8L8.3 16L11.1 13.2L8.9 11H16Z" /></svg>
|
After Width: | Height: | Size: 463 B |
1
core/src/commonMain/resources/images/open_file.svg
Normal file
1
core/src/commonMain/resources/images/open_file.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="white" d="M6.1,10L4,18V8H21A2,2 0 0,0 19,6H12L10,4H4A2,2 0 0,0 2,6V18A2,2 0 0,0 4,20H19C19.9,20 20.7,19.4 20.9,18.5L23.2,10H6.1M19,18H6L7.6,12H20.6L19,18Z" /></svg>
|
After Width: | Height: | Size: 452 B |
1
core/src/commonMain/resources/images/save_as.svg
Normal file
1
core/src/commonMain/resources/images/save_as.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="white" d="M4 19H10V21H4C2.89 21 2 20.1 2 19V5C2 3.9 2.89 3 4 3H16L20 7V9.12L18 11.12V7.83L15.17 5H4V19M14 10V6H5V10H14M20.42 12.3C20.31 12.19 20.18 12.13 20.04 12.13C19.9 12.13 19.76 12.19 19.65 12.3L18.65 13.3L20.7 15.35L21.7 14.35C21.92 14.14 21.92 13.79 21.7 13.58L20.42 12.3M12 19.94V22H14.06L20.12 15.93L18.07 13.88L12 19.94M14 15C14 13.34 12.66 12 11 12S8 13.34 8 15 9.34 18 11 18C11.04 18 11.08 18 11.13 18L14 15.13C14 15.09 14 15.05 14 15" /></svg>
|
After Width: | Height: | Size: 744 B |
1
core/src/commonMain/resources/images/save_file.svg
Normal file
1
core/src/commonMain/resources/images/save_file.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="white" d="M17 3H5C3.89 3 3 3.9 3 5V19C3 20.1 3.89 21 5 21H19C20.1 21 21 20.1 21 19V7L17 3M19 19H5V5H16.17L19 7.83V19M12 12C10.34 12 9 13.34 9 15S10.34 18 12 18 15 16.66 15 15 13.66 12 12 12M6 6H15V10H6V6Z" /></svg>
|
After Width: | Height: | Size: 502 B |
@@ -0,0 +1,14 @@
|
||||
package dev.inmo.kmppscriptbuilder.core
|
||||
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.BuilderView
|
||||
import kotlinx.browser.window
|
||||
import org.jetbrains.compose.web.renderComposableInBody
|
||||
|
||||
fun main() {
|
||||
window.addEventListener("load", {
|
||||
val builder = BuilderView()
|
||||
renderComposableInBody {
|
||||
builder.build()
|
||||
}
|
||||
})
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.inmo.jsuikit.elements.DefaultButton
|
||||
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
|
||||
actual class GpgSigningOptionDrawer(
|
||||
private val mavenInfoView: MavenInfoView
|
||||
) : Drawer<GpgSigning> {
|
||||
@Composable
|
||||
override fun GpgSigning.draw() {
|
||||
if (mavenInfoView.gpgSignProperty == this) {
|
||||
DefaultButton(name, UIKitButton.Type.Primary)
|
||||
} else {
|
||||
DefaultButton(name, UIKitButton.Type.Default) {
|
||||
mavenInfoView.gpgSignProperty = this
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actual fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer = GpgSigningOptionDrawer(mavenInfoView = view)
|
@@ -0,0 +1,59 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.inmo.jsuikit.elements.DefaultButton
|
||||
import dev.inmo.jsuikit.elements.Divider
|
||||
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||
import dev.inmo.jsuikit.modifiers.builder
|
||||
import dev.inmo.jsuikit.utils.Attrs
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
import org.jetbrains.compose.web.dom.Div
|
||||
|
||||
actual object LicensesDrawer : Drawer<LicensesView> {
|
||||
@Composable
|
||||
override fun LicensesView.draw() {
|
||||
dev.inmo.jsuikit.elements.List(
|
||||
licensesOffersToShow.value,
|
||||
Attrs {
|
||||
if (!searchFieldFocused.value) {
|
||||
hidden()
|
||||
}
|
||||
}
|
||||
) {
|
||||
DefaultButton(
|
||||
it.title,
|
||||
UIKitButton.Type.Text
|
||||
) { _ ->
|
||||
licensesListState.add(it.toLicenseState())
|
||||
licenseSearchFilter = ""
|
||||
}
|
||||
Divider.Common()
|
||||
}
|
||||
|
||||
DefaultButton("Add empty license", UIKitButton.Type.Primary, UIKitMargin.Small) {
|
||||
licensesListState.add(LicenseState())
|
||||
}
|
||||
|
||||
licensesListState.forEach { license ->
|
||||
Div(UIKitMargin.Small.builder()) {
|
||||
CommonTextField(
|
||||
license.id,
|
||||
"License ID",
|
||||
) { license.id = it }
|
||||
CommonTextField(
|
||||
license.title,
|
||||
"License title",
|
||||
) { license.title = it }
|
||||
CommonTextField(
|
||||
license.url ?: "",
|
||||
"License URL",
|
||||
) { license.url = it }
|
||||
DefaultButton("Remove", UIKitButton.Type.Danger, UIKitMargin.Small) {
|
||||
licensesListState.remove(license)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.inmo.jsuikit.elements.DefaultButton
|
||||
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||
import dev.inmo.jsuikit.modifiers.builder
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
import org.jetbrains.compose.web.dom.Div
|
||||
|
||||
actual class ListViewDrawer<T> : Drawer<ListView<T>> {
|
||||
@Composable
|
||||
override fun ListView<T>.draw() {
|
||||
DefaultButton(addItemText, UIKitButton.Type.Primary ) { itemsList.add(createItem()) }
|
||||
itemsList.forEach { item ->
|
||||
Div(UIKitMargin.Small.builder()) {
|
||||
buildView(item)
|
||||
DefaultButton(removeItemText, UIKitButton.Type.Danger, UIKitMargin.Small) {
|
||||
itemsList.remove(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.inmo.jsuikit.elements.DefaultButton
|
||||
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
|
||||
actual class ProjectTypeDrawer(
|
||||
private val projectTypeView: ProjectTypeView
|
||||
) : Drawer<ProjectType> {
|
||||
@Composable
|
||||
override fun ProjectType.draw() {
|
||||
if (projectTypeView.projectType == this) {
|
||||
DefaultButton(name, UIKitButton.Type.Primary)
|
||||
} else {
|
||||
DefaultButton(name, UIKitButton.Type.Default) {
|
||||
projectTypeView.projectType = this
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actual fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer = ProjectTypeDrawer(projectTypeView = view)
|
@@ -0,0 +1,82 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.inmo.jsuikit.elements.Icon
|
||||
import dev.inmo.jsuikit.elements.NavItemElement
|
||||
import dev.inmo.jsuikit.elements.Navbar
|
||||
import dev.inmo.jsuikit.elements.NavbarNav
|
||||
import dev.inmo.jsuikit.elements.drawAsLink
|
||||
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||
import dev.inmo.jsuikit.modifiers.UIKitPadding
|
||||
import dev.inmo.jsuikit.modifiers.UIKitText
|
||||
import dev.inmo.jsuikit.modifiers.UIKitTooltipModifier
|
||||
import dev.inmo.jsuikit.modifiers.builder
|
||||
import dev.inmo.jsuikit.modifiers.include
|
||||
import dev.inmo.jsuikit.utils.AttrsWithContentBuilder
|
||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.exportGradle
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.openNewConfig
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.saveConfig
|
||||
import org.jetbrains.compose.web.dom.A
|
||||
import org.jetbrains.compose.web.dom.Div
|
||||
import org.jetbrains.compose.web.dom.Img
|
||||
import org.jetbrains.compose.web.dom.Text
|
||||
|
||||
@Composable
|
||||
actual fun TopAppBar(
|
||||
config: Config,
|
||||
saveAvailable: Boolean,
|
||||
onSaveAvailable: (Boolean) -> Unit,
|
||||
onNewConfig: (Config) -> Unit
|
||||
) {
|
||||
Navbar(
|
||||
leftBuilder = AttrsWithContentBuilder {
|
||||
Div(
|
||||
{
|
||||
onClick {
|
||||
console.log(config)
|
||||
}
|
||||
include(UIKitPadding.Size.Small, UIKitText.Style.Lead)
|
||||
}
|
||||
) {
|
||||
Text("Kotlin publication scripts builder")
|
||||
}
|
||||
Div(UIKitMargin.Small.builder()) {
|
||||
A("https://github.com/InsanusMokrassar/KotlinPublicationScriptsBuilder") {
|
||||
Img("https://img.shields.io/github/stars/InsanusMokrassar/KotlinPublicationScriptsBuilder?label=Github&style=plastic")
|
||||
}
|
||||
}
|
||||
},
|
||||
rightBuilder = AttrsWithContentBuilder {
|
||||
NavbarNav(
|
||||
AttrsWithContentBuilder {
|
||||
NavItemElement(
|
||||
UIKitTooltipModifier("Open file")
|
||||
) {
|
||||
Icon.Storage.Pull.drawAsLink {
|
||||
openNewConfig(onNewConfig)
|
||||
}
|
||||
}
|
||||
},
|
||||
AttrsWithContentBuilder {
|
||||
NavItemElement(
|
||||
UIKitTooltipModifier("Save config")
|
||||
) {
|
||||
Icon.Storage.Push.drawAsLink {
|
||||
saveConfig(config)
|
||||
}
|
||||
}
|
||||
},
|
||||
AttrsWithContentBuilder {
|
||||
NavItemElement(
|
||||
UIKitTooltipModifier("Export gradle script")
|
||||
) {
|
||||
Icon.Storage.Upload.drawAsLink {
|
||||
exportGradle(config)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
@@ -1,6 +1,10 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.inmo.jsuikit.modifiers.UIKitForm
|
||||
import dev.inmo.jsuikit.modifiers.builder
|
||||
import org.jetbrains.compose.web.dom.Legend
|
||||
import org.jetbrains.compose.web.dom.Text
|
||||
|
||||
actual abstract class View {
|
||||
@Composable
|
||||
@@ -9,4 +13,8 @@ actual abstract class View {
|
||||
|
||||
@Composable
|
||||
actual fun View.DrawVertically(title: String, block: @Composable () -> Unit) {
|
||||
Legend(UIKitForm.Legend.builder()) {
|
||||
Text(title)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
@@ -0,0 +1,107 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui.utils
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.inmo.jsuikit.elements.DefaultButton
|
||||
import dev.inmo.jsuikit.elements.DefaultInput
|
||||
import dev.inmo.jsuikit.elements.Divider
|
||||
import dev.inmo.jsuikit.elements.Flex
|
||||
import dev.inmo.jsuikit.elements.Icon
|
||||
import dev.inmo.jsuikit.elements.Label
|
||||
import dev.inmo.jsuikit.elements.drawAsFormInputPart
|
||||
import dev.inmo.jsuikit.modifiers.UIKitButton
|
||||
import dev.inmo.jsuikit.modifiers.UIKitFlex
|
||||
import dev.inmo.jsuikit.modifiers.UIKitForm
|
||||
import dev.inmo.jsuikit.modifiers.UIKitInverse
|
||||
import dev.inmo.jsuikit.modifiers.UIKitMargin
|
||||
import dev.inmo.jsuikit.modifiers.UIKitText
|
||||
import dev.inmo.jsuikit.modifiers.UIKitUtility
|
||||
import dev.inmo.jsuikit.modifiers.builder
|
||||
import dev.inmo.jsuikit.modifiers.include
|
||||
import dev.inmo.jsuikit.utils.Attrs
|
||||
import org.jetbrains.compose.web.attributes.InputType
|
||||
import org.jetbrains.compose.web.dom.Div
|
||||
import org.jetbrains.compose.web.dom.Legend
|
||||
import org.jetbrains.compose.web.dom.Text
|
||||
|
||||
@Composable
|
||||
actual fun TitleText(text: String) {
|
||||
Legend(UIKitForm.Legend.builder()) {
|
||||
Text(text)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun CommonText(text: String, onClick: (() -> Unit)?) {
|
||||
Div(
|
||||
{
|
||||
onClick ?.let {
|
||||
this.onClick { _ ->
|
||||
it()
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(text)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun CommonTextField(
|
||||
presetText: String,
|
||||
hint: String,
|
||||
onFocusChanged: (Boolean) -> Unit,
|
||||
onChange: (String) -> Unit
|
||||
) {
|
||||
DefaultInput(
|
||||
InputType.Text,
|
||||
presetText,
|
||||
false,
|
||||
placeholder = hint,
|
||||
attributesCustomizer = {
|
||||
onFocusIn { onFocusChanged(true) }
|
||||
onFocusOut { onFocusChanged(false) }
|
||||
},
|
||||
onChange = onChange
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun SwitchWithLabel(
|
||||
label: String,
|
||||
checked: Boolean,
|
||||
placeSwitchAtTheStart: Boolean,
|
||||
switchEnabled: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit
|
||||
) {
|
||||
DefaultButton(
|
||||
if (checked) {
|
||||
UIKitButton.Type.Primary
|
||||
} else {
|
||||
UIKitButton.Type.Default
|
||||
},
|
||||
disabled = !switchEnabled,
|
||||
onClick = {
|
||||
onCheckedChange(!checked)
|
||||
},
|
||||
attributesCustomizer = {
|
||||
include(UIKitUtility.Inline)
|
||||
}
|
||||
) {
|
||||
if (checked) {
|
||||
Icon.App.Check.drawAsFormInputPart(UIKitInverse.Light)
|
||||
}
|
||||
Text(label)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun <T> ButtonsPanel(data: Iterable<T>, itemDrawer: @Composable (T) -> Unit) {
|
||||
Flex(UIKitFlex.Alignment.Vertical.Middle, UIKitMargin.Small) {
|
||||
data.forEach { itemDrawer(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun DefaultDivider() {
|
||||
Divider.Common()
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.utils
|
||||
|
||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||
import kotlinx.browser.document
|
||||
import kotlinx.dom.appendElement
|
||||
import org.w3c.dom.HTMLAnchorElement
|
||||
import org.w3c.dom.HTMLInputElement
|
||||
import org.w3c.dom.url.URL
|
||||
import org.w3c.files.Blob
|
||||
import org.w3c.files.BlobPropertyBag
|
||||
import org.w3c.files.FileReader
|
||||
import org.w3c.files.get
|
||||
|
||||
fun saveFile(content: String, filename: String) {
|
||||
val a = document.body!!.appendElement("a") {
|
||||
setAttribute("style", "visibility:hidden; display: none")
|
||||
} as HTMLAnchorElement
|
||||
val blob = Blob(arrayOf(content), BlobPropertyBag(
|
||||
"application/*;charset=utf-8"
|
||||
))
|
||||
val url = URL.createObjectURL(blob)
|
||||
a.href = url
|
||||
a.download = filename
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
a.remove()
|
||||
}
|
||||
|
||||
actual fun openNewConfig(onParsed: (Config) -> Unit) {
|
||||
val targetInput = document.body!!.appendElement("input") {
|
||||
setAttribute("style", "visibility:hidden; display: none")
|
||||
} as HTMLInputElement
|
||||
targetInput.type = "file"
|
||||
targetInput.onchange = {
|
||||
targetInput.files ?.also { files ->
|
||||
for (i in (0 until files.length) ) {
|
||||
files[i] ?.also { file ->
|
||||
val reader = FileReader()
|
||||
|
||||
reader.onload = {
|
||||
val content = it.target.asDynamic().result as String
|
||||
onParsed(serialFormat.decodeFromString(Config.serializer(), content))
|
||||
false
|
||||
}
|
||||
|
||||
reader.readAsText(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
targetInput.click()
|
||||
targetInput.remove()
|
||||
}
|
||||
|
||||
actual fun saveConfig(config: Config): Boolean {
|
||||
saveFile(
|
||||
serialFormat.encodeToString(Config.serializer(), config),
|
||||
"publish.kpsb"
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
actual fun exportGradle(config: Config): Boolean {
|
||||
val filename = "publish.gradle"
|
||||
|
||||
val content = config.run {
|
||||
type.buildMavenGradleConfig(
|
||||
mavenConfig,
|
||||
licenses
|
||||
)
|
||||
}
|
||||
|
||||
saveFile(content, filename)
|
||||
return true
|
||||
}
|
||||
|
||||
actual fun saveAs(config: Config): Boolean {
|
||||
saveFile(
|
||||
serialFormat.encodeToString(Config.serializer(), config),
|
||||
"publish.kpsb"
|
||||
)
|
||||
return true
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.utils
|
||||
|
||||
actual fun openLink(link: String): Boolean {
|
||||
dev.inmo.micro_utils.common.openLink(link)
|
||||
return true
|
||||
}
|
1
core/src/jsMain/resources/css/uikit.min.css
vendored
Normal file
1
core/src/jsMain/resources/css/uikit.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
72
core/src/jsMain/resources/index.html
Normal file
72
core/src/jsMain/resources/index.html
Normal file
@@ -0,0 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Kotlin Publication Scripts Builder</title>
|
||||
<!-- UIkit CSS -->
|
||||
<link rel="stylesheet" href="./css/uikit.min.css" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- <form class="uk-padding-small">-->
|
||||
<!-- <fieldset class="uk-fieldset">-->
|
||||
<!-- <legend class="uk-legend">Project type</legend>-->
|
||||
<!-- <div class="uk-padding-small">-->
|
||||
<!-- <ul class="uk-subnav uk-subnav-pill">-->
|
||||
<!-- <li id="mppProjectType" class="uk-active"><a href="#">Multiplatform</a></li>-->
|
||||
<!-- <li id="jvmProjectType"><a href="#">JVM</a></li>-->
|
||||
<!-- <li id="jsProjectType"><a href="#">JS</a></li>-->
|
||||
<!-- </ul>-->
|
||||
<!-- </div>-->
|
||||
<!-- <legend class="uk-legend">Licenses</legend>-->
|
||||
<!-- <div id="licensesListDiv" class="uk-padding-small"></div>-->
|
||||
|
||||
<!-- <legend class="uk-legend">Project information</legend>-->
|
||||
|
||||
<!-- <div class="uk-padding-small">-->
|
||||
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||
<!-- <label class="uk-form-label" for="projectNameInput">Public project name</label>-->
|
||||
<!-- <input id="projectNameInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||
<!-- <label class="uk-form-label" for="projectDescriptionInput">Public project description</label>-->
|
||||
<!-- <input id="projectDescriptionInput" class="uk-input uk-width-expand" type="text" placeholder="${project.name}">-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||
<!-- <label class="uk-form-label" for="projectUrlInput">Public project URL</label>-->
|
||||
<!-- <input id="projectUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github or other source with readme">-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="uk-margin uk-width-1-1">-->
|
||||
<!-- <label class="uk-form-label" for="projectVCSUrlInput">Public project VCS URL (with .git)</label>-->
|
||||
<!-- <input id="projectVCSUrlInput" class="uk-input uk-width-expand" type="text" placeholder="Type url to github .git file">-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- <div class="uk-margin">-->
|
||||
<!-- <label>GPG Signing</label>-->
|
||||
|
||||
<!-- <div class="uk-padding-small">-->
|
||||
<!-- <ul class="uk-subnav uk-subnav-pill">-->
|
||||
<!-- <li id="disableGpgSigning" class="uk-active" uk-tooltip="title: Signing will not be added"><a href="#">Disabled</a></li>-->
|
||||
<!-- <li id="optionalGpgSigning" uk-tooltip="title: Signing will be added, but disabled in case of absence 'signatory.keyId'"><a href="#">Optional</a></li>-->
|
||||
<!-- <li id="enableGpgSigning" uk-tooltip="title: Signing will be always enabled"><a href="#">Enabled</a></li>-->
|
||||
<!-- </ul>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="uk-margin">-->
|
||||
<!-- <label><input id="includeMavenCentralTargetRepoToggle" class="uk-checkbox" type="checkbox"> Include publication to MavenCentral</label>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- <legend class="uk-legend">Developers info</legend>-->
|
||||
<!-- <div id="developersListDiv" class="uk-padding-small"></div>-->
|
||||
|
||||
<!-- <legend class="uk-legend">Repositories info</legend>-->
|
||||
<!-- <div id="repositoriesListDiv" class="uk-padding-small"></div>-->
|
||||
<!-- </fieldset>-->
|
||||
<!-- </form>-->
|
||||
<!-- UIkit JS -->
|
||||
<script src="./js/uikit.min.js"></script>
|
||||
<script src="./js/uikit-icons.min.js"></script>
|
||||
<!-- Internal JS -->
|
||||
<script src="kmppscriptbuilder.core.js"></script>
|
||||
</body>
|
||||
</html>
|
1
core/src/jsMain/resources/js/uikit-icons.min.js
vendored
Normal file
1
core/src/jsMain/resources/js/uikit-icons.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
core/src/jsMain/resources/js/uikit.min.js
vendored
Normal file
1
core/src/jsMain/resources/js/uikit.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,68 @@
|
||||
package dev.inmo.kmppscriptbuilder.core
|
||||
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Colors
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.BuilderView
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.loadConfigFile
|
||||
import java.io.File
|
||||
|
||||
//private val uncaughtExceptionsBC = BroadcastChannel<DefaultErrorHandler.ErrorEvent>(Channel.CONFLATED)
|
||||
//val uncaughtExceptionsFlow: Flow<DefaultErrorHandler.ErrorEvent> = uncaughtExceptionsBC.asFlow()
|
||||
|
||||
fun main(args: Array<String>) = application {
|
||||
Window(onCloseRequest = ::exitApplication, title = "Kotlin Multiplatform Publishing Builder") {
|
||||
val builder = BuilderView()
|
||||
MaterialTheme(
|
||||
Colors(
|
||||
primary = Color(0x01, 0x57, 0x9b),
|
||||
primaryVariant = Color(0x00, 0x2f, 0x6c),
|
||||
secondary = Color(0xb2, 0xeb, 0xf2),
|
||||
secondaryVariant = Color(0x81, 0xb9, 0xbf),
|
||||
background = Color(0xe1, 0xe2, 0xe1),
|
||||
surface = Color(0xf5, 0xf5, 0xf6),
|
||||
error = Color(0xb7, 0x1c, 0x1c),
|
||||
onPrimary = Color.White,
|
||||
onSecondary = Color.Black,
|
||||
onBackground = Color.Black,
|
||||
onSurface = Color.Black,
|
||||
onError = Color.White,
|
||||
isLight = MaterialTheme.colors.isLight,
|
||||
)
|
||||
) {
|
||||
Box(
|
||||
Modifier.fillMaxSize()
|
||||
.background(color = Color(245, 245, 245))
|
||||
) {
|
||||
|
||||
val stateVertical = rememberScrollState(0)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(stateVertical)
|
||||
) {
|
||||
Column {
|
||||
builder.build()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VerticalScrollbar(
|
||||
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
|
||||
adapter = rememberScrollbarAdapter(stateVertical)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (args.isNotEmpty()) {
|
||||
val config = loadConfigFile(File(args.first()))
|
||||
builder.config = config
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
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,39 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.OutlinedButton
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.SwitchWithLabel
|
||||
|
||||
actual class GpgSigningOptionDrawer(
|
||||
private val mavenInfoView: MavenInfoView
|
||||
) : Drawer<GpgSigning> {
|
||||
@Composable
|
||||
override fun GpgSigning.draw() {
|
||||
if (mavenInfoView.gpgSignProperty == this) {
|
||||
Button({}, Modifier.padding(8.dp)) {
|
||||
Text(name)
|
||||
}
|
||||
} else {
|
||||
OutlinedButton(
|
||||
{
|
||||
mavenInfoView.gpgSignProperty = this
|
||||
},
|
||||
Modifier.padding(8.dp)
|
||||
) {
|
||||
Text(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actual fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer = GpgSigningOptionDrawer(mavenInfoView = view)
|
@@ -4,6 +4,9 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
|
||||
@@ -11,44 +14,39 @@ import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
|
||||
actual object LicensesDrawer : Drawer<LicensesView> {
|
||||
@Composable
|
||||
override fun LicensesView.draw() {
|
||||
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) {
|
||||
licensesListState.add(it.toLicenseState())
|
||||
licenseSearchFilter = ""
|
||||
licensesOffersToShow.clear()
|
||||
if (searchFieldFocused.value) {
|
||||
Column {
|
||||
licensesOffersToShow.value.forEach {
|
||||
Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
|
||||
CommonText(it.title) {
|
||||
licensesListState.add(it.toLicenseState())
|
||||
licenseSearchFilter = ""
|
||||
}
|
||||
Divider()
|
||||
}
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button({ licensesListState.add(LicenseState()) }, Modifier.padding(8.dp)) {
|
||||
CommonText("Add empty license",)
|
||||
CommonText("Add empty license")
|
||||
}
|
||||
|
||||
licensesListState.forEach { license ->
|
||||
Column(Modifier.padding(8.dp)) {
|
||||
CommonTextField(
|
||||
license.id,
|
||||
"License ID"
|
||||
"License ID",
|
||||
) { license.id = it }
|
||||
CommonTextField(
|
||||
license.title,
|
||||
"License title"
|
||||
"License title",
|
||||
) { license.title = it }
|
||||
CommonTextField(
|
||||
license.url ?: "",
|
||||
"License URL"
|
||||
"License URL",
|
||||
) { license.url = it }
|
||||
Button({ licensesListState.remove(license) }, Modifier.padding(8.dp)) {
|
||||
CommonText("Remove",)
|
||||
|
@@ -3,12 +3,14 @@ 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.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
|
||||
|
||||
actual class ListViewDrawer<T> : Drawer<ListView<T>> {
|
||||
@Composable
|
||||
override fun ListView<T>.draw() {
|
||||
Button({ itemsList.add(createItem()) }) {
|
||||
CommonText(addItemText,)
|
||||
|
@@ -1,68 +0,0 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.OutlinedButton
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.SwitchWithLabel
|
||||
|
||||
actual object MavenInfoDrawer : Drawer<MavenInfoView> {
|
||||
@Composable
|
||||
private fun MavenInfoView.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 fun MavenInfoView.draw() {
|
||||
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()
|
||||
}
|
||||
}
|
@@ -15,30 +15,26 @@ import dev.inmo.kmppscriptbuilder.core.models.MultiplatformProjectType
|
||||
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
|
||||
actual object ProjectTypeDrawer : Drawer<ProjectTypeView> {
|
||||
actual class ProjectTypeDrawer(
|
||||
private val projectTypeView: ProjectTypeView
|
||||
) : Drawer<ProjectType> {
|
||||
@Composable
|
||||
private fun ProjectTypeView.addProjectTypeButton(newProjectType: ProjectType) {
|
||||
if (projectType == newProjectType) {
|
||||
override fun ProjectType.draw() {
|
||||
if (projectTypeView.projectType == this) {
|
||||
Button({}, Modifier.padding(8.dp)) {
|
||||
Text(newProjectType.name)
|
||||
Text(name)
|
||||
}
|
||||
} else {
|
||||
OutlinedButton(
|
||||
{
|
||||
projectType = newProjectType
|
||||
projectTypeView.projectType = this
|
||||
},
|
||||
Modifier.padding(8.dp)
|
||||
) {
|
||||
Text(newProjectType.name)
|
||||
Text(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun ProjectTypeView.draw() {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
addProjectTypeButton(MultiplatformProjectType)
|
||||
addProjectTypeButton(JVMProjectType)
|
||||
addProjectTypeButton(JSProjectType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actual fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer = ProjectTypeDrawer(projectTypeView = view)
|
||||
|
@@ -1,18 +0,0 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
|
||||
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
|
||||
|
||||
actual object RepositoryStateDrawer : Drawer<RepositoriesView> {
|
||||
override fun RepositoriesView.draw() {
|
||||
CommonTextField(
|
||||
item.name,
|
||||
"Repository name"
|
||||
) { item.name = it }
|
||||
CommonTextField(
|
||||
item.url,
|
||||
"Repository url"
|
||||
) { item.url = it }
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
package dev.inmo.kmppscriptbuilder.core.ui
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.TooltipArea
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TopAppBar
|
||||
import androidx.compose.material.primarySurface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.inmo.kmppscriptbuilder.core.models.Config
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.exportGradle
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.openNewConfig
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.saveAs
|
||||
import dev.inmo.kmppscriptbuilder.core.utils.saveConfig
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun createIcon(
|
||||
tooltip: String,
|
||||
resource: String,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
TooltipArea(
|
||||
tooltip = {
|
||||
Surface(
|
||||
modifier = Modifier.shadow(4.dp),
|
||||
color = MaterialTheme.colors.primarySurface,
|
||||
shape = RoundedCornerShape(4.dp)
|
||||
) {
|
||||
Text(tooltip, modifier = Modifier.padding(10.dp), color = MaterialTheme.colors.onPrimary)
|
||||
}
|
||||
}
|
||||
) {
|
||||
IconButton(onClick) {
|
||||
Image(
|
||||
painter = painterResource(resource),
|
||||
contentDescription = tooltip
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun TopAppBar(
|
||||
config: Config,
|
||||
saveAvailable: Boolean,
|
||||
onSaveAvailable: (Boolean) -> Unit,
|
||||
onNewConfig: (Config) -> Unit
|
||||
) {
|
||||
TopAppBar(
|
||||
@Composable {
|
||||
Text("Kotlin publication scripts builder", Modifier.clickable { println(config) })
|
||||
},
|
||||
actions = {
|
||||
createIcon("Open file", "images/open_file.svg") {
|
||||
openNewConfig(onNewConfig)
|
||||
}
|
||||
|
||||
if (saveAvailable) {
|
||||
createIcon("Save", "images/save_file.svg") {
|
||||
saveConfig(config)
|
||||
}
|
||||
}
|
||||
|
||||
if (saveAvailable) {
|
||||
createIcon("Export Gradle script", "images/export_gradle.svg") {
|
||||
exportGradle(config)
|
||||
}
|
||||
}
|
||||
|
||||
createIcon("Save as", "images/save_as.svg") {
|
||||
if (saveAs(config)) {
|
||||
onSaveAvailable(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
@@ -6,12 +6,14 @@ 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.Divider
|
||||
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.focus.onFocusChanged
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -29,15 +31,15 @@ actual fun SwitchWithLabel(
|
||||
switchEnabled: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit
|
||||
) {
|
||||
Row(Modifier.padding(0.dp, 8.dp), Arrangement.Start, Alignment.Top) {
|
||||
Row(Modifier.padding(0.dp, 8.dp).clickable { onCheckedChange(!checked) }, Arrangement.Start, Alignment.Top) {
|
||||
val switchCreator = @Composable {
|
||||
Switch(checked, onCheckedChange, Modifier.padding(8.dp, 0.dp), enabled = switchEnabled)
|
||||
Switch(checked, null, Modifier.padding(8.dp, 0.dp), enabled = switchEnabled)
|
||||
}
|
||||
if (placeSwitchAtTheStart) {
|
||||
switchCreator()
|
||||
}
|
||||
Box(Modifier.fillMaxWidth().align(Alignment.CenterVertically).clickable { }) {
|
||||
CommonText(label,)
|
||||
Box(Modifier.fillMaxWidth().align(Alignment.CenterVertically)) {
|
||||
CommonText(label)
|
||||
}
|
||||
if (!placeSwitchAtTheStart) {
|
||||
switchCreator()
|
||||
@@ -46,11 +48,18 @@ actual fun SwitchWithLabel(
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun CommonTextField(presetText: String, hint: String, onChange: (String) -> Unit) {
|
||||
actual fun CommonTextField(
|
||||
presetText: String,
|
||||
hint: String,
|
||||
onFocusChanged: (Boolean) -> Unit,
|
||||
onChange: (String) -> Unit
|
||||
) {
|
||||
OutlinedTextField(
|
||||
presetText,
|
||||
onChange,
|
||||
Modifier.fillMaxWidth(),
|
||||
Modifier.fillMaxWidth().onFocusChanged {
|
||||
onFocusChanged(it.isFocused)
|
||||
},
|
||||
singleLine = true,
|
||||
label = {
|
||||
CommonText(hint,)
|
||||
@@ -69,3 +78,15 @@ actual fun TitleText(text: String) {
|
||||
text, Modifier.padding(0.dp, 8.dp), fontSize = 18.sp
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun <T> ButtonsPanel(data: Iterable<T>, itemDrawer: @Composable (T) -> Unit) {
|
||||
Row {
|
||||
data.forEach { itemDrawer(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
actual fun DefaultDivider() {
|
||||
Divider()
|
||||
}
|
||||
|
@@ -2,33 +2,29 @@ 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"
|
||||
fun MPPFile.text() = readText()
|
||||
|
||||
private var lastFile: File? = null
|
||||
internal var lastFile: MPPFile? = null
|
||||
|
||||
fun loadConfigFile(file: File): Config {
|
||||
fun loadConfigFile(file: MPPFile): Config {
|
||||
lastFile = file
|
||||
return serialFormat.decodeFromString(Config.serializer(), file.readText())
|
||||
return serialFormat.decodeFromString(Config.serializer(), file.text())
|
||||
}
|
||||
|
||||
actual fun MPPFile.text() = readText()
|
||||
|
||||
actual fun loadConfig(): Config? {
|
||||
actual fun openNewConfig(onParsed: (Config) -> Unit) {
|
||||
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)) {
|
||||
when (fc.showOpenDialog(null)) {
|
||||
JFileChooser.APPROVE_OPTION -> {
|
||||
val file = fc.selectedFile
|
||||
lastFile = file
|
||||
return serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText())
|
||||
onParsed(serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText()))
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user