Compare commits
	
		
			21 Commits
		
	
	
		
			build-7c50
			...
			build-3c21
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3c216af814 | |||
| 6b5ab5acba | |||
| f723d55d7e | |||
| c0d0b7521e | |||
| 7536c67589 | |||
| 0770772e7d | |||
| c6b1289f5a | |||
| 788fe49aa4 | |||
| 3be0f24eac | |||
| 9fe7c458e9 | |||
| 8430e68167 | |||
| 53a76c7a73 | |||
| 70baa30127 | |||
| 283bc5acb4 | |||
| 26a5d20e26 | |||
| ca1a91e0f0 | |||
| 26fe225577 | |||
| 9a95bddf08 | |||
| c880d8e657 | |||
| ac87a140cc | |||
| 0dbe3a866b | 
							
								
								
									
										10
									
								
								.github/workflows/commit-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -19,12 +19,12 @@ jobs:
 | 
				
			|||||||
      - name: Set version from gradle.properties
 | 
					      - name: Set version from gradle.properties
 | 
				
			||||||
        run: echo "version=` cat gradle.properties | grep ^version= | grep -o [\\.0-9]* `" >> $GITHUB_ENV
 | 
					        run: echo "version=` cat gradle.properties | grep ^version= | grep -o [\\.0-9]* `" >> $GITHUB_ENV
 | 
				
			||||||
      - name: Build
 | 
					      - name: Build
 | 
				
			||||||
        run: ./gradlew build packageUberJarForCurrentOS
 | 
					        run: ./gradlew build packageReleaseUberJarForCurrentOS
 | 
				
			||||||
      - name: Publish Web
 | 
					      - name: Publish Web
 | 
				
			||||||
        uses: peaceiris/actions-gh-pages@v3
 | 
					        uses: peaceiris/actions-gh-pages@v3
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          github_token: ${{ secrets.GITHUB_TOKEN }}
 | 
					          github_token: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
          publish_dir: ./web/build/distributions
 | 
					          publish_dir: ./core/build/distributions
 | 
				
			||||||
          publish_branch: site
 | 
					          publish_branch: site
 | 
				
			||||||
      - name: Create Release
 | 
					      - name: Create Release
 | 
				
			||||||
        id: create_release
 | 
					        id: create_release
 | 
				
			||||||
@@ -38,12 +38,12 @@ jobs:
 | 
				
			|||||||
          draft: false
 | 
					          draft: false
 | 
				
			||||||
          prerelease: true
 | 
					          prerelease: true
 | 
				
			||||||
      - name: Upload Ubuntu Release Asset
 | 
					      - name: Upload Ubuntu Release Asset
 | 
				
			||||||
        id: upload-ubuntu-release-asset 
 | 
					        id: upload-ubuntu-release-asset
 | 
				
			||||||
        uses: actions/upload-release-asset@v1
 | 
					        uses: actions/upload-release-asset@v1
 | 
				
			||||||
        env:
 | 
					        env:
 | 
				
			||||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
					          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 
 | 
					          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
 | 
				
			||||||
          asset_path: "./desktop/build/compose/jars/kmppscriptbuilder.desktop-linux-x64-${{ env.version }}${{ env.additional_version }}.jar"
 | 
					          asset_path: "core/build/compose/jars/*.jar"
 | 
				
			||||||
          asset_name: KotlinPublicationScriptsBuilder-linux-x64.jar
 | 
					          asset_name: KotlinPublicationScriptsBuilder-linux-x64.jar
 | 
				
			||||||
          asset_content_type: application/java-archive
 | 
					          asset_content_type: application/java-archive
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -10,3 +10,4 @@ build/
 | 
				
			|||||||
out/
 | 
					out/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local.properties
 | 
					local.properties
 | 
				
			||||||
 | 
					kotlin-js-store/
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						@@ -1,6 +1,5 @@
 | 
				
			|||||||
