Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.plusmobileapps.devkit.ui
package com.plusmobileapps.devkit.actions

import com.intellij.notification.NotificationGroupManager
import com.intellij.notification.NotificationType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@ import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.icons.AllIcons
import com.plusmobileapps.devkit.ui.NewModuleDialog

class NewFeatureModuleAction : AnAction("New Feature Module", "Create a new module", AllIcons.Actions.ModuleDirectory) {

override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val selectedFile = e.getData(CommonDataKeys.VIRTUAL_FILE) ?: return

val dialog = NewModuleDialog(project, selectedFile)
val viewModel = NewFeatureModuleViewModel(project, selectedFile)
val dialog = NewModuleDialog(viewModel)
if (dialog.showAndGet()) {
// Dialog was confirmed, process the input
dialog.createModule()
viewModel.createModule()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.plusmobileapps.devkit.actions

object NewFeatureModuleDefaults {
fun getDefaultPublicBuildGradle(): String {
return """
plugins {
kotlin("multiplatform")
}

kotlin {
jvm()
js(IR) {
browser()
nodejs()
}

sourceSets {
val commonMain by getting {
dependencies {
// Public module dependencies
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
}
}
""".trimIndent()
}

fun getDefaultImplBuildGradle(): String {
return """
plugins {
kotlin("multiplatform")
}

kotlin {
jvm()
js(IR) {
browser()
nodejs()
}

sourceSets {
val commonMain by getting {
dependencies {
implementation(project("${'$'}projectDirectory:${'$'}directoryName:public"))
// Implementation module dependencies
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
}
}
""".trimIndent()
}

fun getDefaultTestingBuildGradle(): String {
return """
plugins {
kotlin("multiplatform")
}

kotlin {
jvm()
js(IR) {
browser()
nodejs()
}

sourceSets {
val commonMain by getting {
dependencies {
implementation(project("${'$'}projectDirectory:${'$'}directoryName:public"))
implementation(project("${'$'}projectDirectory:${'$'}directoryName:impl"))
// Testing module dependencies
implementation(kotlin("test"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
}
}
""".trimIndent()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package com.plusmobileapps.devkit.actions

import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.ValidationInfo
import com.intellij.openapi.vfs.VirtualFile
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update

class NewFeatureModuleViewModel(
private val project: Project,
private val parentDirectory: VirtualFile,
) {

val _state = MutableStateFlow(
loadPersistedValues()
)

val state: StateFlow<State> = _state.asStateFlow()

private fun loadPersistedValues(): State {
val properties: PropertiesComponent = PropertiesComponent.getInstance()
return State(
packageName = properties.getValue(PACKAGE_NAME_KEY, "com.example"),
directoryName = "",
namespace = properties.getValue(PACKAGE_NAME_KEY, "com.example"),
createPublic = true,
createImpl = true,
createTesting = false,
publicBuildGradle = properties.getValue(PUBLIC_BUILD_GRADLE_KEY, NewFeatureModuleDefaults.getDefaultPublicBuildGradle()),
implBuildGradle = properties.getValue(IMPL_BUILD_GRADLE_KEY, NewFeatureModuleDefaults.getDefaultImplBuildGradle()),
testingBuildGradle = properties.getValue(TESTING_BUILD_GRADLE_KEY, NewFeatureModuleDefaults.getDefaultTestingBuildGradle())
)
}

fun onNameSpaceUpdated(nameSpace: String) {
_state.update {
it.copy(namespace = nameSpace)
}
}

fun onPackageNameUpdated(packageName: String) {
_state.update {
it.copy(packageName = packageName)
}
updateNamespace()
}

fun onDirectoryNameUpdated(directoryName: String) {
_state.update {
it.copy(directoryName = directoryName)
}
updateNamespace()
}

fun onCreatePublicUpdated(createPublic: Boolean) {
_state.update {
it.copy(createPublic = createPublic)
}
}

fun onCreateImplUpdated(createImpl: Boolean) {
_state.update {
it.copy(createImpl = createImpl)
}
}

fun onCreateTestingUpdated(createTesting: Boolean) {
_state.update {
it.copy(createTesting = createTesting)
}
}

fun onPublicBuildGradleUpdated(publicBuildGradle: String) {
_state.update {
it.copy(publicBuildGradle = publicBuildGradle)
}
}

fun onImplBuildGradleUpdated(implBuildGradle: String) {
_state.update {
it.copy(implBuildGradle = implBuildGradle)
}
}

fun onTestingBuildGradleUpdated(testingBuildGradle: String) {
_state.update {
it.copy(testingBuildGradle = testingBuildGradle)
}
}

fun savePersistedValues() {
val properties = PropertiesComponent.getInstance()
val currentState = state.value

// Save package name and build.gradle.kts templates
properties.setValue(PACKAGE_NAME_KEY, currentState.packageName)
properties.setValue(PUBLIC_BUILD_GRADLE_KEY, currentState.publicBuildGradle)
properties.setValue(IMPL_BUILD_GRADLE_KEY, currentState.implBuildGradle)
properties.setValue(TESTING_BUILD_GRADLE_KEY, currentState.testingBuildGradle)
}

fun createModule() {
// val packageName = packageNameField.text.trim()
// val directoryName = directoryNameField.text.trim()
//
// if (packageName.isEmpty() || directoryName.isEmpty()) {
// return
// }
//
// // Use packageName.directoryName as namespace to create correct directory structure
// val namespace = "$packageName.$directoryName"
//
// // Calculate project directory path relative to project root
// val projectBasePath = project.basePath
// val parentPath = parentDirectory.path
// val projectDirectory = if (projectBasePath != null && parentPath.startsWith(projectBasePath)) {
// // Get relative path from project root, ensuring it starts with ":"
// val relativePath = parentPath.substring(projectBasePath.length)
// .replace("/", ":")
// .let { if (it.startsWith(":")) it else ":$it" }
// relativePath
// } else {
// // Fallback if we can't determine relative path
// ":${parentDirectory.name}"
// }
//
// // Replace placeholders in templates with actual values
// val processedPublicTemplate = if (publicModuleCheckBox.isSelected) {
// publicBuildGradleArea.text
// .replace("\$directoryName", directoryName)
// .replace("\$projectDirectory", projectDirectory)
// } else null
//
// val processedImplTemplate = if (implModuleCheckBox.isSelected) {
// implBuildGradleArea.text
// .replace("\$directoryName", directoryName)
// .replace("\$projectDirectory", projectDirectory)
// } else null
//
// val processedTestingTemplate = if (testingModuleCheckBox.isSelected) {
// testingBuildGradleArea.text
// .replace("\$directoryName", directoryName)
// .replace("\$projectDirectory", projectDirectory)
// } else null
//
// val moduleCreator = ModuleCreator(
// project = project,
// parentDirectory = parentDirectory,
// namespace = namespace,
// directoryName = directoryName,
// createPublic = publicModuleCheckBox.isSelected,
// createImpl = implModuleCheckBox.isSelected,
// createTesting = testingModuleCheckBox.isSelected,
// publicBuildGradleTemplate = processedPublicTemplate,
// implBuildGradleTemplate = processedImplTemplate,
// testingBuildGradleTemplate = processedTestingTemplate
// )
//
// moduleCreator.createModules()
}

private fun updateNamespace() {
val currentState = state.value
val packageName = currentState.packageName.trim()
val directoryName = currentState.directoryName.trim()

_state.update {
it.copy(
namespace = if (packageName.isNotEmpty() && directoryName.isNotEmpty()) {
"$packageName.$directoryName"
} else packageName.ifEmpty {
""
}
)
}
}

data class State(
val packageName: String,
val directoryName: String,
val namespace: String,
val createPublic: Boolean,
val createImpl: Boolean,
val createTesting: Boolean,
val publicBuildGradle: String,
val implBuildGradle: String,
val testingBuildGradle: String
)

companion object {
private const val PACKAGE_NAME_KEY = "plusdevkit.packageName"
private const val PUBLIC_BUILD_GRADLE_KEY = "plusdevkit.publicBuildGradle"
private const val IMPL_BUILD_GRADLE_KEY = "plusdevkit.implBuildGradle"
private const val TESTING_BUILD_GRADLE_KEY = "plusdevkit.testingBuildGradle"
}
}
Loading