total rework

This commit is contained in:
2022-11-16 00:56:24 +06:00
parent 53a76c7a73
commit 8430e68167
69 changed files with 904 additions and 1586 deletions

View 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
}
}
}

View File

@@ -1,65 +0,0 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Divider
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
import dev.inmo.kmppscriptbuilder.core.utils.exportGradle
import dev.inmo.kmppscriptbuilder.core.utils.loadConfig
import dev.inmo.kmppscriptbuilder.core.utils.saveAs
import dev.inmo.kmppscriptbuilder.core.utils.saveConfig
actual object BuilderViewDrawer : Drawer<BuilderView> {
override fun BuilderView.draw() {
Box(Modifier.fillMaxSize()) {
Column() {
TopAppBar(
@Composable {
Text("Kotlin publication scripts builder", Modifier.clickable { println(config) })
},
actions = {
createIcon("Open file", "images/open_file.svg") {
loadConfig()?.also {
config = it
}
}
if (saveAvailableState) {
createIcon("Save", "images/save_file.svg") {
saveConfig(config)
}
}
if (saveAvailableState) {
createIcon("Export Gradle script", "images/export_gradle.svg") {
exportGradle(config)
}
}
createIcon("Save as", "images/save_as.svg") {
if (saveAs(config)) {
saveAvailableState = true
}
}
}
)
Column(Modifier.padding(8.dp)) {
projectTypeView.init()
Divider()
licensesView.init()
Divider()
mavenInfoView.init()
}
}
}
}
}

View File

@@ -0,0 +1,39 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.OutlinedButton
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
import dev.inmo.kmppscriptbuilder.core.ui.utils.SwitchWithLabel
actual class GpgSigningOptionDrawer(
private val mavenInfoView: MavenInfoView
) : Drawer<GpgSigning> {
@Composable
override fun GpgSigning.draw() {
if (mavenInfoView.gpgSignProperty == this) {
Button({}, Modifier.padding(8.dp)) {
Text(name)
}
} else {
OutlinedButton(
{
mavenInfoView.gpgSignProperty = this
},
Modifier.padding(8.dp)
) {
Text(name)
}
}
}
}
actual fun GpgSigningOptionDrawerWithView(view: MavenInfoView): GpgSigningOptionDrawer = GpgSigningOptionDrawer(mavenInfoView = view)

View File

