partially go over with compose

This commit is contained in:
2022-11-15 18:53:59 +06:00
parent 283bc5acb4
commit 70baa30127
27 changed files with 781 additions and 21 deletions

View File

@@ -0,0 +1,28 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.runtime.*
import dev.inmo.kmppscriptbuilder.core.models.Config
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
expect object BuilderViewDrawer : Drawer<BuilderView>
class BuilderView : View() {
internal val projectTypeView = ProjectTypeView()
internal val mavenInfoView = MavenInfoView()
internal val licensesView = LicensesView()
internal var saveAvailableState by mutableStateOf(false)
var config: Config
get() = Config(licensesView.licenses, mavenInfoView.mavenConfig, projectTypeView.projectType)
set(value) {
licensesView.licenses = value.licenses
mavenInfoView.mavenConfig = value.mavenConfig
projectTypeView.projectType = value.type
saveAvailableState = true
}
@Composable
override fun build() {
with(BuilderViewDrawer) { draw() }
}
}

View File

@@ -0,0 +1,29 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.runtime.*
import dev.inmo.kmppscriptbuilder.core.models.Developer
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonTextField
class DeveloperState(
id: String = "",
name: String = "",
eMail: String = ""
) {
var id: String by mutableStateOf(id)
var name: String by mutableStateOf(name)
var eMail: String by mutableStateOf(eMail)
fun toDeveloper() = Developer(id, name, eMail)
}
private fun Developer.toDeveloperState() = DeveloperState(id, name, eMail)
class DevelopersView : ListView<DeveloperState>("Developers info") {
var developers = mutableStateListOf<Developer>()
override val addItemText: String = "Add developer"
override val removeItemText: String = "Remove developer"
override fun createItem(): DeveloperState = DeveloperState()
}

View File

@@ -0,0 +1,88 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.runtime.*
import dev.inmo.kmppscriptbuilder.core.models.License
import dev.inmo.kmppscriptbuilder.core.models.getLicenses
import io.ktor.client.HttpClient
import kotlinx.coroutines.*
private class LicenseState(
id: String = "",
title: String = "",
url: String? = null
) {
var id: String by mutableStateOf(id)
var title: String by mutableStateOf(title)
var url: String? by mutableStateOf(url)
fun toLicense() = License(id, title, url)
}
private fun License.toLicenseState() = LicenseState(id, title, url)
class LicensesView: VerticalView("Licenses") {
private var licensesListState = mutableStateListOf<LicenseState>()
var licenses: List<License>
get() = licensesListState.map { it.toLicense() }
set(value) {
licensesListState.clear()
licensesListState.addAll(value.map { it.toLicenseState() })
}
private val availableLicensesState = mutableStateListOf<License>()
private val licensesOffersToShow = mutableStateListOf<License>()
private var licenseSearchFilter by mutableStateOf("")
init {
CoroutineScope(Dispatchers.Default).launch {
val client = HttpClient()
availableLicensesState.addAll(client.getLicenses().values)
client.close()
}
}
override val content: @Composable ColumnScope.() -> Unit = {
CommonTextField(licenseSearchFilter, "Search filter") { filterText ->
licenseSearchFilter = filterText
licensesOffersToShow.clear()
if (licenseSearchFilter.isNotEmpty()) {
licensesOffersToShow.addAll(
availableLicensesState.filter { filterText.all { symbol -> symbol.lowercaseChar() in it.title } }
)
}
}
Column {
licensesOffersToShow.forEach {
Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
CommonText(it.title, Modifier.clickable {
licensesListState.add(it.toLicenseState())
licenseSearchFilter = ""
licensesOffersToShow.clear()
})
Divider()
}
}
}
Button({ licensesListState.add(LicenseState()) }, Modifier.padding(8.dp)) {
CommonText("Add empty license")
}
licensesListState.forEach { license ->
Column(Modifier.padding(8.dp)) {
CommonTextField(
license.id,
"License ID"
) { license.id = it }
CommonTextField(
license.title,
"License title"
) { license.title = it }
CommonTextField(
license.url ?: "",
"License URL"
) { license.url = it }
Button({ licensesListState.remove(license) }, Modifier.padding(8.dp)) {
CommonText("Remove")
}
}
}
}
}

