Compare commits

...

16 Commits

27 changed files with 523 additions and 300 deletions

1
.gitignore vendored
View File

@@ -10,3 +10,4 @@ build/
out/
local.properties
kotlin-js-store/

View File

@@ -1,6 +1,5 @@
buildscript {
repositories {
jcenter()
google()
mavenCentral()
mavenLocal()
@@ -8,7 +7,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
classpath 'com.android.tools.build:gradle:7.0.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.getkeepsafe.dexcount:dexcount-gradle-plugin:$dexcount_version"
@@ -19,10 +18,8 @@ buildscript {
allprojects {
repositories {
mavenLocal()
jcenter()
mavenCentral()
google()
maven { url "https://kotlin.bintray.com/kotlinx" }
maven { url "https://maven.pkg.jetbrains.space/public/p/compose/dev" }
}
}

View File

@@ -0,0 +1,41 @@
package dev.inmo.kmppscriptbuilder.core.export
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
fun GpgSigning.generateMavenConfig() = when (this) {
GpgSigning.Disabled -> ""
GpgSigning.Optional ->
"""
if (project.hasProperty("signing.gnupg.keyName")) {
apply plugin: 'signing'
signing {
useGpgCmd()
sign publishing.publications
}
task signAll {
tasks.withType(Sign).forEach {
dependsOn(it)
}
}
}
"""
GpgSigning.Enabled ->
"""
apply plugin: 'signing'
signing {
useGpgCmd()
sign publishing.publications
}
task signAll {
tasks.withType(Sign).forEach {
dependsOn(it)
}
}
"""
}

View File

@@ -0,0 +1,67 @@
package dev.inmo.kmppscriptbuilder.core.export.js_only
import dev.inmo.kmppscriptbuilder.core.export.generateMavenConfig
import dev.inmo.kmppscriptbuilder.core.models.*
fun MavenConfig.buildJsOnlyMavenConfig(licenses: List<License>): String = """
apply plugin: 'maven-publish'
task javadocJar(type: Jar) {
classifier = 'javadoc'
}
task sourcesJar(type: Jar) {
kotlin.sourceSets.all {
from(kotlin)
}
classifier = 'sources'
}
publishing {
publications {
maven(MavenPublication) {
kotlin.js().components.forEach {
from(it)
}
artifact javadocJar
artifact sourcesJar
pom {
resolveStrategy = Closure.DELEGATE_FIRST
description = "$description"
name = "$name"
url = "$url"
scm {
developerConnection = "scm:git:[fetch=]${vcsUrl}[push=]${vcsUrl}"
url = "$vcsUrl"
}
developers {
${developers.joinToString("\n") { """
developer {
id = "${it.id}"
name = "${it.name}"
email = "${it.eMail}"
}
""" }}
}
licenses {
${licenses.joinToString("\n") { """
license {
name = "${it.title}"
url = "${it.url}"
}
""" }}
}
}
repositories {
${repositories.joinToString("\n ") { it.build(" ") }}
}
}
}
}
${gpgSigning.generateMavenConfig()}
""".trimIndent()

View File

@@ -1,69 +1,64 @@
package dev.inmo.kmppscriptbuilder.core.export.jvm_only
import dev.inmo.kmppscriptbuilder.core.export.generateMavenConfig
import dev.inmo.kmppscriptbuilder.core.models.*
fun MavenConfig.buildJvmOnlyMavenConfig(licenses: List<License>): String = """
apply plugin: 'maven-publish'
${if (includeGpgSigning) "apply plugin: 'signing'\n" else ""}
task javadocJar(type: Jar) {
from javadoc
classifier = 'javadoc'
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}
apply plugin: 'maven-publish'
publishing {
publications {
maven(MavenPublication) {
from components.java
artifact javadocJar
artifact sourcesJar
task javadocJar(type: Jar) {
from javadoc
classifier = 'javadoc'
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}
pom {
resolveStrategy = Closure.DELEGATE_FIRST
publishing {
publications {
maven(MavenPublication) {
from components.java
description = "$description"
name = "$name"
url = "$url"
artifact javadocJar
artifact sourcesJar
scm {
developerConnection = "scm:git:[fetch=]${vcsUrl}[push=]${vcsUrl}"
url = "$vcsUrl"
}
pom {
resolveStrategy = Closure.DELEGATE_FIRST
developers {
${developers.joinToString("\n") { """
developer {
id = "${it.id}"
name = "${it.name}"
email = "${it.eMail}"
}
""" }}
}
description = "$description"
name = "$name"
url = "$url"
licenses {
${licenses.joinToString("\n") { """
license {
name = "${it.title}"
url = "${it.url}"
}
""" }}
}
scm {
developerConnection = "scm:git:[fetch=]${vcsUrl}[push=]${vcsUrl}"
url = "$vcsUrl"
}
repositories {
${repositories.joinToString("\n ") { it.build(" ") }}
developers {
${developers.joinToString("\n") { """
developer {
id = "${it.id}"
name = "${it.name}"
email = "${it.eMail}"
}
""" }}
}
licenses {
${licenses.joinToString("\n") { """
license {
name = "${it.title}"
url = "${it.url}"
}
""" }}
}
}
repositories {
${repositories.joinToString("\n ") { it.build(" ") }}
}
}
}
${if (includeGpgSigning) """
signing {
useGpgCmd()
sign publishing.publications
}
""" else ""}
""".trimIndent()
}
${gpgSigning.generateMavenConfig()}
""".trimIndent()

View File

@@ -1,56 +1,52 @@
package dev.inmo.kmppscriptbuilder.core.export.mpp
import dev.inmo.kmppscriptbuilder.core.export.generateMavenConfig
import dev.inmo.kmppscriptbuilder.core.models.*
fun MavenConfig.buildMultiplatformMavenConfig(licenses: List<License>): String = """
apply plugin: 'maven-publish'
${if (includeGpgSigning) "apply plugin: 'signing'\n" else ""}
task javadocsJar(type: Jar) {
classifier = 'javadoc'
}
apply plugin: 'maven-publish'
publishing {
publications.all {
artifact javadocsJar
task javadocsJar(type: Jar) {
classifier = 'javadoc'
}
pom {
description = "$description"
name = "$name"
url = "$url"
publishing {
publications.all {
artifact javadocsJar
scm {
developerConnection = "scm:git:[fetch=]${vcsUrl}[push=]${vcsUrl}"
url = "$vcsUrl"
}
pom {
description = "$description"
name = "$name"
url = "$url"
developers {
${developers.joinToString("\n") { """
developer {
id = "${it.id}"
name = "${it.name}"
email = "${it.eMail}"
}
""" }}
}
licenses {
${licenses.joinToString("\n") { """
license {
name = "${it.title}"
url = "${it.url}"
}
""" }}
}
scm {
developerConnection = "scm:git:[fetch=]${vcsUrl}[push=]${vcsUrl}"
url = "$vcsUrl"
}
repositories {
${repositories.joinToString("\n ") { it.build(" ") }}
developers {
${developers.joinToString("\n") { """
developer {
id = "${it.id}"
name = "${it.name}"
email = "${it.eMail}"
}
""" }}
}
licenses {
${licenses.joinToString("\n") { """
license {
name = "${it.title}"
url = "${it.url}"
}
""" }}
}
}
repositories {
${repositories.joinToString("\n ") { it.build(" ") }}
}
}
${if (includeGpgSigning) """
signing {
useGpgCmd()
sign publishing.publications
}
""" else ""}
""".trimIndent()
}
${gpgSigning.generateMavenConfig()}
""".trimIndent()

View File

@@ -1,5 +1,6 @@
package dev.inmo.kmppscriptbuilder.core.models
import dev.inmo.kmppscriptbuilder.core.export.js_only.buildJsOnlyMavenConfig
import dev.inmo.kmppscriptbuilder.core.export.jvm_only.buildJvmOnlyMavenConfig
import dev.inmo.kmppscriptbuilder.core.export.mpp.buildMultiplatformMavenConfig
import kotlinx.serialization.*
@@ -32,12 +33,6 @@ object ProjectTypeSerializer : KSerializer<ProjectType> {
object MultiplatformProjectType : ProjectType() {
override val name: String = "Multiplatform"
// override fun buildBintrayGradleConfig(
// bintrayConfig: BintrayConfig,
// licenses: List<License>
// ): String = bintrayConfig.buildMultiplatformGradleConfig(
// licenses
// )
override fun buildMavenGradleConfig(
mavenConfig: MavenConfig,
@@ -49,12 +44,6 @@ object MultiplatformProjectType : ProjectType() {
object JVMProjectType : ProjectType() {
override val name: String = "JVM"
// override fun buildBintrayGradleConfig(
// bintrayConfig: BintrayConfig,
// licenses: List<License>
// ): String = bintrayConfig.buildJvmOnlyGradleConfig(
// licenses
// )
override fun buildMavenGradleConfig(
mavenConfig: MavenConfig,
@@ -64,6 +53,15 @@ object JVMProjectType : ProjectType() {
)
}
object JSProjectType : ProjectType() {
override val name: String = "JS"
override fun buildMavenGradleConfig(
mavenConfig: MavenConfig,
licenses: List<License>
): String = mavenConfig.buildJsOnlyMavenConfig(licenses)
}
@Serializable
data class Config(
val licenses: List<License>,

View File

@@ -30,19 +30,19 @@ suspend fun HttpClient.getLicenses(): Map<String, License> {
suspend fun HttpClient.searchLicense(name: String): List<License> {
val licenses = licenses ?: getLicenses()
val lowerCase = name.toLowerCase()
val upperCase = name.toUpperCase()
val lowerCase = name.lowercase()
val upperCase = name.uppercase()
return licenses.values.filter {
it.title.toLowerCase().contains(lowerCase) || it.title.toUpperCase().contains(upperCase) || it.title.contains(name)
|| it.id.toLowerCase().contains(lowerCase) || it.id.toUpperCase().contains(upperCase) || it.id.contains(name)
it.title.lowercase().contains(lowerCase) || it.title.uppercase().contains(upperCase) || it.title.contains(name)
|| it.id.lowercase().contains(lowerCase) || it.id.uppercase().contains(upperCase) || it.id.contains(name)
}
}
fun Map<String, License>.searchLicense(name: String): List<License> {
val lowerCase = name.toLowerCase()
val upperCase = name.toUpperCase()
val lowerCase = name.lowercase()
val upperCase = name.uppercase()
return values.filter {
it.title.toLowerCase().contains(lowerCase) || it.title.toUpperCase().contains(upperCase) || it.title.contains(name)
|| it.id.toLowerCase().contains(lowerCase) || it.id.toUpperCase().contains(upperCase) || it.id.contains(name)
it.title.lowercase().contains(lowerCase) || it.title.uppercase().contains(upperCase) || it.title.contains(name)
|| it.id.lowercase().contains(lowerCase) || it.id.uppercase().contains(upperCase) || it.id.contains(name)
}
}

View File

@@ -2,15 +2,30 @@ package dev.inmo.kmppscriptbuilder.core.models
import kotlinx.serialization.Serializable
const val defaultProjectName = "\${project.name}"
const val defaultProjectDescription = "\${project.name}"
@Serializable
sealed class GpgSigning(val name: String) {
@Serializable
object Disabled : GpgSigning("Disabled")
@Serializable
object Optional : GpgSigning("Optional")
@Serializable
object Enabled : GpgSigning("Enabled")
}
@Serializable
data class MavenConfig(
val name: String,
val description: String,
val url: String,
val vcsUrl: String,
val includeGpgSigning: Boolean = false,
val developers: List<Developer>,
val repositories: List<MavenPublishingRepository> = emptyList()
val repositories: List<MavenPublishingRepository> = emptyList(),
val gpgSigning: GpgSigning = GpgSigning.Disabled,
@Deprecated("Replaced with gpgSigning")
val includeGpgSigning: Boolean = false,
)
@Serializable
@@ -22,14 +37,20 @@ data class MavenPublishingRepository(
name.toUpperCase()
}
fun build(indent: String) = """maven {
name = "$name"
url = uri("$url")
credentials {
username = project.hasProperty('${nameCapitalized}_USER') ? project.property('${nameCapitalized}_USER') : System.getenv('${nameCapitalized}_USER')
password = project.hasProperty('${nameCapitalized}_PASSWORD') ? project.property('${nameCapitalized}_PASSWORD') : System.getenv('${nameCapitalized}_PASSWORD')
fun build(indent: String): String {
val usernameProperty = "${nameCapitalized}_USER"
val passwordProperty = "${nameCapitalized}_PASSWORD"
return """if ((project.hasProperty('${usernameProperty}') || System.getenv('${usernameProperty}') != null) && (project.hasProperty('${passwordProperty}') || System.getenv('${passwordProperty}') != null)) {
maven {
name = "$name"
url = uri("$url")
credentials {
username = project.hasProperty('${usernameProperty}') ? project.property('${usernameProperty}') : System.getenv('${usernameProperty}')
password = project.hasProperty('${passwordProperty}') ? project.property('${passwordProperty}') : System.getenv('${passwordProperty}')
}
}
}""".replace("\n", "\n$indent")
}
}
val SonatypeRepository = MavenPublishingRepository("sonatype", "https://oss.sonatype.org/service/local/staging/deploy/maven2/")

View File

@@ -10,7 +10,6 @@ kotlin {
jvm {
compilations.main.kotlinOptions {
jvmTarget = "11"
useIR = true
}
}
sourceSets {

View File

@@ -1,62 +1,67 @@
package dev.inmo.kmppscriptbuilder.desktop
import androidx.compose.desktop.Window
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
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 dev.inmo.kmppscriptbuilder.desktop.utils.*
import dev.inmo.kmppscriptbuilder.desktop.views.*
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import dev.inmo.kmppscriptbuilder.desktop.utils.init
import dev.inmo.kmppscriptbuilder.desktop.utils.loadConfigFile
import dev.inmo.kmppscriptbuilder.desktop.views.BuilderView
import java.io.File
//private val uncaughtExceptionsBC = BroadcastChannel<DefaultErrorHandler.ErrorEvent>(Channel.CONFLATED)
//val uncaughtExceptionsFlow: Flow<DefaultErrorHandler.ErrorEvent> = uncaughtExceptionsBC.asFlow()
fun main(args: Array<String>) = Window(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)
) {
builder.init()
}
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
adapter = rememberScrollbarAdapter(stateVertical)
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)
) {
builder.init()
}
VerticalScrollbar(
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
adapter = rememberScrollbarAdapter(stateVertical)
)
}
}
if (args.isNotEmpty()) {
val config = loadConfigFile(File(args.first()))
builder.config = config
}
}
if (args.isNotEmpty()) {
val config = loadConfigFile(File(args.first()))
builder.config = config
}
}

View File

@@ -0,0 +1,17 @@
package dev.inmo.kmppscriptbuilder.desktop.utils
import java.awt.Desktop
import java.net.URI
fun openLink(link: String): Boolean {
val desktop = if (Desktop.isDesktopSupported()) Desktop.getDesktop() else null
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
try {
desktop.browse(URI(link))
return true
} catch (e: Exception) {
e.printStackTrace()
}
}
return false
}

View File

@@ -1,12 +1,14 @@
package dev.inmo.kmppscriptbuilder.desktop.views
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.svgResource
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import dev.inmo.kmppscriptbuilder.core.models.Config
import dev.inmo.kmppscriptbuilder.desktop.utils.*
@@ -28,6 +30,34 @@ class BuilderView : View() {
saveAvailableState = true
}
@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
)
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
override fun build() {
Box(Modifier.fillMaxSize()) {
@@ -37,56 +67,28 @@ class BuilderView : View() {
CommonText("Kotlin publication scripts builder", Modifier.clickable { println(config) })
},
actions = {
IconButton(
{
loadConfig()?.also {
config = it
}
}
) {
Image(
painter = svgResource("images/open_file.svg"),
contentDescription = "Open file"
)
}
if (saveAvailableState) {
IconButton(
{
saveConfig(config)
}
) {
Image(
painter = svgResource("images/save_file.svg"),
contentDescription = "Save file"
)
createIcon("Open file", "images/open_file.svg") {
loadConfig()?.also {
config = it
}
}
if (saveAvailableState) {
IconButton(
{
exportGradle(config)
}
) {
Image(
painter = svgResource("images/export_gradle.svg"),
contentDescription = "Export Gradle script"
)
createIcon("Save", "images/save_file.svg") {
saveConfig(config)
}
}
IconButton(
{
if (saveAs(config)) {
saveAvailableState = true
}
if (saveAvailableState) {
createIcon("Export Gradle script", "images/export_gradle.svg") {
exportGradle(config)
}
}
createIcon("Save as", "images/save_as.svg") {
if (saveAs(config)) {
saveAvailableState = true
}
) {
Image(
painter = svgResource("images/save_as.svg"),
contentDescription = "Export Gradle script"
)
}
}
)
@@ -100,4 +102,4 @@ class BuilderView : View() {
}
}
}
}
}

View File

@@ -2,7 +2,7 @@ package dev.inmo.kmppscriptbuilder.desktop.views
import androidx.compose.runtime.*
import dev.inmo.kmppscriptbuilder.core.models.Developer
import dev.inmo.kmppscriptbuilder.desktop.utils.*
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonTextField
class DeveloperState(
id: String = "",

View File

@@ -53,7 +53,7 @@ class LicensesView: VerticalView("Licenses") {
licensesOffersToShow.clear()
if (licenseSearchFilter.isNotEmpty()) {
licensesOffersToShow.addAll(
availableLicensesState.filter { filterText.all { symbol -> symbol.toLowerCase() in it.title } }
availableLicensesState.filter { filterText.all { symbol -> symbol.lowercaseChar() in it.title } }
)
}
}

View File

@@ -1,11 +1,13 @@
package dev.inmo.kmppscriptbuilder.desktop.views
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.material.Button
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.inmo.kmppscriptbuilder.desktop.utils.*
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonText
import dev.inmo.kmppscriptbuilder.desktop.utils.VerticalView
abstract class ListView<T>(title: String) : VerticalView(title) {
protected val itemsList = mutableStateListOf<T>()

View File

@@ -1,9 +1,13 @@
package dev.inmo.kmppscriptbuilder.desktop.views
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import dev.inmo.kmppscriptbuilder.core.models.MavenConfig
import dev.inmo.kmppscriptbuilder.core.models.SonatypeRepository
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") {
@@ -11,37 +15,59 @@ class MavenInfoView : VerticalView("Project information") {
private var projectDescriptionProperty by mutableStateOf("")
private var projectUrlProperty by mutableStateOf("")
private var projectVcsUrlProperty by mutableStateOf("")
private var includeGpgSignProperty by mutableStateOf(true)
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,
projectDescriptionProperty,
projectNameProperty.ifBlank { defaultProjectName },
projectDescriptionProperty.ifBlank { defaultProjectDescription },
projectUrlProperty,
projectVcsUrlProperty,
includeGpgSignProperty,
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
includeGpgSignProperty = value.includeGpgSigning
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,
@@ -60,11 +86,12 @@ class MavenInfoView : VerticalView("Project information") {
"Public project VCS URL (with .git)"
) { projectVcsUrlProperty = it }
SwitchWithLabel(
"Include GPG Signing",
includeGpgSignProperty,
placeSwitchAtTheStart = true
) { includeGpgSignProperty = it }
Row(verticalAlignment = Alignment.CenterVertically) {
Text("Gpg Signing: ")
addGpgSigningButton(GpgSigning.Disabled)
addGpgSigningButton(GpgSigning.Optional)
addGpgSigningButton(GpgSigning.Enabled)
}
SwitchWithLabel(
"Include publication to MavenCentral",
@@ -74,4 +101,4 @@ class MavenInfoView : VerticalView("Project information") {
developersView.init()
repositoriesView.init()
}
}
}

View File

@@ -1,33 +1,40 @@
package dev.inmo.kmppscriptbuilder.desktop.views
import androidx.compose.foundation.layout.*
import androidx.compose.material.Switch
import androidx.compose.material.Text
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") {
private var projectTypeState by mutableStateOf<Boolean>(false)
private val calculatedProjectType: ProjectType
get() = if (projectTypeState) JVMProjectType else MultiplatformProjectType
var projectType: ProjectType
get() = calculatedProjectType
set(value) {
projectTypeState = value == JVMProjectType
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(horizontalArrangement = Arrangement.spacedBy(5.dp)) {
Text("Multiplatform", Modifier.alignByBaseline())
Switch(
projectTypeState,
{ projectTypeState = it },
Modifier.padding(4.dp, 0.dp)
)
Text("JVM", Modifier.alignByBaseline())
Row(verticalAlignment = Alignment.CenterVertically) {
addProjectTypeButton(MultiplatformProjectType)
addProjectTypeButton(JVMProjectType)
addProjectTypeButton(JSProjectType)
}
}
}

View File

@@ -2,7 +2,7 @@ package dev.inmo.kmppscriptbuilder.desktop.views
import androidx.compose.runtime.*
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
import dev.inmo.kmppscriptbuilder.desktop.utils.*
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonTextField
class RepositoryState(
name: String = "",

View File

@@ -6,27 +6,27 @@ kotlin.incremental.js=true
android.useAndroidX=true
android.enableJetifier=true
kotlin_version=1.4.30
kotlin_coroutines_version=1.4.2
kotlin_serialisation_core_version=1.1.0
ktor_version=1.5.1
micro_utils_version=0.4.27
kotlin_version=1.6.10
kotlin_coroutines_version=1.6.0
kotlin_serialisation_core_version=1.3.2
ktor_version=1.6.7
micro_utils_version=0.9.0
compose_version=0.3.0
compose_version=1.0.1
# ANDROID
android_minSdkVersion=21
android_compileSdkVersion=30
android_buildToolsVersion=30.0.2
dexcount_version=2.0.0
android_compileSdkVersion=32
android_buildToolsVersion=32.0.0
dexcount_version=3.0.1
junit_version=4.12
test_ext_junit_version=1.1.2
espresso_core=3.3.0
# Dokka
dokka_version=1.4.20
dokka_version=1.6.0
# Project data

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip

View File

@@ -14,12 +14,11 @@ fun saveFile(content: String, filename: String) {
setAttribute("style", "visibility:hidden; display: none")
} as HTMLAnchorElement
val blob = Blob(arrayOf(content), BlobPropertyBag(
"text/plain;charset=utf-8"
"application/*;charset=utf-8"
))
val url = URL.createObjectURL(blob)
a.href = url
a.download = filename
a.target = "_blank"
a.click()
URL.revokeObjectURL(url)
a.remove()

View File

@@ -48,7 +48,7 @@ class LicensesView(
emptyList()
} else {
licensesTemplates.filter {
val lowercasedTitle = it.title.toLowerCase()
val lowercasedTitle = it.title.lowercase()
lowercased.all { it in lowercasedTitle }
}
}
@@ -57,12 +57,12 @@ class LicensesView(
}
private val searchElement = rootElement.createTextField("Quick add", "Type some license name part to find it").apply {
oninput = {
changeActor.offer(Unit)
changeActor.trySend(Unit)
false
}
}
private var searchString: String
get() = searchElement.value.toLowerCase()
get() = searchElement.value.lowercase()
set(value) {
searchElement.value = value
}
@@ -71,7 +71,7 @@ class LicensesView(
createCommonButton(value.title).onclick = {
searchString = ""
licensesView.licenses += value
changeActor.offer(Unit)
changeActor.trySend(Unit)
false
}
}
@@ -110,4 +110,4 @@ class LicensesView(
titleElement.value = to.title
urlElement.value = to.url ?: ""
}
}
}

View File

@@ -1,7 +1,7 @@
package dev.inmo.kmppscriptbuilder.web.views
import dev.inmo.kmppscriptbuilder.core.models.MavenConfig
import dev.inmo.kmppscriptbuilder.core.models.SonatypeRepository
import dev.inmo.kmppscriptbuilder.core.models.*
import dev.inmo.kmppscriptbuilder.web.utils.ukActive
import kotlinx.browser.document
import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLInputElement
@@ -11,23 +11,51 @@ class MavenProjectInfoView : View {
private val descriptionElement = document.getElementById("projectDescriptionInput") as HTMLInputElement
private val urlElement = document.getElementById("projectUrlInput") as HTMLInputElement
private val vcsUrlElement = document.getElementById("projectVCSUrlInput") as HTMLInputElement
private val includeGpgElement = document.getElementById("includeGpgSignToggle") as HTMLInputElement
private val disableGpgSigningElement = document.getElementById("disableGpgSigning") as HTMLElement
private val optionalGpgSigningElement = document.getElementById("optionalGpgSigning") as HTMLElement
private val enableGpgSigningElement = document.getElementById("enableGpgSigning") as HTMLElement
private val includeMavenCentralElement = document.getElementById("includeMavenCentralTargetRepoToggle") as HTMLInputElement
private val developersView = DevelopersView(document.getElementById("developersListDiv") as HTMLElement)
private val repositoriesView = RepositoriesView(document.getElementById("repositoriesListDiv") as HTMLElement)
private var gpgSignMode: GpgSigning = GpgSigning.Disabled
set(value) {
field = value
when (value) {
GpgSigning.Enabled -> {
enableGpgSigningElement.ukActive = true
disableGpgSigningElement.ukActive = false
optionalGpgSigningElement.ukActive = false
}
GpgSigning.Optional -> {
enableGpgSigningElement.ukActive = false
disableGpgSigningElement.ukActive = false
optionalGpgSigningElement.ukActive = true
}
GpgSigning.Disabled -> {
enableGpgSigningElement.ukActive = false
disableGpgSigningElement.ukActive = true
optionalGpgSigningElement.ukActive = false
}
}
}
var mavenConfig: MavenConfig
get() = MavenConfig(
nameElement.value,
descriptionElement.value,
nameElement.value.ifBlank { defaultProjectName },
descriptionElement.value.ifBlank { defaultProjectDescription },
urlElement.value,
vcsUrlElement.value,
includeGpgElement.checked,
developersView.developers,
repositoriesView.repositories + if (includeMavenCentralElement.checked) {
listOf(SonatypeRepository)
} else {
emptyList()
},
when {
optionalGpgSigningElement.ukActive -> GpgSigning.Optional
enableGpgSigningElement.ukActive -> GpgSigning.Enabled
else -> GpgSigning.Disabled
}
)
set(value) {
@@ -35,10 +63,20 @@ class MavenProjectInfoView : View {
descriptionElement.value = value.description
urlElement.value = value.url
vcsUrlElement.value = value.vcsUrl
includeGpgElement.checked = value.includeGpgSigning
gpgSignMode = if (value.includeGpgSigning) {
GpgSigning.Enabled
} else {
value.gpgSigning
}
developersView.developers = value.developers
val reposWithoutSonatype = value.repositories.filter { it != SonatypeRepository }
includeMavenCentralElement.checked = value.repositories.size != reposWithoutSonatype.size
repositoriesView.repositories = value.repositories
repositoriesView.repositories = reposWithoutSonatype
}
}
init {
enableGpgSigningElement.onclick = { gpgSignMode = GpgSigning.Enabled; Unit }
disableGpgSigningElement.onclick = { gpgSignMode = GpgSigning.Disabled; Unit }
optionalGpgSigningElement.onclick = { gpgSignMode = GpgSigning.Optional; Unit }
}
}

View File

@@ -8,16 +8,18 @@ import org.w3c.dom.HTMLElement
class ProjectTypeView : View {
private val mppProjectTypeElement = document.getElementById("mppProjectType") as HTMLElement
private val jvmProjectTypeElement = document.getElementById("jvmProjectType") as HTMLElement
private val jsProjectTypeElement = document.getElementById("jsProjectType") as HTMLElement
var projectType: ProjectType
get() = if (jvmProjectTypeElement.ukActive) {
JVMProjectType
} else {
MultiplatformProjectType
get() = when {
jvmProjectTypeElement.ukActive -> JVMProjectType
jsProjectTypeElement.ukActive -> JSProjectType
else -> MultiplatformProjectType
}
set(value) {
mppProjectTypeElement.ukActive = value == MultiplatformProjectType
jvmProjectTypeElement.ukActive = value == JVMProjectType
jsProjectTypeElement.ukActive = value == JSProjectType
}
init {
@@ -29,5 +31,9 @@ class ProjectTypeView : View {
projectType = JVMProjectType
Unit
}
jsProjectTypeElement.onclick = {
projectType = JSProjectType
Unit
}
}
}
}

View File

@@ -21,7 +21,7 @@ class RepositoriesView(rootElement: HTMLElement) : MutableListView<MavenPublishi
override fun HTMLElement.addContentBeforeRemoveButton(value: MavenPublishingRepository) {
createTextField("Repository name", "This name will be used to identify repository in grade").value = value.name
createTextField("Repository URL", "For example: https://repo.maven.apache.org/maven2/").value = value.name
createTextField("Repository URL", "For example: https://repo.maven.apache.org/maven2/").value = value.url
}
override fun HTMLElement.updateElement(from: MavenPublishingRepository, to: MavenPublishingRepository) {

View File

@@ -10,6 +10,7 @@
<nav class="uk-navbar-container" uk-navbar>
<div class="uk-navbar-left">
<div class="uk-padding-small uk-text-lead">Kotlin Publication Scripts Builder</div>
<div class="uk-padding-small"><a href="https://github.com/InsanusMokrassar/KotlinPublicationScriptsBuilder"><img src="https://img.shields.io/github/stars/InsanusMokrassar/KotlinPublicationScriptsBuilder?label=Github&style=plastic"/></a></div>
</div>
<div class="uk-navbar-right">
<ul class="uk-navbar-nav">
@@ -26,15 +27,11 @@
<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 class="uk-margin uk-width-1-1">-->
<!-- <input id="searchFilterInput" class="uk-input uk-width-expand" type="text" placeholder="License search filter">-->
<!-- </div>-->
<!-- <button class="uk-button uk-button-primary">Add empty license</button>-->
</div>
<div id="licensesListDiv" class="uk-padding-small"></div>
<legend class="uk-legend">Project information</legend>
@@ -57,7 +54,15 @@
</div>
<div class="uk-margin">
<label><input id="includeGpgSignToggle" class="uk-checkbox" type="checkbox" checked> Include GPG Signing</label>
<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>
@@ -77,4 +82,4 @@
<!-- Internal JS -->
<script src="kmppscriptbuilder.web.js"></script>
</body>
</html>
</html>