@@ -4,6 +4,9 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Divider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
@@ -11,44 +14,39 @@ import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
actual object LicensesDrawer : Drawer<LicensesView> {
@Composable
override fun LicensesView.draw() {
CommonTextField(licenseSearchFilter, "Search filter") { filterText ->
licenseSearchFilter = filterText
licensesOffersToShow.clear()
if (licenseSearchFilter.isNotEmpty()) {
licensesOffersToShow.addAll(
availableLicensesState.filter { filterText.all { symbol -> symbol.lowercaseChar() in it.title } }
)
}
}
Column {
licensesOffersToShow.forEach {
Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
CommonText(it.title) {
licensesListState.add(it.toLicenseState())
licenseSearchFilter = ""
licensesOffersToShow.clear()
if (searchFieldFocused.value) {
Column {
licensesOffersToShow.value.forEach {
Column(Modifier.padding(16.dp, 8.dp, 8.dp, 8.dp)) {
CommonText(it.title) {
licensesListState.add(it.toLicenseState())
licenseSearchFilter = ""
}
Divider()
}
Divider()
}
}
}
Button({ licensesListState.add(LicenseState()) }, Modifier.padding(8.dp)) {
CommonText("Add empty license",)
CommonText("Add empty license")
}
licensesListState.forEach { license ->
Column(Modifier.padding(8.dp)) {
CommonTextField(
license.id,
"License ID"
"License ID",
) { license.id = it }
CommonTextField(
license.title,
"License title"
"License title",
) { license.title = it }
CommonTextField(
license.url ?: "",
"License URL"
"License URL",
) { license.url = it }
Button({ licensesListState.remove(license) }, Modifier.padding(8.dp)) {
CommonText("Remove",)

View File

@@ -3,12 +3,14 @@ package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonText
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
actual class ListViewDrawer<T> : Drawer<ListView<T>> {
@Composable
override fun ListView<T>.draw() {
Button({ itemsList.add(createItem()) }) {
CommonText(addItemText,)

View File

@@ -1,68 +0,0 @@
package dev.inmo.kmppscriptbuilder.core.ui
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.OutlinedButton
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.inmo.kmppscriptbuilder.core.models.GpgSigning
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
import dev.inmo.kmppscriptbuilder.core.ui.utils.SwitchWithLabel
actual object MavenInfoDrawer : Drawer<MavenInfoView> {
@Composable
private fun MavenInfoView.addGpgSigningButton(gpgSigning: GpgSigning) {
if (gpgSignProperty == gpgSigning) {
Button({}, Modifier.padding(8.dp)) {
Text(gpgSigning.name)
}
} else {
OutlinedButton(
{
gpgSignProperty = gpgSigning
},
Modifier.padding(8.dp)
) {
Text(gpgSigning.name)
}
}
}
override fun MavenInfoView.draw() {
CommonTextField(
projectNameProperty,
"Public project name"
) { projectNameProperty = it }
CommonTextField(
projectDescriptionProperty,
"Public project description"
) { projectDescriptionProperty = it }
CommonTextField(
projectUrlProperty,
"Public project URL"
) { projectUrlProperty = it }
CommonTextField(
projectVcsUrlProperty,
"Public project VCS URL (with .git)"
) { projectVcsUrlProperty = it }
Row(verticalAlignment = Alignment.CenterVertically) {
Text("Gpg Signing: ")
addGpgSigningButton(GpgSigning.Disabled)
addGpgSigningButton(GpgSigning.Optional)
addGpgSigningButton(GpgSigning.Enabled)
}
SwitchWithLabel(
"Include publication to MavenCentral",
publishToMavenCentralProperty,
placeSwitchAtTheStart = true
) { publishToMavenCentralProperty = it }
developersView.init()
repositoriesView.init()
}
}

View File

@@ -15,30 +15,26 @@ import dev.inmo.kmppscriptbuilder.core.models.MultiplatformProjectType
import dev.inmo.kmppscriptbuilder.core.models.ProjectType
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
actual object ProjectTypeDrawer : Drawer<ProjectTypeView> {
actual class ProjectTypeDrawer(
private val projectTypeView: ProjectTypeView
) : Drawer<ProjectType> {
@Composable
private fun ProjectTypeView.addProjectTypeButton(newProjectType: ProjectType) {
if (projectType == newProjectType) {
override fun ProjectType.draw() {
if (projectTypeView.projectType == this) {
Button({}, Modifier.padding(8.dp)) {
Text(newProjectType.name)
Text(name)
}
} else {
OutlinedButton(
{
projectType = newProjectType
projectTypeView.projectType = this
},
Modifier.padding(8.dp)
) {
Text(newProjectType.name)
Text(name)
}
}
}
override fun ProjectTypeView.draw() {
Row(verticalAlignment = Alignment.CenterVertically) {
addProjectTypeButton(MultiplatformProjectType)
addProjectTypeButton(JVMProjectType)
addProjectTypeButton(JSProjectType)
}
}
}
actual fun ProjectTypeDrawerWithView(view: ProjectTypeView): ProjectTypeDrawer = ProjectTypeDrawer(projectTypeView = view)

View File

@@ -1,18 +0,0 @@
package dev.inmo.kmppscriptbuilder.core.ui
import dev.inmo.kmppscriptbuilder.core.ui.utils.CommonTextField
import dev.inmo.kmppscriptbuilder.core.ui.utils.Drawer
actual object RepositoryStateDrawer : Drawer<RepositoriesView> {
override fun RepositoriesView.draw() {
CommonTextField(
item.name,
"Repository name"
) { item.name = it }
CommonTextField(
item.url,
"Repository url"
) { item.url = it }
}
}

View File

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

View File

@@ -6,12 +6,14 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Divider
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Switch
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -29,15 +31,15 @@ actual fun SwitchWithLabel(
switchEnabled: Boolean,
onCheckedChange: (Boolean) -> Unit
) {
Row(Modifier.padding(0.dp, 8.dp), Arrangement.Start, Alignment.Top) {
Row(Modifier.padding(0.dp, 8.dp).clickable { onCheckedChange(!checked) }, Arrangement.Start, Alignment.Top) {
val switchCreator = @Composable {
Switch(checked, onCheckedChange, Modifier.padding(8.dp, 0.dp), enabled = switchEnabled)
Switch(checked, null, Modifier.padding(8.dp, 0.dp), enabled = switchEnabled)
}
if (placeSwitchAtTheStart) {
switchCreator()
}
Box(Modifier.fillMaxWidth().align(Alignment.CenterVertically).clickable { }) {
CommonText(label,)
Box(Modifier.fillMaxWidth().align(Alignment.CenterVertically)) {
CommonText(label)
}
if (!placeSwitchAtTheStart) {
switchCreator()
@@ -46,11 +48,18 @@ actual fun SwitchWithLabel(
}
@Composable
actual fun CommonTextField(presetText: String, hint: String, onChange: (String) -> Unit) {
actual fun CommonTextField(
presetText: String,
hint: String,
onFocusChanged: (Boolean) -> Unit,
onChange: (String) -> Unit
) {
OutlinedTextField(
presetText,
onChange,
Modifier.fillMaxWidth(),
Modifier.fillMaxWidth().onFocusChanged {
onFocusChanged(it.isFocused)
},
singleLine = true,
label = {
CommonText(hint,)
@@ -69,3 +78,15 @@ actual fun TitleText(text: String) {
text, Modifier.padding(0.dp, 8.dp), fontSize = 18.sp
)
}
@Composable
actual fun <T> ButtonsPanel(data: Iterable<T>, itemDrawer: @Composable (T) -> Unit) {
Row {
data.forEach { itemDrawer(it) }
}
}
@Composable
actual fun DefaultDivider() {
Divider()
}

View File

@@ -2,33 +2,29 @@ package dev.inmo.kmppscriptbuilder.core.utils
import dev.inmo.kmppscriptbuilder.core.models.Config
import dev.inmo.kmppscriptbuilder.core.ui.utils.FileFilter
import dev.inmo.kmppscriptbuilder.core.utils.serialFormat
import dev.inmo.micro_utils.common.MPPFile
import java.io.File
import javax.swing.JFileChooser
private const val appExtension = "kpsb"
fun MPPFile.text() = readText()
private var lastFile: File? = null
internal var lastFile: MPPFile? = null
fun loadConfigFile(file: File): Config {
fun loadConfigFile(file: MPPFile): Config {
lastFile = file
return serialFormat.decodeFromString(Config.serializer(), file.readText())
return serialFormat.decodeFromString(Config.serializer(), file.text())
}
actual fun MPPFile.text() = readText()
actual fun loadConfig(): Config? {
actual fun openNewConfig(onParsed: (Config) -> Unit) {
val fc = JFileChooser(lastFile ?.parent)
fc.addChoosableFileFilter(FileFilter("Kotlin Publication Scripts Builder", Regex(".*\\.$appExtension")))
fc.addChoosableFileFilter(FileFilter("JSON", Regex(".*\\.json")))
return when (fc.showOpenDialog(null)) {
when (fc.showOpenDialog(null)) {
JFileChooser.APPROVE_OPTION -> {
val file = fc.selectedFile
lastFile = file
return serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText())
onParsed(serialFormat.decodeFromString(Config.serializer(), fc.selectedFile.readText()))
}
else -> null
}
}