diff --git a/build.gradle.kts b/build.gradle.kts index 960f3ef..ca280dc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,12 +2,18 @@ import org.gradle.jvm.tasks.Jar import org.jetbrains.compose.compose import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +buildscript { + dependencies { + classpath("com.guardsquare:proguard-gradle:7.2.1") + } +} + plugins { // Kotlin version must match compose version - kotlin("jvm") version "1.7.0" - kotlin("kapt") version "1.7.0" - kotlin("plugin.serialization") version "1.7.0" - id("org.jetbrains.compose") version "1.2.0-alpha01-dev755" + kotlin("jvm") version "1.7.10" + kotlin("kapt") version "1.7.10" + kotlin("plugin.serialization") version "1.7.10" + id("org.jetbrains.compose") version "1.2.0-alpha01-dev774" } // Remember to update Constants.APP_VERSION when changing this version @@ -39,6 +45,7 @@ dependencies { implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-scalars:2.9.0") implementation("net.i2p.crypto:eddsa:0.3.0") + } tasks.test { @@ -81,6 +88,7 @@ compose.desktop { task("fatJarLinux", type = Jar::class) { + archiveBaseName.set("$projectName-linux") duplicatesStrategy = DuplicatesStrategy.EXCLUDE @@ -100,3 +108,58 @@ task("fatJarLinux", type = Jar::class) { } with(tasks.jar.get() as CopySpec) } + +val obfuscate by tasks.registering(proguard.gradle.ProGuardTask::class) + +val fatJarProvider = tasks.register("fatJar", Jar::class) { + this.dependsOn(configurations.named("runtimeClasspath")) + this.dependsOn(tasks.named("jar")) + + this.classifier = "fat" + + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + this.manifest { + attributes["Implementation-Title"] = name + attributes["Implementation-Version"] = projectVersion + attributes["Main-Class"] = "com.jetpackduba.gitnuro.MainKt" + } + + val sourceClasses = sourceSets.main.get().output.classesDirs + this.inputs.files(sourceClasses) + + this.doFirst { + from(files(sourceClasses)) + from(configurations.runtimeClasspath.asFileTree.files.map { zipTree(it) }) + exclude("**/*.kotlin_metadata") + exclude("**/*.kotlin_module") + exclude("**/*.kotlin_builtins") + exclude("**/module-info.class") + exclude("META-INF/maven/**") + } +} +fun mapObfuscatedJarFile(file: File) = + File("${project.buildDir}/tmp/obfuscated/${file.nameWithoutExtension}.min.jar") + +obfuscate.configure { + dependsOn(tasks.jar.get()) + + val allJars = tasks.jar.get().outputs.files + sourceSets.main.get().runtimeClasspath.filter { it.path.endsWith(".jar") } + .filterNot { it.name.startsWith("skiko-awt-") && !it.name.startsWith("skiko-awt-runtime-") } // walkaround https://github.com/JetBrains/compose-jb/issues/1971 + + for (file in allJars) { + injars(file) + outjars(mapObfuscatedJarFile(file)) + } + + libraryjars("${compose.desktop.application.javaHome ?: System.getProperty("java.home")}/jmods") + + configuration("proguard-rules.pro") +} + +task("r8Jar", type = JavaExec::class) { + val r8File = File("$buildDir/libs/gitnuro-linux-proguard.jar") + val rules = file("proguard-rules.pro") + this.dependsOn(configurations.named("runtimeClasspath")) + this.inputs.files(fatJarProvider.get().outputs.files, rules) + this.outputs.file(r8File) +} diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/extensions/ModifierExtensions.kt b/src/main/kotlin/com/jetpackduba/gitnuro/extensions/ModifierExtensions.kt index 4cd6873..c0bec1f 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/extensions/ModifierExtensions.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/extensions/ModifierExtensions.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.clickable import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.pointer.PointerIconDefaults import androidx.compose.ui.input.pointer.pointerHoverIcon @@ -21,4 +22,12 @@ fun Modifier.handMouseClickable(onClick: () -> Unit): Modifier { return this .clickable { onClick() } .pointerHoverIcon(PointerIconDefaults.Hand) +} + +/** + * Ignore keyboard events of that components. + * Specially useful for clickable components that may get focused and become clickable when pressing ENTER. + */ +fun Modifier.ignoreKeyEvents(): Modifier { + return this.onPreviewKeyEvent { true } } \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/git/FileChangesWatcher.kt b/src/main/kotlin/com/jetpackduba/gitnuro/git/FileChangesWatcher.kt index 78e9c78..3648bad 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/git/FileChangesWatcher.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/git/FileChangesWatcher.kt @@ -35,7 +35,7 @@ class FileChangesWatcher @Inject constructor() { ENTRY_MODIFY ) - // register directory and sub-directories but ignore dirs by gitignore + // register directory and subdirectories but ignore dirs by gitignore Files.walkFileTree(path, object : SimpleFileVisitor() { @Throws(IOException::class) override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult { diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/Menu.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/Menu.kt index 975fda3..7493bae 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/Menu.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/Menu.kt @@ -21,6 +21,7 @@ import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import com.jetpackduba.gitnuro.extensions.handMouseClickable +import com.jetpackduba.gitnuro.extensions.ignoreKeyEvents import com.jetpackduba.gitnuro.theme.primaryTextColor import com.jetpackduba.gitnuro.ui.context_menu.* import com.jetpackduba.gitnuro.viewmodels.MenuViewModel @@ -161,6 +162,7 @@ fun MenuButton( modifier = modifier .handMouseClickable { if (enabled) onClick() } .border(ButtonDefaults.outlinedBorder, RoundedCornerShape(4.dp)) + .ignoreKeyEvents() .padding(vertical = 8.dp, horizontal = 16.dp), ) { Row( @@ -203,6 +205,7 @@ fun ExtendedMenuButton( Row(modifier = modifier.height(IntrinsicSize.Min)) { Row( modifier = Modifier + .ignoreKeyEvents() .handMouseClickable { if (enabled) onClick() } .border(ButtonDefaults.outlinedBorder, RoundedCornerShape(topStart = 4.dp, bottomStart = 4.dp)) .padding(vertical = 8.dp, horizontal = 16.dp), @@ -227,6 +230,7 @@ fun ExtendedMenuButton( modifier = Modifier .width(20.dp) .fillMaxHeight() + .ignoreKeyEvents() .border(ButtonDefaults.outlinedBorder, RoundedCornerShape(topEnd = 4.dp, bottomEnd = 4.dp)) .handMouseClickable { showDropDownMenu = true