View File

@@ -0,0 +1,26 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
expect class ListViewDrawer<T>() : Drawer<ListView<T>>
abstract class ListView<T>(protected val title: String) : View() {
internal val itemsList = mutableStateListOf<T>()
internal open val addItemText: String = "Add"
internal open val removeItemText: String = "Remove"
internal abstract fun createItem(): T
@Composable
internal abstract fun buildView(item: T)
protected val drawer = ListViewDrawer<T>()
override fun build() {
DrawVertically(title) {
with(drawer) { draw() }
}
}
}

View File

@@ -0,0 +1,104 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.VerticalAlignmentLine
import androidx.compose.ui.unit.dp
import dev.inmo.kmppscriptbuilder.core.models.*
import dev.inmo.kmppscriptbuilder.desktop.utils.*
class MavenInfoView : VerticalView("Project information") {
private var projectNameProperty by mutableStateOf("")
private var projectDescriptionProperty by mutableStateOf("")
private var projectUrlProperty by mutableStateOf("")
private var projectVcsUrlProperty by mutableStateOf("")
private var gpgSignProperty by mutableStateOf<GpgSigning>(GpgSigning.Disabled)
private var publishToMavenCentralProperty by mutableStateOf(false)
private val developersView = DevelopersView()
private val repositoriesView = RepositoriesView()
var mavenConfig: MavenConfig
get() = MavenConfig(
projectNameProperty.ifBlank { defaultProjectName },
projectDescriptionProperty.ifBlank { defaultProjectDescription },
projectUrlProperty,
projectVcsUrlProperty,
developersView.developers,
repositoriesView.repositories + if (publishToMavenCentralProperty) {
listOf(SonatypeRepository)
} else {
emptyList()
},
gpgSignProperty
)
set(value) {
projectNameProperty = value.name
projectDescriptionProperty = value.description
projectUrlProperty = value.url
projectVcsUrlProperty = value.vcsUrl
gpgSignProperty = if (value.includeGpgSigning) {
GpgSigning.Enabled
} else {
value.gpgSigning
}
publishToMavenCentralProperty = value.repositories.any { it == SonatypeRepository }
developersView.developers = value.developers
repositoriesView.repositories = value.repositories.filter { it != SonatypeRepository }
// developersView.developers = value.developers
}
@Composable
private fun addGpgSigningButton(gpgSigning: GpgSigning) {
if (gpgSignProperty == gpgSigning) {
Button({}, Modifier.padding(8.dp)) {
Text(gpgSigning.name)
}
} else {
OutlinedButton(
{
gpgSignProperty = gpgSigning
},
Modifier.padding(8.dp)
) {
Text(gpgSigning.name)
}
}
}
override val content: @Composable ColumnScope.() -> Unit = {
CommonTextField(
projectNameProperty,
"Public project name"
) { projectNameProperty = it }
CommonTextField(
projectDescriptionProperty,
"Public project description"
) { projectDescriptionProperty = it }
CommonTextField(
projectUrlProperty,
"Public project URL"
) { projectUrlProperty = it }
CommonTextField(
projectVcsUrlProperty,
"Public project VCS URL (with .git)"
) { projectVcsUrlProperty = it }
Row(verticalAlignment = Alignment.CenterVertically) {
Text("Gpg Signing: ")
addGpgSigningButton(GpgSigning.Disabled)
addGpgSigningButton(GpgSigning.Optional)
addGpgSigningButton(GpgSigning.Enabled)
}
SwitchWithLabel(
"Include publication to MavenCentral",
publishToMavenCentralProperty,
placeSwitchAtTheStart = true
) { publishToMavenCentralProperty = it }
developersView.init()
repositoriesView.init()
}
}