buildscript {
 | 
					buildscript {
 | 
				
			||||||
    repositories {
 | 
					    repositories {
 | 
				
			||||||
        jcenter()
 | 
					 | 
				
			||||||
        google()
 | 
					        google()
 | 
				
			||||||
        mavenCentral()
 | 
					        mavenCentral()
 | 
				
			||||||
        mavenLocal()
 | 
					        mavenLocal()
 | 
				
			||||||
@@ -8,21 +7,18 @@ buildscript {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dependencies {
 | 
					    dependencies {
 | 
				
			||||||
        classpath 'com.android.tools.build:gradle:4.0.2'
 | 
					        classpath libs.buildscript.kt.gradle
 | 
				
			||||||
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 | 
					        classpath libs.buildscript.kt.serialization
 | 
				
			||||||
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
 | 
					        classpath libs.buildscript.jb.dokka
 | 
				
			||||||
        classpath "com.getkeepsafe.dexcount:dexcount-gradle-plugin:$dexcount_version"
 | 
					        classpath libs.buildscript.gh.release
 | 
				
			||||||
        classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
allprojects {
 | 
					allprojects {
 | 
				
			||||||
    repositories {
 | 
					    repositories {
 | 
				
			||||||
        mavenLocal()
 | 
					        mavenLocal()
 | 
				
			||||||
        jcenter()
 | 
					 | 
				
			||||||
        mavenCentral()
 | 
					        mavenCentral()
 | 
				
			||||||
        google()
 | 
					        google()
 | 
				
			||||||
        maven { url "https://kotlin.bintray.com/kotlinx" }
 | 
					 | 
				
			||||||
        maven { url "https://maven.pkg.jetbrains.space/public/p/compose/dev" }
 | 
					        maven { url "https://maven.pkg.jetbrains.space/public/p/compose/dev" }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,20 +1,46 @@
 | 
				
			|||||||
plugins {
 | 
					plugins {
 | 
				
			||||||
    id "org.jetbrains.kotlin.multiplatform"
 | 
					    id "org.jetbrains.kotlin.multiplatform"
 | 
				
			||||||
    id "org.jetbrains.kotlin.plugin.serialization"
 | 
					    id "org.jetbrains.kotlin.plugin.serialization"
 | 
				
			||||||
    id "com.android.library"
 | 
					    alias(libs.plugins.jb.compose)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
apply from: "$mppProjectWithSerializationPresetPath"
 | 
					apply from: "$mppProjectWithSerializationPresetPath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kotlin {
 | 
					kotlin {
 | 
				
			||||||
 | 
					    js (IR) {
 | 
				
			||||||
 | 
					        binaries.executable()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    sourceSets {
 | 
					    sourceSets {
 | 
				
			||||||
        commonMain {
 | 
					        commonMain {
 | 
				
			||||||
            dependencies {
 | 
					            dependencies {
 | 
				
			||||||
                api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
 | 
					                api libs.kt.coroutines
 | 
				
			||||||
                api "dev.inmo:micro_utils.coroutines:$micro_utils_version"
 | 
					                api libs.microutils.common
 | 
				
			||||||
 | 
					                api libs.microutils.coroutines
 | 
				
			||||||
                api "io.ktor:ktor-client-core:$ktor_version"
 | 
					                api libs.ktor.client
 | 
				
			||||||
 | 
					                api(compose.runtime)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        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"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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()
 | 
				
			||||||
@@ -1,69 +1,64 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.core.export.jvm_only
 | 
					package dev.inmo.kmppscriptbuilder.core.export.jvm_only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.export.generateMavenConfig
 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.*
 | 
					import dev.inmo.kmppscriptbuilder.core.models.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun MavenConfig.buildJvmOnlyMavenConfig(licenses: List<License>): String = """
 | 
					fun MavenConfig.buildJvmOnlyMavenConfig(licenses: List<License>): String = """
 | 
				
			||||||
    apply plugin: 'maven-publish'
 | 
					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'
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    publishing {
 | 
					task javadocJar(type: Jar) {
 | 
				
			||||||
        publications {
 | 
					    from javadoc
 | 
				
			||||||
            maven(MavenPublication) {
 | 
					    classifier = 'javadoc'
 | 
				
			||||||
                from components.java
 | 
					}
 | 
				
			||||||
    
 | 
					task sourcesJar(type: Jar) {
 | 
				
			||||||
                artifact javadocJar
 | 
					    from sourceSets.main.allSource
 | 
				
			||||||
                artifact sourcesJar
 | 
					    classifier = 'sources'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                pom {
 | 
					publishing {
 | 
				
			||||||
                    resolveStrategy = Closure.DELEGATE_FIRST
 | 
					    publications {
 | 
				
			||||||
 | 
					        maven(MavenPublication) {
 | 
				
			||||||
 | 
					            from components.java
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    description = "$description"
 | 
					            artifact javadocJar
 | 
				
			||||||
                    name = "$name"
 | 
					            artifact sourcesJar
 | 
				
			||||||
                    url = "$url"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    scm {
 | 
					            pom {
 | 
				
			||||||
                        developerConnection = "scm:git:[fetch=]${vcsUrl}[push=]${vcsUrl}"
 | 
					                resolveStrategy = Closure.DELEGATE_FIRST
 | 
				
			||||||
                        url = "$vcsUrl"
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    developers {
 | 
					                description = "$description"
 | 
				
			||||||
                        ${developers.joinToString("\n") { """
 | 
					                name = "$name"
 | 
				
			||||||
                            developer {
 | 
					                url = "$url"
 | 
				
			||||||
                                id = "${it.id}"
 | 
					 | 
				
			||||||
                                name = "${it.name}"
 | 
					 | 
				
			||||||
                                email = "${it.eMail}"
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        """ }}
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    licenses {
 | 
					                scm {
 | 
				
			||||||
                        ${licenses.joinToString("\n") { """
 | 
					                    developerConnection = "scm:git:[fetch=]${vcsUrl}[push=]${vcsUrl}"
 | 
				
			||||||
                            license {
 | 
					                    url = "$vcsUrl"
 | 
				
			||||||
                                name = "${it.title}"
 | 
					 | 
				
			||||||
                                url = "${it.url}"
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        """ }}
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                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 {
 | 
					${gpgSigning.generateMavenConfig()}
 | 
				
			||||||
        useGpgCmd()
 | 
					""".trimIndent()
 | 
				
			||||||
        sign publishing.publications
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    """ else ""}
 | 
					 | 
				
			||||||
""".trimIndent()
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,56 +1,52 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.core.export.mpp
 | 
					package dev.inmo.kmppscriptbuilder.core.export.mpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.export.generateMavenConfig
 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.*
 | 
					import dev.inmo.kmppscriptbuilder.core.models.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun MavenConfig.buildMultiplatformMavenConfig(licenses: List<License>): String = """
 | 
					fun MavenConfig.buildMultiplatformMavenConfig(licenses: List<License>): String = """
 | 
				
			||||||
    apply plugin: 'maven-publish'
 | 
					apply plugin: 'maven-publish'
 | 
				
			||||||
    ${if (includeGpgSigning) "apply plugin: 'signing'\n" else ""}
 | 
					 | 
				
			||||||
    task javadocsJar(type: Jar) {
 | 
					 | 
				
			||||||
        classifier = 'javadoc'
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    publishing {
 | 
					task javadocsJar(type: Jar) {
 | 
				
			||||||
        publications.all {
 | 
					    classifier = 'javadoc'
 | 
				
			||||||
            artifact javadocsJar
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            pom {
 | 
					publishing {
 | 
				
			||||||
                description = "$description"
 | 
					    publications.all {
 | 
				
			||||||
                name = "$name"
 | 
					        artifact javadocsJar
 | 
				
			||||||
                url = "$url"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                scm {
 | 
					        pom {
 | 
				
			||||||
                    developerConnection = "scm:git:[fetch=]${vcsUrl}[push=]${vcsUrl}"
 | 
					            description = "$description"
 | 
				
			||||||
                    url = "$vcsUrl"
 | 
					            name = "$name"
 | 
				
			||||||
                }
 | 
					            url = "$url"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                developers {
 | 
					            scm {
 | 
				
			||||||
                    ${developers.joinToString("\n") { """
 | 
					                developerConnection = "scm:git:[fetch=]${vcsUrl}[push=]${vcsUrl}"
 | 
				
			||||||
                        developer {
 | 
					                url = "$vcsUrl"
 | 
				
			||||||
                            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("                ") }}
 | 
					            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 {
 | 
					    ${gpgSigning.generateMavenConfig()}
 | 
				
			||||||
        useGpgCmd()
 | 
					""".trimIndent()
 | 
				
			||||||
        sign publishing.publications
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    """ else ""}
 | 
					 | 
				
			||||||
""".trimIndent()
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.core.models
 | 
					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.jvm_only.buildJvmOnlyMavenConfig
 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.export.mpp.buildMultiplatformMavenConfig
 | 
					import dev.inmo.kmppscriptbuilder.core.export.mpp.buildMultiplatformMavenConfig
 | 
				
			||||||
import kotlinx.serialization.*
 | 
					import kotlinx.serialization.*
 | 
				
			||||||
@@ -32,12 +33,6 @@ object ProjectTypeSerializer : KSerializer<ProjectType> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
object MultiplatformProjectType : ProjectType() {
 | 
					object MultiplatformProjectType : ProjectType() {
 | 
				
			||||||
    override val name: String = "Multiplatform"
 | 
					    override val name: String = "Multiplatform"
 | 
				
			||||||
//    override fun buildBintrayGradleConfig(
 | 
					 | 
				
			||||||
//        bintrayConfig: BintrayConfig,
 | 
					 | 
				
			||||||
//        licenses: List<License>
 | 
					 | 
				
			||||||
//    ): String = bintrayConfig.buildMultiplatformGradleConfig(
 | 
					 | 
				
			||||||
//        licenses
 | 
					 | 
				
			||||||
//    )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun buildMavenGradleConfig(
 | 
					    override fun buildMavenGradleConfig(
 | 
				
			||||||
        mavenConfig: MavenConfig,
 | 
					        mavenConfig: MavenConfig,
 | 
				
			||||||
@@ -49,12 +44,6 @@ object MultiplatformProjectType : ProjectType() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
object JVMProjectType : ProjectType() {
 | 
					object JVMProjectType : ProjectType() {
 | 
				
			||||||
    override val name: String = "JVM"
 | 
					    override val name: String = "JVM"
 | 
				
			||||||
//    override fun buildBintrayGradleConfig(
 | 
					 | 
				
			||||||
//        bintrayConfig: BintrayConfig,
 | 
					 | 
				
			||||||
//        licenses: List<License>
 | 
					 | 
				
			||||||
//    ): String = bintrayConfig.buildJvmOnlyGradleConfig(
 | 
					 | 
				
			||||||
//        licenses
 | 
					 | 
				
			||||||
//    )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun buildMavenGradleConfig(
 | 
					    override fun buildMavenGradleConfig(
 | 
				
			||||||
        mavenConfig: MavenConfig,
 | 
					        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
 | 
					@Serializable
 | 
				
			||||||
data class Config(
 | 
					data class Config(
 | 
				
			||||||
    val licenses: List<License>,
 | 
					    val licenses: List<License>,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
 | 
				
			|||||||
import io.ktor.client.HttpClient
 | 
					import io.ktor.client.HttpClient
 | 
				
			||||||
import io.ktor.client.request.get
 | 
					import io.ktor.client.request.get
 | 
				
			||||||
import io.ktor.client.request.url
 | 
					import io.ktor.client.request.url
 | 
				
			||||||
 | 
					import io.ktor.client.statement.bodyAsText
 | 
				
			||||||
import kotlinx.serialization.Serializable
 | 
					import kotlinx.serialization.Serializable
 | 
				
			||||||
import kotlinx.serialization.builtins.MapSerializer
 | 
					import kotlinx.serialization.builtins.MapSerializer
 | 
				
			||||||
import kotlinx.serialization.builtins.serializer
 | 
					import kotlinx.serialization.builtins.serializer
 | 
				
			||||||
@@ -20,9 +21,9 @@ private val commonLicensesListDeserializer = MapSerializer(String.serializer(),
 | 
				
			|||||||
private var licenses: Map<String, License>? = null
 | 
					private var licenses: Map<String, License>? = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
suspend fun HttpClient.getLicenses(): Map<String, License> {
 | 
					suspend fun HttpClient.getLicenses(): Map<String, License> {
 | 
				
			||||||
    val answer = get<String> {
 | 
					    val answer = get {
 | 
				
			||||||
        url("https://licenses.opendefinition.org/licenses/groups/all.json")
 | 
					        url("https://licenses.opendefinition.org/licenses/groups/all.json")
 | 
				
			||||||
    }
 | 
					    }.bodyAsText()
 | 
				
			||||||
    return serialFormat.decodeFromString(commonLicensesListDeserializer, answer).also { gotLicenses ->
 | 
					    return serialFormat.decodeFromString(commonLicensesListDeserializer, answer).also { gotLicenses ->
 | 
				
			||||||
        licenses = gotLicenses
 | 
					        licenses = gotLicenses
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -30,19 +31,19 @@ suspend fun HttpClient.getLicenses(): Map<String, License> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
suspend fun HttpClient.searchLicense(name: String): List<License> {
 | 
					suspend fun HttpClient.searchLicense(name: String): List<License> {
 | 
				
			||||||
    val licenses = licenses ?: getLicenses()
 | 
					    val licenses = licenses ?: getLicenses()
 | 
				
			||||||
    val lowerCase = name.toLowerCase()
 | 
					    val lowerCase = name.lowercase()
 | 
				
			||||||
    val upperCase = name.toUpperCase()
 | 
					    val upperCase = name.uppercase()
 | 
				
			||||||
    return licenses.values.filter {
 | 
					    return licenses.values.filter {
 | 
				
			||||||
        it.title.toLowerCase().contains(lowerCase) || it.title.toUpperCase().contains(upperCase) || it.title.contains(name)
 | 
					        it.title.lowercase().contains(lowerCase) || it.title.uppercase().contains(upperCase) || it.title.contains(name)
 | 
				
			||||||
            || it.id.toLowerCase().contains(lowerCase) || it.id.toUpperCase().contains(upperCase) || it.id.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> {
 | 
					fun Map<String, License>.searchLicense(name: String): List<License> {
 | 
				
			||||||
    val lowerCase = name.toLowerCase()
 | 
					    val lowerCase = name.lowercase()
 | 
				
			||||||
    val upperCase = name.toUpperCase()
 | 
					    val upperCase = name.uppercase()
 | 
				
			||||||
    return values.filter {
 | 
					    return values.filter {
 | 
				
			||||||
        it.title.toLowerCase().contains(lowerCase) || it.title.toUpperCase().contains(upperCase) || it.title.contains(name)
 | 
					        it.title.lowercase().contains(lowerCase) || it.title.uppercase().contains(upperCase) || it.title.contains(name)
 | 
				
			||||||
            || it.id.toLowerCase().contains(lowerCase) || it.id.toUpperCase().contains(upperCase) || it.id.contains(name)
 | 
					            || it.id.lowercase().contains(lowerCase) || it.id.uppercase().contains(upperCase) || it.id.contains(name)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,37 +5,110 @@ import kotlinx.serialization.Serializable
 | 
				
			|||||||
const val defaultProjectName = "\${project.name}"
 | 
					const val defaultProjectName = "\${project.name}"
 | 
				
			||||||
const val defaultProjectDescription = "\${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
 | 
					@Serializable
 | 
				
			||||||
data class MavenConfig(
 | 
					data class MavenConfig(
 | 
				
			||||||
    val name: String,
 | 
					    val name: String,
 | 
				
			||||||
    val description: String,
 | 
					    val description: String,
 | 
				
			||||||
    val url: String,
 | 
					    val url: String,
 | 
				
			||||||
    val vcsUrl: String,
 | 
					    val vcsUrl: String,
 | 
				
			||||||
    val includeGpgSigning: Boolean = false,
 | 
					 | 
				
			||||||
    val developers: List<Developer>,
 | 
					    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
 | 
					@Serializable
 | 
				
			||||||
data class MavenPublishingRepository(
 | 
					data class MavenPublishingRepository(
 | 
				
			||||||
    val name: String,
 | 
					    val name: String,
 | 
				
			||||||
    val url: String
 | 
					    val url: String,
 | 
				
			||||||
 | 
					    val credsType: CredentialsType = CredentialsType.UsernameAndPassword(
 | 
				
			||||||
 | 
					        CredentialsType.UsernameAndPassword.defaultUsernameProperty(name),
 | 
				
			||||||
 | 
					        CredentialsType.UsernameAndPassword.defaultPasswordProperty(name),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    private val nameCapitalized by lazy {
 | 
					 | 
				
			||||||
        name.toUpperCase()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun build(indent: String): String {
 | 
					    @Serializable
 | 
				
			||||||
        val usernameProperty = "${nameCapitalized}_USER"
 | 
					    sealed interface CredentialsType {
 | 
				
			||||||
        val passwordProperty = "${nameCapitalized}_PASSWORD"
 | 
					        @Serializable
 | 
				
			||||||
        return """if ((project.hasProperty('${usernameProperty}') || System.getenv('${usernameProperty}') != null) && (project.hasProperty('${passwordProperty}') || System.getenv('${passwordProperty}') != null)) {
 | 
					        object Nothing: CredentialsType {
 | 
				
			||||||
    maven {
 | 
					            override fun buildCheckPart(): String = "true"
 | 
				
			||||||
        name = "$name"
 | 
					            override fun buildCredsPart(): String = ""
 | 
				
			||||||
        url = uri("$url")
 | 
					        }
 | 
				
			||||||
 | 
					        @Serializable
 | 
				
			||||||
 | 
					        data class UsernameAndPassword(
 | 
				
			||||||
 | 
					            val usernameProperty: String,
 | 
				
			||||||
 | 
					            val passwordProperty: String
 | 
				
			||||||
 | 
					        ): CredentialsType {
 | 
				
			||||||
 | 
					            constructor(baseParameter: String) : this(
 | 
				
			||||||
 | 
					                defaultUsernameProperty(baseParameter),
 | 
				
			||||||
 | 
					                defaultPasswordProperty(baseParameter)
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            override fun buildCheckPart(): String = "(project.hasProperty('${usernameProperty}') || System.getenv('${usernameProperty}') != null) && (project.hasProperty('${passwordProperty}') || System.getenv('${passwordProperty}') != null)"
 | 
				
			||||||
 | 
					            override fun buildCredsPart(): String {
 | 
				
			||||||
 | 
					return """
 | 
				
			||||||
        credentials {
 | 
					        credentials {
 | 
				
			||||||
            username = project.hasProperty('${usernameProperty}') ? project.property('${usernameProperty}') : System.getenv('${usernameProperty}')
 | 
					            username = project.hasProperty('${usernameProperty}') ? project.property('${usernameProperty}') : System.getenv('${usernameProperty}')
 | 
				
			||||||
            password = project.hasProperty('${passwordProperty}') ? project.property('${passwordProperty}') : System.getenv('${passwordProperty}')
 | 
					            password = project.hasProperty('${passwordProperty}') ? project.property('${passwordProperty}') : System.getenv('${passwordProperty}')
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            companion object {
 | 
				
			||||||
 | 
					                fun defaultUsernameProperty(name: String): String {
 | 
				
			||||||
 | 
					                    return "${name.uppercase()}_USER"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                fun defaultPasswordProperty(name: String): String {
 | 
				
			||||||
 | 
					                    return "${name.uppercase()}_PASSWORD"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        @Serializable
 | 
				
			||||||
 | 
					        data class HttpHeaderCredentials(
 | 
				
			||||||
 | 
					            val headerName: String,
 | 
				
			||||||
 | 
					            val headerValueProperty: String
 | 
				
			||||||
 | 
					        ): CredentialsType {
 | 
				
			||||||
 | 
					            override fun buildCheckPart(): String = "project.hasProperty('${headerValueProperty}') || System.getenv('${headerValueProperty}') != null"
 | 
				
			||||||
 | 
					            override fun buildCredsPart(): String {
 | 
				
			||||||
 | 
					return """
 | 
				
			||||||
 | 
					        credentials(HttpHeaderCredentials) {
 | 
				
			||||||
 | 
					            name = "$headerName"
 | 
				
			||||||
 | 
					            value = project.hasProperty('${headerValueProperty}') ? project.property('${headerValueProperty}') : System.getenv('${headerValueProperty}')
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            companion object {
 | 
				
			||||||
 | 
					                fun defaultValueProperty(name: String): String {
 | 
				
			||||||
 | 
					                    return "${name.uppercase()}_TOKEN"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fun buildCheckPart(): String
 | 
				
			||||||
 | 
					        fun buildCredsPart(): String
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    private val nameCapitalized by lazy {
 | 
				
			||||||
 | 
					        name.uppercase()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun build(indent: String): String {
 | 
				
			||||||
 | 
					        return """if (${credsType.buildCheckPart()}) {
 | 
				
			||||||
 | 
					    maven {
 | 
				
			||||||
 | 
					        name = "$name"
 | 
				
			||||||
 | 
					        url = uri("$url")
 | 
				
			||||||
 | 
					${credsType.buildCredsPart()}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}""".replace("\n", "\n$indent")
 | 
					}""".replace("\n", "\n$indent")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.Config
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultContentColumn
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultDivider
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					expect fun TopAppBar(
 | 
				
			||||||
 | 
					    config: Config,
 | 
				
			||||||
 | 
					    saveAvailable: Boolean,
 | 
				
			||||||
 | 
					    onSaveAvailable: (Boolean) -> Unit,
 | 
				
			||||||
 | 
					    onNewConfig: (Config) -> Unit
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BuilderView : View() {
 | 
				
			||||||
 | 
					    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() {
 | 
				
			||||||
 | 
					            return 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() {
 | 
				
			||||||
 | 
					        TopAppBar(
 | 
				
			||||||
 | 
					            config,
 | 
				
			||||||
 | 
					            saveAvailableState,
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                saveAvailableState = it
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            config = it
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DefaultContentColumn {
 | 
				
			||||||
 | 
					            projectTypeView.build()
 | 
				
			||||||
 | 
					            DefaultDivider()
 | 
				
			||||||
 | 
					            licensesView.build()
 | 
				
			||||||
 | 
					            DefaultDivider()
 | 
				
			||||||
 | 
					            mavenInfoView.build()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,8 +1,13 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
 | 
					package dev.inmo.kmppscriptbuilder.core.ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.compose.runtime.*
 | 
					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.Developer
 | 
					import dev.inmo.kmppscriptbuilder.core.models.Developer
 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.*
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DeveloperState(
 | 
					class DeveloperState(
 | 
				
			||||||
    id: String = "",
 | 
					    id: String = "",
 | 
				
			||||||
@@ -22,10 +27,10 @@ class DevelopersView : ListView<DeveloperState>("Developers info") {
 | 
				
			|||||||
    var developers: List<Developer>
 | 
					    var developers: List<Developer>
 | 
				
			||||||
        get() = itemsList.map { it.toDeveloper() }
 | 
					        get() = itemsList.map { it.toDeveloper() }
 | 
				
			||||||
        set(value) {
 | 
					        set(value) {
 | 
				
			||||||
            itemsList.clear()
 | 
					            itemsList.apply {
 | 
				
			||||||
            itemsList.addAll(
 | 
					                clear()
 | 
				
			||||||
                value.map { it.toDeveloperState() }
 | 
					                addAll(value.map { it.toDeveloperState() })
 | 
				
			||||||
            )
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override val addItemText: String = "Add developer"
 | 
					    override val addItemText: String = "Add developer"
 | 
				
			||||||
@@ -34,18 +39,19 @@ class DevelopersView : ListView<DeveloperState>("Developers info") {
 | 
				
			|||||||
    override fun createItem(): DeveloperState = DeveloperState()
 | 
					    override fun createItem(): DeveloperState = DeveloperState()
 | 
				
			||||||
    @Composable
 | 
					    @Composable
 | 
				
			||||||
    override fun buildView(item: DeveloperState) {
 | 
					    override fun buildView(item: DeveloperState) {
 | 
				
			||||||
 | 
					        CommonText("Developer username")
 | 
				
			||||||
        CommonTextField(
 | 
					        CommonTextField(
 | 
				
			||||||
            item.id,
 | 
					            item.id,
 | 
				
			||||||
            "Developer username"
 | 
					 | 
				
			||||||
        ) { item.id = it }
 | 
					        ) { item.id = it }
 | 
				
			||||||
 | 
					        DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					        CommonText("Developer name")
 | 
				
			||||||
        CommonTextField(
 | 
					        CommonTextField(
 | 
				
			||||||
            item.name,
 | 
					            item.name,
 | 
				
			||||||
            "Developer name"
 | 
					 | 
				
			||||||
        ) { item.name = it }
 | 
					        ) { item.name = it }
 | 
				
			||||||
 | 
					        DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					        CommonText("Developer E-Mail")
 | 
				
			||||||
        CommonTextField(
 | 
					        CommonTextField(
 | 
				
			||||||
            item.eMail,
 | 
					            item.eMail,
 | 
				
			||||||
            "Developer E-Mail"
 | 
					 | 
				
			||||||
        ) { item.eMail = it }
 | 
					        ) { item.eMail = it }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					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.setValue
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.models.License
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.models.getLicenses
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					import io.ktor.client.HttpClient
 | 
				
			||||||
 | 
					import kotlinx.coroutines.CoroutineScope
 | 
				
			||||||
 | 
					import kotlinx.coroutines.Dispatchers
 | 
				
			||||||
 | 
					import kotlinx.coroutines.launch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal fun License.toLicenseState() = LicenseState(id, title, url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					expect object LicensesDrawer : Drawer<LicensesView>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LicensesView : ListView<LicenseState>("Licenses") {
 | 
				
			||||||
 | 
					    var licenses: List<License>
 | 
				
			||||||
 | 
					        get() = itemsList.map { it.toLicense() }
 | 
				
			||||||
 | 
					        set(value) {
 | 
				
			||||||
 | 
					            itemsList.clear()
 | 
				
			||||||
 | 
					            itemsList.addAll(value.map { it.toLicenseState() })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    internal val availableLicensesState = 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)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override val addItemText: String
 | 
				
			||||||
 | 
					        get() = "Add empty license"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    init {
 | 
				
			||||||
 | 
					        CoroutineScope(Dispatchers.Default).launch {
 | 
				
			||||||
 | 
					            val client = HttpClient()
 | 
				
			||||||
 | 
					            availableLicensesState.addAll(client.getLicenses().values)
 | 
				
			||||||
 | 
					            client.close()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun createItem(): LicenseState = LicenseState()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun buildView(item: LicenseState) {
 | 
				
			||||||
 | 
					        CommonText("License ID")
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            item.id,
 | 
				
			||||||
 | 
					            "Short name like \"Apache-2.0\"",
 | 
				
			||||||
 | 
					        ) { item.id = it }
 | 
				
			||||||
 | 
					        CommonText("License title")
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            item.title,
 | 
				
			||||||
 | 
					            "Official title of license (like \"Apache Software License 2.0\")",
 | 
				
			||||||
 | 
					        ) { item.title = it }
 | 
				
			||||||
 | 
					        CommonText("License URL")
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            item.url ?: "",
 | 
				
			||||||
 | 
					            "Link to your LICENSE file OR official license file (like \"https://opensource.org/licenses/Apache-2.0\")",
 | 
				
			||||||
 | 
					        ) { item.url = it }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override val content: @Composable () -> Unit = {
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            licenseSearchFilter,
 | 
				
			||||||
 | 
					            "Search filter",
 | 
				
			||||||
 | 
					            onFocusChanged = {
 | 
				
			||||||
 | 
					                searchFieldFocused.value = it
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ) { filterText ->
 | 
				
			||||||
 | 
					            licenseSearchFilter = filterText
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with(LicensesDrawer) { draw() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super.content()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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>(title: String) : VerticalView(title) {
 | 
				
			||||||
 | 
					    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 val content: @Composable () -> Unit = {
 | 
				
			||||||
 | 
					        with(drawer) {
 | 
				
			||||||
 | 
					            draw()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					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.CommonText
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.SwitchWithLabel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					expect class GpgSigningOptionDrawer : Drawer<GpgSigning>
 | 
				
			||||||
 | 
					expect fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MavenInfoView : VerticalView("Project information") {
 | 
				
			||||||
 | 
					    internal var projectNameProperty by mutableStateOf("")
 | 
				
			||||||
 | 
					    internal var projectDescriptionProperty by mutableStateOf("")
 | 
				
			||||||
 | 
					    internal var projectUrlProperty by mutableStateOf("")
 | 
				
			||||||
 | 
					    internal var projectVcsUrlProperty by mutableStateOf("")
 | 
				
			||||||
 | 
					    internal var gpgSignProperty by mutableStateOf<GpgSigning>(GpgSigning.Disabled)
 | 
				
			||||||
 | 
					    internal var publishToMavenCentralProperty by mutableStateOf(false)
 | 
				
			||||||
 | 
					    internal val developersView = DevelopersView()
 | 
				
			||||||
 | 
					    internal 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 }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val gpgSigningDrawer = GpgSigningOptionDrawerWithView(this)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override val content: @Composable () -> Unit = {
 | 
				
			||||||
 | 
					        CommonText("Public project name")
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            projectNameProperty,
 | 
				
			||||||
 | 
					            "\${project.name}",
 | 
				
			||||||
 | 
					        ) { projectNameProperty = it }
 | 
				
			||||||
 | 
					        DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					        CommonText("Public project description")
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            projectDescriptionProperty,
 | 
				
			||||||
 | 
					            "\${project.name}",
 | 
				
			||||||
 | 
					        ) { projectDescriptionProperty = it }
 | 
				
			||||||
 | 
					        DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					        CommonText("Public project URL")
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            projectUrlProperty,
 | 
				
			||||||
 | 
					            "Type url to github or other source with readme",
 | 
				
			||||||
 | 
					        ) { projectUrlProperty = it }
 | 
				
			||||||
 | 
					        DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					        CommonText("Public project VCS URL (with .git)")
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            projectVcsUrlProperty,
 | 
				
			||||||
 | 
					            "Type url to github .git file"
 | 
				
			||||||
 | 
					        ) { projectVcsUrlProperty = it }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ButtonsPanel(
 | 
				
			||||||
 | 
					            "Gpg signing",
 | 
				
			||||||
 | 
					            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()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.DefaultSmallVerticalMargin
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 = {
 | 
				
			||||||
 | 
					        ButtonsPanel(
 | 
				
			||||||
 | 
					            "Project type",
 | 
				
			||||||
 | 
					            MultiplatformProjectType,
 | 
				
			||||||
 | 
					            JVMProjectType,
 | 
				
			||||||
 | 
					            JSProjectType
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            with(typeDrawer) {
 | 
				
			||||||
 | 
					                with (it) {
 | 
				
			||||||
 | 
					                    draw()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,142 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
 | 
					import androidx.compose.runtime.getValue
 | 
				
			||||||
 | 
					import androidx.compose.runtime.mutableStateOf
 | 
				
			||||||
 | 
					import androidx.compose.runtime.remember
 | 
				
			||||||
 | 
					import androidx.compose.runtime.setValue
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.ButtonsPanel
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultContentColumn
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RepositoryState(
 | 
				
			||||||
 | 
					    name: String = "",
 | 
				
			||||||
 | 
					    url: String = "",
 | 
				
			||||||
 | 
					    credsType: MavenPublishingRepository.CredentialsType = MavenPublishingRepository.CredentialsType.UsernameAndPassword(name)
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    var name: String by mutableStateOf(name)
 | 
				
			||||||
 | 
					    var url: String by mutableStateOf(url)
 | 
				
			||||||
 | 
					    var credsType by mutableStateOf(credsType)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun toRepository() = MavenPublishingRepository(name, url, credsType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private fun MavenPublishingRepository.toRepositoryState() = RepositoryState(name, url, credsType)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					expect class RepositoryCredentialTypeDrawer : Drawer<MavenPublishingRepository.CredentialsType>
 | 
				
			||||||
 | 
					expect fun RepositoryCredentialTypeDrawerWithState(repositoryState: RepositoryState): RepositoryCredentialTypeDrawer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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) {
 | 
				
			||||||
 | 
					        val credsTypesDrawer = remember {
 | 
				
			||||||
 | 
					            RepositoryCredentialTypeDrawerWithState(item)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CommonText("Repository name")
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            item.name,
 | 
				
			||||||
 | 
					            "This name will be used to identify repository in gradle"
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            val previous = item.name
 | 
				
			||||||
 | 
					            item.name = it
 | 
				
			||||||
 | 
					            when (val currentCredsType = item.credsType) {
 | 
				
			||||||
 | 
					                is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials -> {
 | 
				
			||||||
 | 
					                    if (MavenPublishingRepository.CredentialsType.HttpHeaderCredentials.defaultValueProperty(previous) == currentCredsType.headerValueProperty) {
 | 
				
			||||||
 | 
					                        item.credsType = currentCredsType.copy(
 | 
				
			||||||
 | 
					                            headerValueProperty = MavenPublishingRepository.CredentialsType.HttpHeaderCredentials.defaultValueProperty(it)
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                MavenPublishingRepository.CredentialsType.Nothing -> {}
 | 
				
			||||||
 | 
					                is MavenPublishingRepository.CredentialsType.UsernameAndPassword -> {
 | 
				
			||||||
 | 
					                    var current: MavenPublishingRepository.CredentialsType.UsernameAndPassword = currentCredsType
 | 
				
			||||||
 | 
					                    if (MavenPublishingRepository.CredentialsType.UsernameAndPassword.defaultUsernameProperty(previous) == currentCredsType.usernameProperty) {
 | 
				
			||||||
 | 
					                        current = current.copy(
 | 
				
			||||||
 | 
					                            usernameProperty = MavenPublishingRepository.CredentialsType.UsernameAndPassword.defaultUsernameProperty(it)
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (MavenPublishingRepository.CredentialsType.UsernameAndPassword.defaultPasswordProperty(previous) == currentCredsType.passwordProperty) {
 | 
				
			||||||
 | 
					                        current = current.copy(
 | 
				
			||||||
 | 
					                            passwordProperty = MavenPublishingRepository.CredentialsType.UsernameAndPassword.defaultPasswordProperty(it)
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    item.credsType = current
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					        CommonText("Repository url")
 | 
				
			||||||
 | 
					        CommonTextField(
 | 
				
			||||||
 | 
					            item.url,
 | 
				
			||||||
 | 
					            "For example: https://repo.maven.apache.org/maven2/"
 | 
				
			||||||
 | 
					        ) { item.url = it }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ButtonsPanel(
 | 
				
			||||||
 | 
					            "Credentials type",
 | 
				
			||||||
 | 
					            MavenPublishingRepository.CredentialsType.Nothing.takeIf { item.credsType != it } ?: item.credsType,
 | 
				
			||||||
 | 
					            MavenPublishingRepository.CredentialsType.UsernameAndPassword(item.name).takeIf { item.credsType !is MavenPublishingRepository.CredentialsType.UsernameAndPassword } ?: item.credsType,
 | 
				
			||||||
 | 
					            MavenPublishingRepository.CredentialsType.HttpHeaderCredentials(
 | 
				
			||||||
 | 
					                "Authorization",
 | 
				
			||||||
 | 
					                MavenPublishingRepository.CredentialsType.HttpHeaderCredentials.defaultValueProperty(item.name)
 | 
				
			||||||
 | 
					            ).takeIf { item.credsType !is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials } ?: item.credsType,
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            with(credsTypesDrawer) {
 | 
				
			||||||
 | 
					                with(it) {
 | 
				
			||||||
 | 
					                    draw()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DefaultContentColumn {
 | 
				
			||||||
 | 
					            when (val credsType = item.credsType) {
 | 
				
			||||||
 | 
					                is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials -> {
 | 
				
			||||||
 | 
					                    CommonText("Header name")
 | 
				
			||||||
 | 
					                    CommonTextField(credsType.headerName) {
 | 
				
			||||||
 | 
					                        item.credsType = credsType.copy(headerName = it)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    CommonText("Property name")
 | 
				
			||||||
 | 
					                    CommonTextField(credsType.headerValueProperty) {
 | 
				
			||||||
 | 
					                        item.credsType = credsType.copy(headerValueProperty = it)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                MavenPublishingRepository.CredentialsType.Nothing -> {
 | 
				
			||||||
 | 
					                    CommonText("No parameters for absence of credentials")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                is MavenPublishingRepository.CredentialsType.UsernameAndPassword -> {
 | 
				
			||||||
 | 
					                    CommonText("Username property name")
 | 
				
			||||||
 | 
					                    CommonTextField(credsType.usernameProperty) {
 | 
				
			||||||
 | 
					                        item.credsType = credsType.copy(usernameProperty = it)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    CommonText("Password property name")
 | 
				
			||||||
 | 
					                    CommonTextField(credsType.passwordProperty) {
 | 
				
			||||||
 | 
					                        item.credsType = credsType.copy(passwordProperty = it)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultContentColumn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class VerticalView(protected val title: String) : View() {
 | 
				
			||||||
 | 
					    abstract val content: @Composable () -> Unit
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun build() {
 | 
				
			||||||
 | 
					        DefaultContentColumn {
 | 
				
			||||||
 | 
					            DrawVertically(title, content)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun interface Drawer<T> {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    fun T.draw()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.ui.utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					expect fun TitleText(text: String)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					expect fun CommonText(text: String, onClick: (() -> Unit)? = null)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					expect fun CommonTextField(
 | 
				
			||||||
 | 
					    presetText: String,
 | 
				
			||||||
 | 
					    hint: String? = null,
 | 
				
			||||||
 | 
					    onFocusChanged: (Boolean) -> Unit = {},
 | 
				
			||||||
 | 
					    onChange: (String) -> Unit
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					expect fun SwitchWithLabel(
 | 
				
			||||||
 | 
					    label: String,
 | 
				
			||||||
 | 
					    checked: Boolean,
 | 
				
			||||||
 | 
					    placeSwitchAtTheStart: Boolean = false,
 | 
				
			||||||
 | 
					    switchEnabled: Boolean = true,
 | 
				
			||||||
 | 
					    onCheckedChange: (Boolean) -> Unit
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					expect fun <T> ButtonsPanel(
 | 
				
			||||||
 | 
					    title: String,
 | 
				
			||||||
 | 
					    data: Iterable<T>,
 | 
				
			||||||
 | 
					    itemDrawer: @Composable (T) -> Unit
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					fun <T> ButtonsPanel(
 | 
				
			||||||
 | 
					    title: String,
 | 
				
			||||||
 | 
					    vararg data: T,
 | 
				
			||||||
 | 
					    itemDrawer: @Composable (T) -> Unit
 | 
				
			||||||
 | 
					) = ButtonsPanel(title, data.toList(), itemDrawer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					expect fun DefaultDivider()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					expect fun DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					expect fun DefaultContentColumn(block: @Composable () -> Unit)
 | 
				
			||||||
@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					expect fun openNewConfig(onParsed: (Config) -> Unit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 463 B After Width: | Height: | Size: 463 B  | 
| 
		 Before Width: | Height: | Size: 452 B After Width: | Height: | Size: 452 B  | 
| 
		 Before Width: | Height: | Size: 744 B After Width: | Height: | Size: 744 B  | 
| 
		 Before Width: | Height: | Size: 502 B 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,35 @@
 | 
				
			|||||||
 | 
					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.UIKitTooltipModifier
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitUtility
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual class GpgSigningOptionDrawer(
 | 
				
			||||||
 | 
					    private val mavenInfoView: MavenInfoView
 | 
				
			||||||
 | 
					) : Drawer<GpgSigning> {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun GpgSigning.draw() {
 | 
				
			||||||
 | 
					        val tooltipModifier = UIKitTooltipModifier(
 | 
				
			||||||
 | 
					            when (this) {
 | 
				
			||||||
 | 
					                GpgSigning.Disabled -> "Signing will not be added"
 | 
				
			||||||
 | 
					                GpgSigning.Enabled -> "Signing will be always enabled"
 | 
				
			||||||
 | 
					                GpgSigning.Optional -> "Signing will be added, but disabled in case of absence 'signatory.keyId'"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        if (mavenInfoView.gpgSignProperty == this) {
 | 
				
			||||||
 | 
					            DefaultButton(name, UIKitButton.Type.Primary, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded, tooltipModifier)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            DefaultButton(name, UIKitButton.Type.Default, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded, tooltipModifier) {
 | 
				
			||||||
 | 
					                mavenInfoView.gpgSignProperty = this
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer = GpgSigningOptionDrawer(mavenInfoView = view)
 | 
				
			||||||
@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					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.UIKitUtility
 | 
				
			||||||
 | 
					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 dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					            ) { _ ->
 | 
				
			||||||
 | 
					                itemsList.add(it.toLicenseState())
 | 
				
			||||||
 | 
					                licenseSearchFilter = ""
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Divider.Common()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					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.UIKitUtility
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultContentColumn
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual class ListViewDrawer<T> : Drawer<ListView<T>> {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun ListView<T>.draw() {
 | 
				
			||||||
 | 
					        itemsList.forEach { item ->
 | 
				
			||||||
 | 
					            DefaultContentColumn {
 | 
				
			||||||
 | 
					                buildView(item)
 | 
				
			||||||
 | 
					                DefaultButton(removeItemText, UIKitButton.Type.Default, UIKitMargin.Small, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded) {
 | 
				
			||||||
 | 
					                    itemsList.remove(item)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            DefaultButton(addItemText, UIKitButton.Type.Primary, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded ) { itemsList.add(createItem()) }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (itemsList.isEmpty()) {
 | 
				
			||||||
 | 
					            DefaultButton(addItemText, UIKitButton.Type.Primary, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded ) { itemsList.add(createItem()) }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					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.UIKitText
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitUtility
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.models.ProjectType
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual class ProjectTypeDrawer(
 | 
				
			||||||
 | 
					    private val projectTypeView: ProjectTypeView
 | 
				
			||||||
 | 
					) : Drawer<ProjectType> {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun ProjectType.draw() {
 | 
				
			||||||
 | 
					        if (projectTypeView.projectType == this) {
 | 
				
			||||||
 | 
					            DefaultButton(name, UIKitButton.Type.Primary, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            DefaultButton(name, UIKitButton.Type.Default, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded) {
 | 
				
			||||||
 | 
					                projectTypeView.projectType = this
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer = ProjectTypeDrawer(projectTypeView = view)
 | 
				
			||||||
@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					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.UIKitUtility
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.NoTransform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual class RepositoryCredentialTypeDrawer(
 | 
				
			||||||
 | 
					    private val state: RepositoryState
 | 
				
			||||||
 | 
					) : Drawer<MavenPublishingRepository.CredentialsType> {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun MavenPublishingRepository.CredentialsType.draw() {
 | 
				
			||||||
 | 
					        val name = when (this@draw) {
 | 
				
			||||||
 | 
					            is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials -> "Headers"
 | 
				
			||||||
 | 
					            MavenPublishingRepository.CredentialsType.Nothing -> "No"
 | 
				
			||||||
 | 
					            is MavenPublishingRepository.CredentialsType.UsernameAndPassword -> "Username and password"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (state.credsType == this) {
 | 
				
			||||||
 | 
					            DefaultButton(name, UIKitButton.Type.Primary, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            DefaultButton(name, UIKitButton.Type.Default, UIKitButton.Size.Small, UIKitMargin.Small.Horizontal, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded) {
 | 
				
			||||||
 | 
					                state.credsType = this
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual fun RepositoryCredentialTypeDrawerWithState(repositoryState: RepositoryState): RepositoryCredentialTypeDrawer = RepositoryCredentialTypeDrawer(repositoryState)
 | 
				
			||||||
@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					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.UIKitBackground
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitInverse
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitMargin
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitModifier
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitNavbar
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitPadding
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitSection
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitText
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitTooltipModifier
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.attrsBuilder
 | 
				
			||||||
 | 
					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.Section
 | 
				
			||||||
 | 
					import org.jetbrains.compose.web.dom.Text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun TopAppBar(
 | 
				
			||||||
 | 
					    config: Config,
 | 
				
			||||||
 | 
					    saveAvailable: Boolean,
 | 
				
			||||||
 | 
					    onSaveAvailable: (Boolean) -> Unit,
 | 
				
			||||||
 | 
					    onNewConfig: (Config) -> Unit
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    Section(attrsBuilder(UIKitSection.Style.Primary, UIKitInverse.Light)) {
 | 
				
			||||||
 | 
					        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)
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            navModifiers = arrayOf(UIKitNavbar.Transparent)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitForm
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.builder
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.DefaultSmallVerticalMargin
 | 
				
			||||||
 | 
					import org.jetbrains.compose.web.dom.Legend
 | 
				
			||||||
 | 
					import org.jetbrains.compose.web.dom.Text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual abstract class View {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    actual abstract fun build()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun View.DrawVertically(title: String, block: @Composable () -> Unit) {
 | 
				
			||||||
 | 
					    Legend(UIKitForm.Legend.builder()) {
 | 
				
			||||||
 | 
					        Text(title)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					    block()
 | 
				
			||||||
 | 
					    DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					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.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.UIKitUtility
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.attrsBuilder
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.builder
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.include
 | 
				
			||||||
 | 
					import kotlinx.browser.window
 | 
				
			||||||
 | 
					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 {
 | 
				
			||||||
 | 
					                window.setTimeout( // avoid immediate hiding of potential interface data with additional delay
 | 
				
			||||||
 | 
					                    { onFocusChanged(false) },
 | 
				
			||||||
 | 
					                    100
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        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, UIKitUtility.NoTransform, UIKitUtility.Border.Rounded)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        if (checked) {
 | 
				
			||||||
 | 
					            Icon.App.Check.drawAsFormInputPart(UIKitInverse.Light)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Text(label)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun <T> ButtonsPanel(
 | 
				
			||||||
 | 
					    title: String,
 | 
				
			||||||
 | 
					    data: Iterable<T>,
 | 
				
			||||||
 | 
					    itemDrawer: @Composable (T) -> Unit
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    Flex(UIKitFlex.Alignment.Vertical.Middle, UIKitMargin.Small) {
 | 
				
			||||||
 | 
					        Div(UIKitMargin.Small.Horizontal.builder()) { Text(title) }
 | 
				
			||||||
 | 
					        data.forEach { itemDrawer(it) }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun DefaultDivider() {
 | 
				
			||||||
 | 
					    Divider.Common()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun DefaultSmallVerticalMargin() {
 | 
				
			||||||
 | 
					    Div(UIKitMargin.Small.Top.builder())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun DefaultContentColumn(block: @Composable () -> Unit) {
 | 
				
			||||||
 | 
					    Div(attrsBuilder(UIKitMargin.Small.Horizontal, UIKitMargin.Small.Vertical)) {
 | 
				
			||||||
 | 
					        block()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.ui.utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitCustom
 | 
				
			||||||
 | 
					import dev.inmo.jsuikit.modifiers.UIKitUtility
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					val ClassNoTransform = UIKitCustom(arrayOf("no-transform"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					val UIKitUtility.Companion.NoTransform
 | 
				
			||||||
 | 
					    get() = ClassNoTransform
 | 
				
			||||||
@@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								core/src/jsMain/resources/css/internal.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					.no-transform {
 | 
				
			||||||
 | 
					    text-transform: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								core/src/jsMain/resources/css/uikit.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										73
									
								
								core/src/jsMain/resources/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					<!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" />
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="./css/internal.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.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@@ -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
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					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.DefaultSmallVerticalMargin
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.TitleText
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual abstract class View {
 | 
				
			||||||
 | 
					    internal open val defaultModifier = Modifier.fillMaxWidth()
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    actual abstract fun build()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun View.DrawVertically(
 | 
				
			||||||
 | 
					    title: String,
 | 
				
			||||||
 | 
					    block: @Composable () -> Unit
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    TitleText(title)
 | 
				
			||||||
 | 
					    DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Column(defaultModifier) {
 | 
				
			||||||
 | 
					        block()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DefaultSmallVerticalMargin()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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, 0.dp)) {
 | 
				
			||||||
 | 
					                Text(name)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            OutlinedButton(
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    mavenInfoView.gpgSignProperty = this
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                Modifier.padding(8.dp, 0.dp)
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                Text(name)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer = GpgSigningOptionDrawer(mavenInfoView = view)
 | 
				
			||||||
@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					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.material.Divider
 | 
				
			||||||
 | 
					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.CommonTextField
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual object LicensesDrawer : Drawer<LicensesView> {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun LicensesView.draw() {
 | 
				
			||||||
 | 
					        if (searchFieldFocused.value) {
 | 
				
			||||||
 | 
					            Column {
 | 
				
			||||||
 | 
					                licensesOffersToShow.value.forEach {
 | 
				
			||||||
 | 
					                    Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
 | 
				
			||||||
 | 
					                        CommonText(it.title) {
 | 
				
			||||||
 | 
					                            itemsList.add(it.toLicenseState())
 | 
				
			||||||
 | 
					                            licenseSearchFilter = ""
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        Divider()
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.padding
 | 
				
			||||||
 | 
					import androidx.compose.material.Button
 | 
				
			||||||
 | 
					import androidx.compose.material.OutlinedButton
 | 
				
			||||||
 | 
					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.DefaultContentColumn
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual class ListViewDrawer<T> : Drawer<ListView<T>> {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun ListView<T>.draw() {
 | 
				
			||||||
 | 
					        itemsList.forEach { item ->
 | 
				
			||||||
 | 
					            DefaultContentColumn {
 | 
				
			||||||
 | 
					                buildView(item)
 | 
				
			||||||
 | 
					                OutlinedButton({ itemsList.remove(item) }, Modifier.padding(8.dp)) {
 | 
				
			||||||
 | 
					                    CommonText(removeItemText,)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Button({ itemsList.add(createItem()) }) {
 | 
				
			||||||
 | 
					                CommonText(addItemText,)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (itemsList.isEmpty()) {
 | 
				
			||||||
 | 
					            Button({ itemsList.add(createItem()) }) {
 | 
				
			||||||
 | 
					                CommonText(addItemText,)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					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.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.Drawer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual class ProjectTypeDrawer(
 | 
				
			||||||
 | 
					    private val projectTypeView: ProjectTypeView
 | 
				
			||||||
 | 
					) : Drawer<ProjectType> {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun ProjectType.draw() {
 | 
				
			||||||
 | 
					        if (projectTypeView.projectType == this) {
 | 
				
			||||||
 | 
					            Button({}, Modifier.padding(8.dp, 0.dp)) {
 | 
				
			||||||
 | 
					                Text(name)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            OutlinedButton(
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    projectTypeView.projectType = this
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                Modifier.padding(8.dp, 0.dp)
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                Text(name)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer = ProjectTypeDrawer(projectTypeView = view)
 | 
				
			||||||
@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.Modifier
 | 
				
			||||||
 | 
					import androidx.compose.ui.unit.dp
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
 | 
				
			||||||
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual class RepositoryCredentialTypeDrawer(
 | 
				
			||||||
 | 
					    private val state: RepositoryState
 | 
				
			||||||
 | 
					) : Drawer<MavenPublishingRepository.CredentialsType> {
 | 
				
			||||||
 | 
					    @Composable
 | 
				
			||||||
 | 
					    override fun MavenPublishingRepository.CredentialsType.draw() {
 | 
				
			||||||
 | 
					        val name = when (this@draw) {
 | 
				
			||||||
 | 
					            is MavenPublishingRepository.CredentialsType.HttpHeaderCredentials -> "Headers"
 | 
				
			||||||
 | 
					            MavenPublishingRepository.CredentialsType.Nothing -> "No"
 | 
				
			||||||
 | 
					            is MavenPublishingRepository.CredentialsType.UsernameAndPassword -> "Username and password"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (state.credsType == this) {
 | 
				
			||||||
 | 
					            Button({}, Modifier.padding(8.dp, 0.dp)) {
 | 
				
			||||||
 | 
					                Text(name)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            OutlinedButton(
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    state.credsType = this
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                Modifier.padding(8.dp, 0.dp)
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                Text(name)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					actual fun RepositoryCredentialTypeDrawerWithState(repositoryState: RepositoryState): RepositoryCredentialTypeDrawer = RepositoryCredentialTypeDrawer(repositoryState)
 | 
				
			||||||
@@ -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)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					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.Column
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.Row
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.Spacer
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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).clickable { onCheckedChange(!checked) }, Arrangement.Start, Alignment.Top) {
 | 
				
			||||||
 | 
					        val switchCreator = @Composable {
 | 
				
			||||||
 | 
					            Switch(checked, null, Modifier.padding(8.dp, 0.dp), enabled = switchEnabled)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (placeSwitchAtTheStart) {
 | 
				
			||||||
 | 
					            switchCreator()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Box(Modifier.fillMaxWidth().align(Alignment.CenterVertically)) {
 | 
				
			||||||
 | 
					            CommonText(label)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!placeSwitchAtTheStart) {
 | 
				
			||||||
 | 
					            switchCreator()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun CommonTextField(
 | 
				
			||||||
 | 
					    presetText: String,
 | 
				
			||||||
 | 
					    hint: String?,
 | 
				
			||||||
 | 
					    onFocusChanged: (Boolean) -> Unit,
 | 
				
			||||||
 | 
					    onChange: (String) -> Unit
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    OutlinedTextField(
 | 
				
			||||||
 | 
					        presetText,
 | 
				
			||||||
 | 
					        onChange,
 | 
				
			||||||
 | 
					        Modifier.fillMaxWidth().onFocusChanged {
 | 
				
			||||||
 | 
					            onFocusChanged(it.isFocused)
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        singleLine = true,
 | 
				
			||||||
 | 
					        label = hint ?.let {
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                CommonText(hint)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun CommonText(text: String, onClick: (() -> Unit)?) {
 | 
				
			||||||
 | 
					    Text(text, modifier = Modifier.run { onClick ?.let { clickable(onClick = it) } ?: this })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun TitleText(text: String) {
 | 
				
			||||||
 | 
					    Text(
 | 
				
			||||||
 | 
					        text, Modifier.padding(0.dp, 8.dp), fontSize = 18.sp
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun <T> ButtonsPanel(
 | 
				
			||||||
 | 
					    title: String,
 | 
				
			||||||
 | 
					    data: Iterable<T>,
 | 
				
			||||||
 | 
					    itemDrawer: @Composable (T) -> Unit
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    Row {
 | 
				
			||||||
 | 
					        Text(title, Modifier.padding(8.dp))
 | 
				
			||||||
 | 
					        data.forEach { itemDrawer(it) }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun DefaultDivider() {
 | 
				
			||||||
 | 
					    Divider()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun DefaultSmallVerticalMargin() {
 | 
				
			||||||
 | 
					    Spacer(Modifier.padding(0.dp, 4.dp))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					actual fun DefaultContentColumn(block: @Composable () -> Unit) {
 | 
				
			||||||
 | 
					    Column(Modifier.padding(8.dp)) {
 | 
				
			||||||
 | 
					        block()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
 | 
					package dev.inmo.kmppscriptbuilder.core.ui.utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.File
 | 
					import java.io.File
 | 
				
			||||||
import javax.swing.filechooser.FileFilter
 | 
					import javax.swing.filechooser.FileFilter
 | 
				
			||||||
@@ -1,40 +1,40 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
 | 
					package dev.inmo.kmppscriptbuilder.core.utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
 | 
					import dev.inmo.kmppscriptbuilder.core.models.Config
 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
 | 
					import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
 | 
				
			||||||
 | 
					import dev.inmo.micro_utils.common.MPPFile
 | 
				
			||||||
import java.io.File
 | 
					import java.io.File
 | 
				
			||||||
import javax.swing.JFileChooser
 | 
					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
 | 
					    lastFile = file
 | 
				
			||||||
    return serialFormat.decodeFromString(Config.serializer(), file.readText())
 | 
					    return serialFormat.decodeFromString(Config.serializer(), file.text())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun loadConfig(): Config? {
 | 
					actual fun openNewConfig(onParsed: (Config) -> Unit) {
 | 
				
			||||||
    val fc = JFileChooser(lastFile ?.parent)
 | 
					    val fc = JFileChooser(lastFile ?.parent)
 | 
				
			||||||
    fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
 | 
					    fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
 | 
				
			||||||
    fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
 | 
					    fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
 | 
				
			||||||
    return when (fc.showOpenDialog(null)) {
 | 
					    when (fc.showOpenDialog(null)) {
 | 
				
			||||||
        JFileChooser.APPROVE_OPTION -> {
 | 
					        JFileChooser.APPROVE_OPTION -> {
 | 
				
			||||||
            val file = fc.selectedFile
 | 
					            val file = fc.selectedFile
 | 
				
			||||||
            lastFile = file
 | 
					            lastFile = file
 | 
				
			||||||
            return serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText())
 | 
					            onParsed(serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText()))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else -> null
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun saveConfig(config: Config): Boolean {
 | 
					actual fun saveConfig(config: Config): Boolean {
 | 
				
			||||||
    return lastFile ?.also {
 | 
					    return lastFile ?.also {
 | 
				
			||||||
        it.writeText(serialFormat.encodeToString(Config.serializer(), config))
 | 
					        it.writeText(serialFormat.encodeToString(Config.serializer(), config))
 | 
				
			||||||
    } != null
 | 
					    } != null
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun exportGradle(config: Config): Boolean {
 | 
					actual fun exportGradle(config: Config): Boolean {
 | 
				
			||||||
    val fc = JFileChooser(lastFile ?.parent)
 | 
					    val fc = JFileChooser(lastFile ?.parent)
 | 
				
			||||||
    fc.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
 | 
					    fc.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
 | 
				
			||||||
    return when (fc.showSaveDialog(null)) {
 | 
					    return when (fc.showSaveDialog(null)) {
 | 
				
			||||||
@@ -55,7 +55,7 @@ fun exportGradle(config: Config): Boolean {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun saveAs(config: Config): Boolean {
 | 
					actual fun saveAs(config: Config): Boolean {
 | 
				
			||||||
    val fc = JFileChooser(lastFile ?.parent)
 | 
					    val fc = JFileChooser(lastFile ?.parent)
 | 
				
			||||||
    fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
 | 
					    fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
 | 
				
			||||||
    fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
 | 
					    fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
 | 
				
			||||||
@@ -1,10 +1,9 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
 | 
					package dev.inmo.kmppscriptbuilder.core.utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.awt.Desktop
 | 
					import java.awt.Desktop
 | 
				
			||||||
import java.lang.Exception
 | 
					 | 
				
			||||||
import java.net.URI
 | 
					import java.net.URI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun openLink(link: String): Boolean {
 | 
					actual fun openLink(link: String): Boolean {
 | 
				
			||||||
    val desktop = if (Desktop.isDesktopSupported()) Desktop.getDesktop() else null
 | 
					    val desktop = if (Desktop.isDesktopSupported()) Desktop.getDesktop() else null
 | 
				
			||||||
    if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
 | 
					    if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					package dev.inmo.kmppscriptbuilder.core.utils 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
<manifest package="dev.inmo.KotlinPublicationScriptsBuilder.core"/>
 | 
					 | 
				
			||||||
@@ -1,40 +0,0 @@
 | 
				
			|||||||
apply plugin: 'com.getkeepsafe.dexcount'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
android {
 | 
					 | 
				
			||||||
    compileSdkVersion "$android_compileSdkVersion".toInteger()
 | 
					 | 
				
			||||||
    buildToolsVersion "$android_buildToolsVersion"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    defaultConfig {
 | 
					 | 
				
			||||||
        minSdkVersion "$android_minSdkVersion".toInteger()
 | 
					 | 
				
			||||||
        targetSdkVersion "$android_compileSdkVersion".toInteger()
 | 
					 | 
				
			||||||
        versionCode "${android_code_version}".toInteger()
 | 
					 | 
				
			||||||
        versionName "$version"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    buildTypes {
 | 
					 | 
				
			||||||
        release {
 | 
					 | 
				
			||||||
            minifyEnabled false
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        debug {
 | 
					 | 
				
			||||||
            debuggable true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    packagingOptions {
 | 
					 | 
				
			||||||
        exclude 'META-INF/kotlinx-serialization-runtime.kotlin_module'
 | 
					 | 
				
			||||||
        exclude 'META-INF/kotlinx-serialization-cbor.kotlin_module'
 | 
					 | 
				
			||||||
        exclude 'META-INF/kotlinx-serialization-properties.kotlin_module'
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    compileOptions {
 | 
					 | 
				
			||||||
        sourceCompatibility JavaVersion.VERSION_1_8
 | 
					 | 
				
			||||||
        targetCompatibility JavaVersion.VERSION_1_8
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    kotlinOptions {
 | 
					 | 
				
			||||||
        jvmTarget = JavaVersion.VERSION_1_8.toString()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sourceSets {
 | 
					 | 
				
			||||||
        main.java.srcDirs += 'src/main/kotlin'
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,37 +0,0 @@
 | 
				
			|||||||
plugins {
 | 
					 | 
				
			||||||
    id "org.jetbrains.kotlin.multiplatform"
 | 
					 | 
				
			||||||
    id "org.jetbrains.kotlin.plugin.serialization"
 | 
					 | 
				
			||||||
    id("org.jetbrains.compose") version "$compose_version"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
apply from: "$mppJavaProjectPresetPath"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
kotlin {
 | 
					 | 
				
			||||||
    jvm {
 | 
					 | 
				
			||||||
        compilations.main.kotlinOptions {
 | 
					 | 
				
			||||||
            jvmTarget = "11"
 | 
					 | 
				
			||||||
            useIR = true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    sourceSets {
 | 
					 | 
				
			||||||
        commonMain {
 | 
					 | 
				
			||||||
            dependencies {
 | 
					 | 
				
			||||||
                implementation project(":kmppscriptbuilder.core")
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        jvmMain {
 | 
					 | 
				
			||||||
            dependencies {
 | 
					 | 
				
			||||||
                implementation(compose.desktop.currentOs)
 | 
					 | 
				
			||||||
                api "io.ktor:ktor-client-cio:$ktor_version"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
compose.desktop {
 | 
					 | 
				
			||||||
    application {
 | 
					 | 
				
			||||||
        mainClass = "dev.inmo.kmppscriptbuilder.desktop.BuilderKt"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,62 +0,0 @@
 | 
				
			|||||||
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.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 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)
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (args.isNotEmpty()) {
 | 
					 | 
				
			||||||
        val config = loadConfigFile(File(args.first()))
 | 
					 | 
				
			||||||
        builder.config = config
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,60 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import androidx.compose.foundation.clickable
 | 
					 | 
				
			||||||
import androidx.compose.foundation.layout.*
 | 
					 | 
				
			||||||
import androidx.compose.material.*
 | 
					 | 
				
			||||||
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
 | 
					 | 
				
			||||||
inline fun TitleText(text: String) = Text(
 | 
					 | 
				
			||||||
    text, Modifier.padding(0.dp, 8.dp), fontSize = 18.sp
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Composable
 | 
					 | 
				
			||||||
inline fun CommonText(text: String, modifier: Modifier = Modifier) = Text(
 | 
					 | 
				
			||||||
    text, modifier = modifier
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Composable
 | 
					 | 
				
			||||||
inline fun CommonTextField(presetText: String, hint: String, noinline onChange: (String) -> Unit) = OutlinedTextField(
 | 
					 | 
				
			||||||
    presetText,
 | 
					 | 
				
			||||||
    onChange,
 | 
					 | 
				
			||||||
    Modifier.fillMaxWidth(),
 | 
					 | 
				
			||||||
    singleLine = true,
 | 
					 | 
				
			||||||
    label = {
 | 
					 | 
				
			||||||
        CommonText(hint)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Composable
 | 
					 | 
				
			||||||
inline fun SwitchWithLabel(
 | 
					 | 
				
			||||||
    label: String,
 | 
					 | 
				
			||||||
    checked: Boolean,
 | 
					 | 
				
			||||||
    placeSwitchAtTheStart: Boolean = false,
 | 
					 | 
				
			||||||
    switchEnabled: Boolean = true,
 | 
					 | 
				
			||||||
    modifier: Modifier = Modifier.padding(0.dp, 8.dp),
 | 
					 | 
				
			||||||
    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
 | 
					 | 
				
			||||||
    verticalAlignment: Alignment.Vertical = Alignment.Top,
 | 
					 | 
				
			||||||
    switchModifier: Modifier = Modifier.padding(8.dp, 0.dp),
 | 
					 | 
				
			||||||
    noinline onCheckedChange: (Boolean) -> Unit
 | 
					 | 
				
			||||||
) = Row(modifier, horizontalArrangement, verticalAlignment) {
 | 
					 | 
				
			||||||
    val switchCreator = @Composable {
 | 
					 | 
				
			||||||
        Switch(checked, onCheckedChange, switchModifier, enabled = switchEnabled)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (placeSwitchAtTheStart) {
 | 
					 | 
				
			||||||
        switchCreator()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    CommonText(label, Modifier.align(Alignment.CenterVertically).clickable {  })
 | 
					 | 
				
			||||||
    if (!placeSwitchAtTheStart) {
 | 
					 | 
				
			||||||
        switchCreator()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,34 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.utils
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import androidx.compose.foundation.layout.*
 | 
					 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					 | 
				
			||||||
import androidx.compose.ui.Modifier
 | 
					 | 
				
			||||||
import androidx.compose.ui.unit.dp
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
abstract class View {
 | 
					 | 
				
			||||||
    protected open val defaultModifier = Modifier.fillMaxWidth().padding(8.dp)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Composable
 | 
					 | 
				
			||||||
    abstract fun build()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
abstract class VerticalView(val title: String) : View() {
 | 
					 | 
				
			||||||
    abstract val content: @Composable ColumnScope.() -> Unit
 | 
					 | 
				
			||||||
    @Composable
 | 
					 | 
				
			||||||
    override fun build() {
 | 
					 | 
				
			||||||
        TitleText(title)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Column(
 | 
					 | 
				
			||||||
            defaultModifier
 | 
					 | 
				
			||||||
        ) {
 | 
					 | 
				
			||||||
            content()
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Spacer(Modifier.fillMaxWidth().height(8.dp))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Composable
 | 
					 | 
				
			||||||
fun <T : View> T.init(): T = apply {
 | 
					 | 
				
			||||||
    build()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,111 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import androidx.compose.foundation.Image
 | 
					 | 
				
			||||||
import androidx.compose.foundation.clickable
 | 
					 | 
				
			||||||
import androidx.compose.foundation.layout.*
 | 
					 | 
				
			||||||
import androidx.compose.material.*
 | 
					 | 
				
			||||||
import androidx.compose.runtime.*
 | 
					 | 
				
			||||||
import androidx.compose.ui.Modifier
 | 
					 | 
				
			||||||
import androidx.compose.ui.graphics.asImageBitmap
 | 
					 | 
				
			||||||
import androidx.compose.ui.platform.DesktopPlatform
 | 
					 | 
				
			||||||
import androidx.compose.ui.res.loadSvgResource
 | 
					 | 
				
			||||||
import androidx.compose.ui.res.svgResource
 | 
					 | 
				
			||||||
import androidx.compose.ui.unit.Density
 | 
					 | 
				
			||||||
import androidx.compose.ui.unit.dp
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.*
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions
 | 
					 | 
				
			||||||
import java.awt.Desktop
 | 
					 | 
				
			||||||
import java.lang.Exception
 | 
					 | 
				
			||||||
import java.net.URL
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class BuilderView : View() {
 | 
					 | 
				
			||||||
    private val projectTypeView = ProjectTypeView()
 | 
					 | 
				
			||||||
    private val mavenInfoView = MavenInfoView()
 | 
					 | 
				
			||||||
    private val licensesView = LicensesView()
 | 
					 | 
				
			||||||
    private var saveAvailableState by mutableStateOf(false)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override val defaultModifier: Modifier = Modifier.fillMaxSize()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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() {
 | 
					 | 
				
			||||||
        Box(Modifier.fillMaxSize()) {
 | 
					 | 
				
			||||||
            Column() {
 | 
					 | 
				
			||||||
                TopAppBar(
 | 
					 | 
				
			||||||
                    @Composable {
 | 
					 | 
				
			||||||
                        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"
 | 
					 | 
				
			||||||
                                )
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if (saveAvailableState) {
 | 
					 | 
				
			||||||
                            IconButton(
 | 
					 | 
				
			||||||
                                {
 | 
					 | 
				
			||||||
                                    exportGradle(config)
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            ) {
 | 
					 | 
				
			||||||
                                Image(
 | 
					 | 
				
			||||||
                                    painter = svgResource("images/export_gradle.svg"),
 | 
					 | 
				
			||||||
                                    contentDescription = "Export Gradle script"
 | 
					 | 
				
			||||||
                                )
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        IconButton(
 | 
					 | 
				
			||||||
                            {
 | 
					 | 
				
			||||||
                                if (saveAs(config)) {
 | 
					 | 
				
			||||||
                                    saveAvailableState = true
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        ) {
 | 
					 | 
				
			||||||
                            Image(
 | 
					 | 
				
			||||||
                                painter = svgResource("images/save_as.svg"),
 | 
					 | 
				
			||||||
                                contentDescription = "Export Gradle script"
 | 
					 | 
				
			||||||
                            )
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                Column(Modifier.padding(8.dp)) {
 | 
					 | 
				
			||||||
                    projectTypeView.init()
 | 
					 | 
				
			||||||
                    Divider()
 | 
					 | 
				
			||||||
                    licensesView.init()
 | 
					 | 
				
			||||||
                    Divider()
 | 
					 | 
				
			||||||
                    mavenInfoView.init()
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,95 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import androidx.compose.foundation.clickable
 | 
					 | 
				
			||||||
import androidx.compose.foundation.layout.*
 | 
					 | 
				
			||||||
import androidx.compose.material.Button
 | 
					 | 
				
			||||||
import androidx.compose.material.Divider
 | 
					 | 
				
			||||||
import androidx.compose.runtime.*
 | 
					 | 
				
			||||||
import androidx.compose.ui.Modifier
 | 
					 | 
				
			||||||
import androidx.compose.ui.unit.dp
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.License
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.*
 | 
					 | 
				
			||||||
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.toLowerCase() 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")
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,33 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import androidx.compose.foundation.layout.*
 | 
					 | 
				
			||||||
import androidx.compose.material.*
 | 
					 | 
				
			||||||
import androidx.compose.runtime.*
 | 
					 | 
				
			||||||
import androidx.compose.ui.Modifier
 | 
					 | 
				
			||||||
import androidx.compose.ui.unit.dp
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
abstract class ListView<T>(title: String) : VerticalView(title) {
 | 
					 | 
				
			||||||
    protected val itemsList = mutableStateListOf<T>()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected open val addItemText: String = "Add"
 | 
					 | 
				
			||||||
    protected open val removeItemText: String = "Remove"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected abstract fun createItem(): T
 | 
					 | 
				
			||||||
    @Composable
 | 
					 | 
				
			||||||
    protected abstract fun buildView(item: T)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override val content: @Composable ColumnScope.() -> Unit = {
 | 
					 | 
				
			||||||
        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)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,76 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import androidx.compose.foundation.layout.ColumnScope
 | 
					 | 
				
			||||||
import androidx.compose.runtime.*
 | 
					 | 
				
			||||||
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 includeGpgSignProperty by mutableStateOf(true)
 | 
					 | 
				
			||||||
    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,
 | 
					 | 
				
			||||||
            includeGpgSignProperty,
 | 
					 | 
				
			||||||
            developersView.developers,
 | 
					 | 
				
			||||||
            repositoriesView.repositories + if (publishToMavenCentralProperty) {
 | 
					 | 
				
			||||||
                listOf(SonatypeRepository)
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                emptyList()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        set(value) {
 | 
					 | 
				
			||||||
            projectNameProperty = value.name
 | 
					 | 
				
			||||||
            projectDescriptionProperty = value.description
 | 
					 | 
				
			||||||
            projectUrlProperty = value.url
 | 
					 | 
				
			||||||
            projectVcsUrlProperty = value.vcsUrl
 | 
					 | 
				
			||||||
            includeGpgSignProperty = value.includeGpgSigning
 | 
					 | 
				
			||||||
            publishToMavenCentralProperty = value.repositories.any { it == SonatypeRepository }
 | 
					 | 
				
			||||||
            developersView.developers = value.developers
 | 
					 | 
				
			||||||
            repositoriesView.repositories = value.repositories.filter { it != SonatypeRepository }
 | 
					 | 
				
			||||||
//            developersView.developers = value.developers
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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 }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        SwitchWithLabel(
 | 
					 | 
				
			||||||
            "Include GPG Signing",
 | 
					 | 
				
			||||||
            includeGpgSignProperty,
 | 
					 | 
				
			||||||
            placeSwitchAtTheStart = true
 | 
					 | 
				
			||||||
        ) { includeGpgSignProperty = it }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        SwitchWithLabel(
 | 
					 | 
				
			||||||
            "Include publication to MavenCentral",
 | 
					 | 
				
			||||||
            publishToMavenCentralProperty,
 | 
					 | 
				
			||||||
            placeSwitchAtTheStart = true
 | 
					 | 
				
			||||||
        ) { publishToMavenCentralProperty = it }
 | 
					 | 
				
			||||||
        developersView.init()
 | 
					 | 
				
			||||||
        repositoriesView.init()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,33 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import androidx.compose.foundation.layout.*
 | 
					 | 
				
			||||||
import androidx.compose.material.Switch
 | 
					 | 
				
			||||||
import androidx.compose.material.Text
 | 
					 | 
				
			||||||
import androidx.compose.runtime.*
 | 
					 | 
				
			||||||
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
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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())
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,45 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.desktop.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import androidx.compose.runtime.*
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.desktop.utils.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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 }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -16,7 +16,6 @@ allprojects {
 | 
				
			|||||||
        mppProjectWithSerializationPresetPath = "${rootProject.projectDir.absolutePath}/mppProjectWithSerialization.gradle"
 | 
					        mppProjectWithSerializationPresetPath = "${rootProject.projectDir.absolutePath}/mppProjectWithSerialization.gradle"
 | 
				
			||||||
        mppJavaProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJavaProject.gradle"
 | 
					        mppJavaProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJavaProject.gradle"
 | 
				
			||||||
        mppJsProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJsProject.gradle"
 | 
					        mppJsProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppJsProject.gradle"
 | 
				
			||||||
        mppAndroidProjectPresetPath = "${rootProject.projectDir.absolutePath}/mppAndroidProject.gradle"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        defaultAndroidSettingsPresetPath = "${rootProject.projectDir.absolutePath}/defaultAndroidSettings.gradle"
 | 
					        defaultAndroidSettingsPresetPath = "${rootProject.projectDir.absolutePath}/defaultAndroidSettings.gradle"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,30 +3,18 @@ org.gradle.parallel=true
 | 
				
			|||||||
kotlin.js.generate.externals=true
 | 
					kotlin.js.generate.externals=true
 | 
				
			||||||
kotlin.incremental=true
 | 
					kotlin.incremental=true
 | 
				
			||||||
kotlin.incremental.js=true
 | 
					kotlin.incremental.js=true
 | 
				
			||||||
android.useAndroidX=true
 | 
					 | 
				
			||||||
android.enableJetifier=true
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
kotlin_version=1.4.31
 | 
					kotlin_version=1.7.20
 | 
				
			||||||
kotlin_coroutines_version=1.4.3
 | 
					kotlin_coroutines_version=1.6.4
 | 
				
			||||||
kotlin_serialisation_core_version=1.1.0
 | 
					kotlin_serialisation_core_version=1.4.1
 | 
				
			||||||
ktor_version=1.5.2
 | 
					ktor_version=2.1.3
 | 
				
			||||||
micro_utils_version=0.4.36
 | 
					micro_utils_version=0.14.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
compose_version=0.3.2
 | 
					compose_version=1.2.1
 | 
				
			||||||
 | 
					 | 
				
			||||||
# ANDROID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
android_minSdkVersion=21
 | 
					 | 
				
			||||||
android_compileSdkVersion=30
 | 
					 | 
				
			||||||
android_buildToolsVersion=30.0.2
 | 
					 | 
				
			||||||
dexcount_version=2.0.0
 | 
					 | 
				
			||||||
junit_version=4.12
 | 
					 | 
				
			||||||
test_ext_junit_version=1.1.2
 | 
					 | 
				
			||||||
espresso_core=3.3.0
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Dokka
 | 
					# Dokka
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dokka_version=1.4.20
 | 
					dokka_version=1.7.20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Project data
 | 
					# Project data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										45
									
								
								gradle/libs.versions.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					[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"
 | 
				
			||||||
 | 
					kjsuikit = "0.4.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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" }
 | 
				
			||||||
 | 
					ktor-client-js = { module = "io.ktor:ktor-client-js", 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" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jsuikit = { module = "dev.inmo:kjsuikit", version.ref = "kjsuikit" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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" }
 | 
				
			||||||
							
								
								
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
 | 
				
			|||||||
distributionPath=wrapper/dists
 | 
					distributionPath=wrapper/dists
 | 
				
			||||||
zipStoreBase=GRADLE_USER_HOME
 | 
					zipStoreBase=GRADLE_USER_HOME
 | 
				
			||||||
zipStorePath=wrapper/dists
 | 
					zipStorePath=wrapper/dists
 | 
				
			||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
 | 
					distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,9 +4,7 @@ project.group = "$group"
 | 
				
			|||||||
// apply from: "$publishGradlePath"
 | 
					// apply from: "$publishGradlePath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kotlin {
 | 
					kotlin {
 | 
				
			||||||
    jvm {
 | 
					    jvm()
 | 
				
			||||||
        compilations.main.kotlinOptions.useIR = true
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sourceSets {
 | 
					    sourceSets {
 | 
				
			||||||
        commonMain {
 | 
					        commonMain {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,10 +5,8 @@ project.group = "$group"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
kotlin {
 | 
					kotlin {
 | 
				
			||||||
    js (IR) {
 | 
					    js (IR) {
 | 
				
			||||||
        browser {
 | 
					        browser()
 | 
				
			||||||
            binaries.executable()
 | 
					        binaries.executable()
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        nodejs()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sourceSets {
 | 
					    sourceSets {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,16 +4,11 @@ project.group = "$group"
 | 
				
			|||||||
// apply from: "$publishGradlePath"
 | 
					// apply from: "$publishGradlePath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kotlin {
 | 
					kotlin {
 | 
				
			||||||
    jvm {
 | 
					    jvm()
 | 
				
			||||||
        compilations.main.kotlinOptions.useIR = true
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    js (IR) {
 | 
					    js (IR) {
 | 
				
			||||||
        browser()
 | 
					        browser()
 | 
				
			||||||
        nodejs()
 | 
					        nodejs()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    android {
 | 
					 | 
				
			||||||
        publishAllLibraryVariants()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sourceSets {
 | 
					    sourceSets {
 | 
				
			||||||
        commonMain {
 | 
					        commonMain {
 | 
				
			||||||
@@ -39,14 +34,5 @@ kotlin {
 | 
				
			|||||||
                implementation kotlin('test-junit')
 | 
					                implementation kotlin('test-junit')
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        androidTest {
 | 
					 | 
				
			||||||
            dependencies {
 | 
					 | 
				
			||||||
                implementation kotlin('test-junit')
 | 
					 | 
				
			||||||
                implementation "androidx.test.ext:junit:$test_ext_junit_version"
 | 
					 | 
				
			||||||
                implementation "androidx.test.espresso:espresso-core:$espresso_core"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
apply from: "$defaultAndroidSettingsPresetPath"
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,8 +9,8 @@ rootProject.name = 'kmppscriptbuilder'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
String[] includes = [
 | 
					String[] includes = [
 | 
				
			||||||
        ":core",
 | 
					        ":core",
 | 
				
			||||||
        ":desktop",
 | 
					//        ":desktop",
 | 
				
			||||||
        ":web"
 | 
					//        ":web"
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +0,0 @@
 | 
				
			|||||||
plugins {
 | 
					 | 
				
			||||||
    id "org.jetbrains.kotlin.multiplatform"
 | 
					 | 
				
			||||||
    id "org.jetbrains.kotlin.plugin.serialization"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
apply from: "$mppJsProjectPresetPath"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
kotlin {
 | 
					 | 
				
			||||||
    sourceSets {
 | 
					 | 
				
			||||||
        commonMain {
 | 
					 | 
				
			||||||
            dependencies {
 | 
					 | 
				
			||||||
                implementation project(":kmppscriptbuilder.core")
 | 
					 | 
				
			||||||
                implementation "dev.inmo:micro_utils.common:$micro_utils_version"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,82 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.web.views.*
 | 
					 | 
				
			||||||
import kotlinx.browser.document
 | 
					 | 
				
			||||||
import kotlinx.dom.appendElement
 | 
					 | 
				
			||||||
import org.w3c.dom.*
 | 
					 | 
				
			||||||
import org.w3c.dom.url.URL
 | 
					 | 
				
			||||||
import org.w3c.files.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fun main() {
 | 
					 | 
				
			||||||
    document.addEventListener(
 | 
					 | 
				
			||||||
        "DOMContentLoaded",
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            val builderView = BuilderView()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            (document.getElementById("openConfig") as HTMLElement).onclick = {
 | 
					 | 
				
			||||||
                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
 | 
					 | 
				
			||||||
                                    builderView.config = serialFormat.decodeFromString(Config.serializer(), content)
 | 
					 | 
				
			||||||
                                    false
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                reader.readAsText(file)
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                targetInput.click()
 | 
					 | 
				
			||||||
                targetInput.remove()
 | 
					 | 
				
			||||||
                false
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            (document.getElementById("saveConfig") as HTMLElement).onclick = {
 | 
					 | 
				
			||||||
                val filename = "publish.kpsb"
 | 
					 | 
				
			||||||
                val content = serialFormat.encodeToString(Config.serializer(), builderView.config)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                saveFile(content, filename)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                false
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            (document.getElementById("exportScript") as HTMLElement).onclick = {
 | 
					 | 
				
			||||||
                val filename = "publish.gradle"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                val content = builderView.config.run {
 | 
					 | 
				
			||||||
                    type.buildMavenGradleConfig(
 | 
					 | 
				
			||||||
                        mavenConfig,
 | 
					 | 
				
			||||||
                        licenses
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                saveFile(content, filename)
 | 
					 | 
				
			||||||
                false
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.utils
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.w3c.dom.HTMLElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var HTMLElement.ukActive: Boolean
 | 
					 | 
				
			||||||
    get() = classList.contains("uk-active")
 | 
					 | 
				
			||||||
    set(value) {
 | 
					 | 
				
			||||||
        if (value) {
 | 
					 | 
				
			||||||
            classList.add("uk-active")
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            classList.remove("uk-active")
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.utils
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import kotlinx.browser.document
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
inline fun <R> keepScrolling(crossinline block: () -> R): R = document.body ?.let {
 | 
					 | 
				
			||||||
    val (x, y) = (it.scrollLeft to it.scrollTop)
 | 
					 | 
				
			||||||
    return block().also { _ ->
 | 
					 | 
				
			||||||
        it.scrollTo(x, y)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
} ?: block()
 | 
					 | 
				
			||||||
@@ -1,23 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.Config
 | 
					 | 
				
			||||||
import kotlinx.browser.document
 | 
					 | 
				
			||||||
import org.w3c.dom.HTMLElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class BuilderView : View {
 | 
					 | 
				
			||||||
    private val projectTypeView = ProjectTypeView()
 | 
					 | 
				
			||||||
    private val licensesView = LicensesView(document.getElementById("licensesListDiv") as HTMLElement)
 | 
					 | 
				
			||||||
    private val mavenInfoTypeView = MavenProjectInfoView()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var config: Config
 | 
					 | 
				
			||||||
        get() = Config(
 | 
					 | 
				
			||||||
            licensesView.licenses,
 | 
					 | 
				
			||||||
            mavenInfoTypeView.mavenConfig,
 | 
					 | 
				
			||||||
            projectTypeView.projectType
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        set(value) {
 | 
					 | 
				
			||||||
            licensesView.licenses = value.licenses
 | 
					 | 
				
			||||||
            mavenInfoTypeView.mavenConfig = value.mavenConfig
 | 
					 | 
				
			||||||
            projectTypeView.projectType = value.type
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,35 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.Developer
 | 
					 | 
				
			||||||
import org.w3c.dom.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class DevelopersView(rootElement: HTMLElement) : MutableListView<Developer>(rootElement, "Add developer", "Remove developer") {
 | 
					 | 
				
			||||||
    private val HTMLElement.usernameElement: HTMLInputElement
 | 
					 | 
				
			||||||
        get() = getElementsByTagName("input")[0] as HTMLInputElement
 | 
					 | 
				
			||||||
    private val HTMLElement.nameElement: HTMLInputElement
 | 
					 | 
				
			||||||
        get() = getElementsByTagName("input")[1] as HTMLInputElement
 | 
					 | 
				
			||||||
    private val HTMLElement.emailElement: HTMLInputElement
 | 
					 | 
				
			||||||
        get() = getElementsByTagName("input")[2] as HTMLInputElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var developers: List<Developer>
 | 
					 | 
				
			||||||
        get() = elements.map {
 | 
					 | 
				
			||||||
            Developer(it.usernameElement.value, it.nameElement.value, it.emailElement.value)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        set(value) {
 | 
					 | 
				
			||||||
            data = value
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun createPlainObject(): Developer = Developer("", "", "")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun HTMLElement.addContentBeforeRemoveButton(value: Developer) {
 | 
					 | 
				
			||||||
        createTextField("Developer ID", "Developer username").value = value.id
 | 
					 | 
				
			||||||
        createTextField("Developer name", "").value = value.name
 | 
					 | 
				
			||||||
        createTextField("Developer E-Mail", "").value = value.eMail
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun HTMLElement.updateElement(from: Developer, to: Developer) {
 | 
					 | 
				
			||||||
        usernameElement.value = to.id
 | 
					 | 
				
			||||||
        nameElement.value = to.name
 | 
					 | 
				
			||||||
        emailElement.value = to.eMail
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,113 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.License
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.coroutines.safeActor
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
 | 
					 | 
				
			||||||
import io.ktor.client.HttpClient
 | 
					 | 
				
			||||||
import kotlinx.coroutines.*
 | 
					 | 
				
			||||||
import kotlinx.coroutines.channels.Channel
 | 
					 | 
				
			||||||
import kotlinx.coroutines.channels.SendChannel
 | 
					 | 
				
			||||||
import kotlinx.coroutines.flow.consumeAsFlow
 | 
					 | 
				
			||||||
import kotlinx.coroutines.flow.debounce
 | 
					 | 
				
			||||||
import kotlinx.dom.appendElement
 | 
					 | 
				
			||||||
import org.w3c.dom.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class LicensesView(
 | 
					 | 
				
			||||||
    rootElement: HTMLElement,
 | 
					 | 
				
			||||||
    client: HttpClient = HttpClient(),
 | 
					 | 
				
			||||||
    scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
 | 
					 | 
				
			||||||
) : MutableListView<License>(rootElement, "Add empty license", "Remove license") {
 | 
					 | 
				
			||||||
    private val HTMLElement.idElement: HTMLInputElement
 | 
					 | 
				
			||||||
        get() = getElementsByTagName("input")[0] as HTMLInputElement
 | 
					 | 
				
			||||||
    private val HTMLElement.titleElement: HTMLInputElement
 | 
					 | 
				
			||||||
        get() = getElementsByTagName("input")[1] as HTMLInputElement
 | 
					 | 
				
			||||||
    private val HTMLElement.urlElement: HTMLInputElement
 | 
					 | 
				
			||||||
        get() = getElementsByTagName("input")[2] as HTMLInputElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private class LicenseOfferList(
 | 
					 | 
				
			||||||
        rootElement: HTMLElement,
 | 
					 | 
				
			||||||
        private val licensesView: LicensesView,
 | 
					 | 
				
			||||||
        client: HttpClient,
 | 
					 | 
				
			||||||
        scope: CoroutineScope
 | 
					 | 
				
			||||||
    ) : ListView<License>(rootElement, useSimpleDiffStrategy = true) {
 | 
					 | 
				
			||||||
        private var licensesTemplates: List<License> = emptyList()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        init {
 | 
					 | 
				
			||||||
            scope.launch {
 | 
					 | 
				
			||||||
                licensesTemplates = client.getLicenses().values.toList()
 | 
					 | 
				
			||||||
                changeActor.send(Unit) // update list of searches
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private val changeActor: SendChannel<Unit> = scope.run {
 | 
					 | 
				
			||||||
            val onChangeActor = Channel<Unit>(Channel.CONFLATED)
 | 
					 | 
				
			||||||
            onChangeActor.consumeAsFlow().subscribeSafelyWithoutExceptions(scope) {
 | 
					 | 
				
			||||||
                val lowercased = searchString
 | 
					 | 
				
			||||||
                data = if (lowercased.isEmpty()) {
 | 
					 | 
				
			||||||
                    emptyList()
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    licensesTemplates.filter {
 | 
					 | 
				
			||||||
                        val lowercasedTitle = it.title.toLowerCase()
 | 
					 | 
				
			||||||
                        lowercased.all { it in lowercasedTitle }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            onChangeActor
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        private val searchElement = rootElement.createTextField("Quick add", "Type some license name part to find it").apply {
 | 
					 | 
				
			||||||
            oninput = {
 | 
					 | 
				
			||||||
                changeActor.offer(Unit)
 | 
					 | 
				
			||||||
                false
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        private var searchString: String
 | 
					 | 
				
			||||||
            get() = searchElement.value.toLowerCase()
 | 
					 | 
				
			||||||
            set(value) {
 | 
					 | 
				
			||||||
                searchElement.value = value
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        override fun HTMLElement.placeElement(value: License) {
 | 
					 | 
				
			||||||
            createCommonButton(value.title).onclick = {
 | 
					 | 
				
			||||||
                searchString = ""
 | 
					 | 
				
			||||||
                licensesView.licenses += value
 | 
					 | 
				
			||||||
                changeActor.offer(Unit)
 | 
					 | 
				
			||||||
                false
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        override fun HTMLElement.updateElement(from: License, to: License) {
 | 
					 | 
				
			||||||
            getElementsByTagName("button")[0] ?.remove()
 | 
					 | 
				
			||||||
            placeElement(to)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private val licensesOffersList = LicenseOfferList(
 | 
					 | 
				
			||||||
        rootElement.appendElement("div") { classList.add("uk-padding-small") } as HTMLElement,
 | 
					 | 
				
			||||||
        this,
 | 
					 | 
				
			||||||
        client,
 | 
					 | 
				
			||||||
        scope
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var licenses: List<License>
 | 
					 | 
				
			||||||
        get() = elements.map {
 | 
					 | 
				
			||||||
            License(it.idElement.value, it.titleElement.value, it.urlElement.value)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        set(value) {
 | 
					 | 
				
			||||||
            data = value
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun createPlainObject(): License = License("", "", "")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun HTMLElement.addContentBeforeRemoveButton(value: License) {
 | 
					 | 
				
			||||||
        createTextField("License Id", "Short name like \"Apache-2.0\"").value = value.id
 | 
					 | 
				
			||||||
        createTextField("License Title", "Official title of license (like \"Apache Software License 2.0\")").value = value.title
 | 
					 | 
				
			||||||
        createTextField("License URL", "Link to your LICENSE file OR official license file (like \"https://opensource.org/licenses/Apache-2.0\")").value = value.url ?: ""
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun HTMLElement.updateElement(from: License, to: License) {
 | 
					 | 
				
			||||||
        idElement.value = to.id
 | 
					 | 
				
			||||||
        titleElement.value = to.title
 | 
					 | 
				
			||||||
        urlElement.value = to.url ?: ""
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,58 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.micro_utils.common.calculateStrictDiff
 | 
					 | 
				
			||||||
import kotlinx.dom.appendElement
 | 
					 | 
				
			||||||
import org.w3c.dom.HTMLElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
abstract class ListView<T>(
 | 
					 | 
				
			||||||
    protected val rootElement: HTMLElement,
 | 
					 | 
				
			||||||
    useSimpleDiffStrategy: Boolean = false
 | 
					 | 
				
			||||||
) : View {
 | 
					 | 
				
			||||||
    protected val elements = mutableListOf<HTMLElement>()
 | 
					 | 
				
			||||||
    private val diffHandling: (old: List<T>, new: List<T>) -> Unit = if (useSimpleDiffStrategy) {
 | 
					 | 
				
			||||||
        { _, new ->
 | 
					 | 
				
			||||||
            elements.forEach { it.remove() }
 | 
					 | 
				
			||||||
            elements.clear()
 | 
					 | 
				
			||||||
            new.forEach {
 | 
					 | 
				
			||||||
                val element = instantiateElement()
 | 
					 | 
				
			||||||
                elements.add(element)
 | 
					 | 
				
			||||||
                element.placeElement(it)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        {  old, new ->
 | 
					 | 
				
			||||||
            val diff = old.calculateStrictDiff(new)
 | 
					 | 
				
			||||||
            diff.removed.forEach {
 | 
					 | 
				
			||||||
                elements[it.index].remove()
 | 
					 | 
				
			||||||
                elements.removeAt(it.index)
 | 
					 | 
				
			||||||
                println(it.value)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            diff.added.forEach {
 | 
					 | 
				
			||||||
                val element = instantiateElement()
 | 
					 | 
				
			||||||
                elements.add(element)
 | 
					 | 
				
			||||||
                element.placeElement(it.value)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            diff.replaced.forEach { (old, new) ->
 | 
					 | 
				
			||||||
                val element = elements.getOrNull(old.index) ?.also { it.updateElement(old.value, new.value) }
 | 
					 | 
				
			||||||
                if (element == null) {
 | 
					 | 
				
			||||||
                    val newElement = instantiateElement()
 | 
					 | 
				
			||||||
                    newElement.placeElement(new.value)
 | 
					 | 
				
			||||||
                    elements[new.index] = newElement
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    protected var data: List<T> = emptyList()
 | 
					 | 
				
			||||||
        set(value) {
 | 
					 | 
				
			||||||
            val old = field
 | 
					 | 
				
			||||||
            field = value
 | 
					 | 
				
			||||||
            diffHandling(old, value)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected abstract fun HTMLElement.placeElement(value: T)
 | 
					 | 
				
			||||||
    protected abstract fun HTMLElement.updateElement(from: T, to: T)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun instantiateElement() = rootElement.appendElement("div") {
 | 
					 | 
				
			||||||
        classList.add("uk-padding-small")
 | 
					 | 
				
			||||||
    } as HTMLElement
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,43 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.*
 | 
					 | 
				
			||||||
import kotlinx.browser.document
 | 
					 | 
				
			||||||
import org.w3c.dom.HTMLElement
 | 
					 | 
				
			||||||
import org.w3c.dom.HTMLInputElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MavenProjectInfoView : View {
 | 
					 | 
				
			||||||
    private val nameElement = document.getElementById("projectNameInput") as HTMLInputElement
 | 
					 | 
				
			||||||
    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 includeMavenCentralElement = document.getElementById("includeMavenCentralTargetRepoToggle") as HTMLInputElement
 | 
					 | 
				
			||||||
    private val developersView = DevelopersView(document.getElementById("developersListDiv") as HTMLElement)
 | 
					 | 
				
			||||||
    private val repositoriesView = RepositoriesView(document.getElementById("repositoriesListDiv") as HTMLElement)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var mavenConfig: MavenConfig
 | 
					 | 
				
			||||||
        get() = MavenConfig(
 | 
					 | 
				
			||||||
            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()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        set(value) {
 | 
					 | 
				
			||||||
            nameElement.value = value.name
 | 
					 | 
				
			||||||
            descriptionElement.value = value.description
 | 
					 | 
				
			||||||
            urlElement.value = value.url
 | 
					 | 
				
			||||||
            vcsUrlElement.value = value.vcsUrl
 | 
					 | 
				
			||||||
            includeGpgElement.checked = value.includeGpgSigning
 | 
					 | 
				
			||||||
            developersView.developers = value.developers
 | 
					 | 
				
			||||||
            val reposWithoutSonatype = value.repositories.filter { it != SonatypeRepository }
 | 
					 | 
				
			||||||
            includeMavenCentralElement.checked = value.repositories.size != reposWithoutSonatype.size
 | 
					 | 
				
			||||||
            repositoriesView.repositories = reposWithoutSonatype
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,41 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.web.utils.keepScrolling
 | 
					 | 
				
			||||||
import org.w3c.dom.HTMLElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
abstract class MutableListView<T>(
 | 
					 | 
				
			||||||
    rootElement: HTMLElement,
 | 
					 | 
				
			||||||
    addButtonText: String = "Add",
 | 
					 | 
				
			||||||
    private val removeButtonText: String = "Remove"
 | 
					 | 
				
			||||||
) : ListView<T>(rootElement) {
 | 
					 | 
				
			||||||
    init {
 | 
					 | 
				
			||||||
        rootElement.createPrimaryButton(addButtonText).apply {
 | 
					 | 
				
			||||||
            onclick = {
 | 
					 | 
				
			||||||
                keepScrolling {
 | 
					 | 
				
			||||||
                    val newObject = createPlainObject()
 | 
					 | 
				
			||||||
                    data += newObject
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                false
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected abstract fun createPlainObject(): T
 | 
					 | 
				
			||||||
    protected open fun HTMLElement.addContentBeforeRemoveButton(value: T) {}
 | 
					 | 
				
			||||||
    protected open fun HTMLElement.addContentAfterRemoveButton(value: T) {}
 | 
					 | 
				
			||||||
    final override fun HTMLElement.placeElement(value: T) {
 | 
					 | 
				
			||||||
        addContentBeforeRemoveButton(value)
 | 
					 | 
				
			||||||
        addRemoveButton()
 | 
					 | 
				
			||||||
        addContentAfterRemoveButton(value)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun HTMLElement.addRemoveButton() {
 | 
					 | 
				
			||||||
        val button = createPrimaryButton(removeButtonText)
 | 
					 | 
				
			||||||
        button.onclick = {
 | 
					 | 
				
			||||||
            elements.indexOf(button.parentElement).takeIf { it > -1 } ?.also {
 | 
					 | 
				
			||||||
                data -= data[it]
 | 
					 | 
				
			||||||
            } ?: rootElement.removeChild(this@addRemoveButton)
 | 
					 | 
				
			||||||
            false
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,33 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.*
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.web.utils.ukActive
 | 
					 | 
				
			||||||
import kotlinx.browser.document
 | 
					 | 
				
			||||||
import org.w3c.dom.HTMLElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ProjectTypeView : View {
 | 
					 | 
				
			||||||
    private val mppProjectTypeElement = document.getElementById("mppProjectType") as HTMLElement
 | 
					 | 
				
			||||||
    private val jvmProjectTypeElement = document.getElementById("jvmProjectType") as HTMLElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var projectType: ProjectType
 | 
					 | 
				
			||||||
        get() = if (jvmProjectTypeElement.ukActive) {
 | 
					 | 
				
			||||||
            JVMProjectType
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            MultiplatformProjectType
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        set(value) {
 | 
					 | 
				
			||||||
            mppProjectTypeElement.ukActive = value == MultiplatformProjectType
 | 
					 | 
				
			||||||
            jvmProjectTypeElement.ukActive = value == JVMProjectType
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    init {
 | 
					 | 
				
			||||||
        mppProjectTypeElement.onclick = {
 | 
					 | 
				
			||||||
            projectType = MultiplatformProjectType
 | 
					 | 
				
			||||||
            Unit
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        jvmProjectTypeElement.onclick = {
 | 
					 | 
				
			||||||
            projectType = JVMProjectType
 | 
					 | 
				
			||||||
            Unit
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
 | 
					 | 
				
			||||||
import org.w3c.dom.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class RepositoriesView(rootElement: HTMLElement) : MutableListView<MavenPublishingRepository>(rootElement, "Add repository", "Remove repository") {
 | 
					 | 
				
			||||||
    private val HTMLElement.nameElement: HTMLInputElement
 | 
					 | 
				
			||||||
        get() = getElementsByTagName("input")[0] as HTMLInputElement
 | 
					 | 
				
			||||||
    private val HTMLElement.urlElement: HTMLInputElement
 | 
					 | 
				
			||||||
        get() = getElementsByTagName("input")[1] as HTMLInputElement
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var repositories: List<MavenPublishingRepository>
 | 
					 | 
				
			||||||
        get() = elements.map {
 | 
					 | 
				
			||||||
            MavenPublishingRepository(it.nameElement.value, it.urlElement.value)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        set(value) {
 | 
					 | 
				
			||||||
            data = value
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun createPlainObject(): MavenPublishingRepository = MavenPublishingRepository("", "")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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.url
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    override fun HTMLElement.updateElement(from: MavenPublishingRepository, to: MavenPublishingRepository) {
 | 
					 | 
				
			||||||
        nameElement.value = to.name
 | 
					 | 
				
			||||||
        urlElement.value = to.url
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,3 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface View
 | 
					 | 
				
			||||||
@@ -1,35 +0,0 @@
 | 
				
			|||||||
package dev.inmo.kmppscriptbuilder.web.views
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import kotlinx.dom.appendElement
 | 
					 | 
				
			||||||
import org.w3c.dom.*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fun HTMLElement.createTextField(
 | 
					 | 
				
			||||||
    label: String,
 | 
					 | 
				
			||||||
    placeholder: String
 | 
					 | 
				
			||||||
): HTMLInputElement {
 | 
					 | 
				
			||||||
    return appendElement("div") {
 | 
					 | 
				
			||||||
        classList.add("uk-margin", "uk-width-1-1")
 | 
					 | 
				
			||||||
    }.appendElement("label") {
 | 
					 | 
				
			||||||
        classList.add("uk-form-label")
 | 
					 | 
				
			||||||
        innerHTML = label
 | 
					 | 
				
			||||||
    }.run {
 | 
					 | 
				
			||||||
        val input = appendElement("input") {
 | 
					 | 
				
			||||||
            classList.add("uk-input", "uk-width-expand")
 | 
					 | 
				
			||||||
            setAttribute("type", "text")
 | 
					 | 
				
			||||||
            setAttribute("placeholder", placeholder)
 | 
					 | 
				
			||||||
        } as HTMLInputElement
 | 
					 | 
				
			||||||
        input
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fun HTMLElement.createPrimaryButton(text: String): HTMLButtonElement = (appendElement("button") {
 | 
					 | 
				
			||||||
    classList.add("uk-button", "uk-button-primary")
 | 
					 | 
				
			||||||
} as HTMLButtonElement).apply {
 | 
					 | 
				
			||||||
    innerText = text
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fun HTMLElement.createCommonButton(text: String): HTMLButtonElement = (appendElement("button") {
 | 
					 | 
				
			||||||
    classList.add("uk-button", "uk-button-default")
 | 
					 | 
				
			||||||
} as HTMLButtonElement).apply {
 | 
					 | 
				
			||||||
    innerText = text
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,81 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang="en">
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
    <meta charset="UTF-8">
 | 
					 | 
				
			||||||
    <title>Kotlin Publication Scripts Builder</title>
 | 
					 | 
				
			||||||
    <!-- UIkit CSS -->
 | 
					 | 
				
			||||||
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.6.17/dist/css/uikit.min.css" />
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
<body>
 | 
					 | 
				
			||||||
    <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">
 | 
					 | 
				
			||||||
                <li uk-tooltip="title: Open config" id="openConfig"><a href="#"><span uk-icon="icon: pull"></span></a></li><!--Open file-->
 | 
					 | 
				
			||||||
                <li uk-tooltip="title: Save config" id="saveConfig"><a href="#"><span uk-icon="icon: push"></span></a></li><!--Save file-->
 | 
					 | 
				
			||||||
                <li uk-tooltip="title: Export script" id="exportScript"><a href="#"><span uk-icon="icon: upload"></span></a></li><!--Save file-->
 | 
					 | 
				
			||||||
            </ul>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
    </nav>
 | 
					 | 
				
			||||||
    <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>
 | 
					 | 
				
			||||||
                </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>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            <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><input id="includeGpgSignToggle" class="uk-checkbox" type="checkbox" checked> Include GPG Signing</label>
 | 
					 | 
				
			||||||
                </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="https://cdn.jsdelivr.net/npm/uikit@3.6.17/dist/js/uikit.min.js"></script>
 | 
					 | 
				
			||||||
    <script src="https://cdn.jsdelivr.net/npm/uikit@3.6.17/dist/js/uikit-icons.min.js"></script>
 | 
					 | 
				
			||||||
    <!-- Internal JS -->
 | 
					 | 
				
			||||||
    <script src="kmppscriptbuilder.web.js"></script>
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||