View File

@@ -0,0 +1,40 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.inmo.kmppscriptbuilder.core.models.*
import dev.inmo.kmppscriptbuilder.desktop.utils.VerticalView
class ProjectTypeView : VerticalView("Project type") {
var projectType by mutableStateOf<ProjectType>(MultiplatformProjectType)
@Composable
private fun addProjectTypeButton(newProjectType: ProjectType) {
if (projectType == newProjectType) {
Button({}, Modifier.padding(8.dp)) {
Text(newProjectType.name)
}
} else {
OutlinedButton(
{
projectType = newProjectType
},
Modifier.padding(8.dp)
) {
Text(newProjectType.name)
}
}
}
override val content: @Composable ColumnScope.() -> Unit = {
Row(verticalAlignment = Alignment.CenterVertically) {
addProjectTypeButton(MultiplatformProjectType)
addProjectTypeButton(JVMProjectType)
addProjectTypeButton(JSProjectType)
}
}
}

View File

@@ -0,0 +1,45 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.runtime.*
import dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository
import dev.inmo.kmppscriptbuilder.desktop.utils.CommonTextField
class RepositoryState(
name: String = "",
url: String = ""
) {
var name: String by mutableStateOf(name)
var url: String by mutableStateOf(url)
fun toRepository() = MavenPublishingRepository(name, url)
}
private fun MavenPublishingRepository.toRepositoryState() = RepositoryState(name, url)
class RepositoriesView : ListView<RepositoryState>("Repositories info") {
var repositories: List<MavenPublishingRepository>
get() = itemsList.map { it.toRepository() }
set(value) {
itemsList.clear()
itemsList.addAll(
value.map { it.toRepositoryState() }
)
}
override val addItemText: String = "Add repository"
override val removeItemText: String = "Remove repository"
override fun createItem(): RepositoryState = RepositoryState()
@Composable
override fun buildView(item: RepositoryState) {
CommonTextField(
item.name,
"Repository name"
) { item.name = it }
CommonTextField(
item.url,
"Repository url"
) { item.url = it }
}
}

View File

@@ -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()
}

View File

@@ -0,0 +1,8 @@
package dev.inmo.kmppscriptbuilder.core.ui.utils
import androidx.compose.runtime.Composable
interface Drawer<T> {
@Composable
fun T.draw()
}

View File

@@ -0,0 +1,21 @@
package dev.inmo.kmppscriptbuilder.core.ui.utils
import androidx.compose.runtime.Composable
@Composable
expect fun TitleText(text: String)
@Composable
expect fun CommonText(text: String)
@Composable
expect fun CommonTextField(presetText: String, hint: String, onChange: (String) -> Unit)
@Composable
expect fun SwitchWithLabel(
label: String,
checked: Boolean,
placeSwitchAtTheStart: Boolean = false,
switchEnabled: Boolean = true,
onCheckedChange: (Boolean) -> Unit
)

View File

@@ -0,0 +1,23 @@
package dev.inmo.kmppscriptbuilder.core.utils
import dev.inmo.kmppscriptbuilder.core.models.Config
import dev.inmo.micro_utils.common.MPPFile
internal const val appExtension = "kpsb"
private var lastFile: MPPFile? = null
fun loadConfigFile(file: MPPFile): Config {
lastFile = file
return serialFormat.decodeFromString(Config.serializer(), file.text())
}
expect fun MPPFile.text(): String
expect fun loadConfig(): Config?
expect fun saveConfig(config: Config): Boolean
expect fun exportGradle(config: Config): Boolean
expect fun saveAs(config: Config): Boolean

View File

@@ -0,0 +1,3 @@
package dev.inmo.kmppscriptbuilder.core.utils
expect fun openLink(link: String): Boolean