diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4a8e7d9..6eee0c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,6 +26,10 @@ jobs: - uses: actions/checkout@v6 with: submodules: true + - name: Make script executable + run: chmod +x ./patch_submodule.sh + - name: Run patch submodule script + run: ./patch_submodule.sh - name: set up secrets run: | echo "${{ secrets.RELEASE_KEYSTORE }}" > keystore.asc @@ -42,7 +46,7 @@ jobs: - name: set up JDK uses: actions/setup-java@v5 with: - java-version: 17 + java-version: 21 distribution: "temurin" cache: 'gradle' - name: Setup Gradle diff --git a/app/build.gradle b/app/build.gradle index 7ae1347..2f5f1fc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,27 +1,38 @@ +def getCommitCount() { + try { + def stdout = new ByteArrayOutputStream() + exec { + commandLine 'git', 'rev-list', '--count', 'HEAD' + standardOutput = stdout + } + return stdout.toString().trim().toInteger() + } catch (ignored) { + return 1 + } +} + plugins { id 'com.android.application' - id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.plugin.serialization' version '2.3.21' id 'org.jetbrains.kotlin.plugin.compose' version '2.3.21' } - android { namespace 'net.helcel.fidelity' - compileSdk 36 + compileSdk = 37 defaultConfig { applicationId 'net.helcel.fidelity' - versionName "1.0d" + versionName "1.3" + versionCode getCommitCount() buildConfigField("String", "APP_NAME", "\"Keepass Fidelity\"") manifestPlaceholders["APP_NAME"] = "Keepass Fidelity" - minSdk 28 - targetSdk 36 + minSdk = 28 + targetSdk = 37 } - signingConfigs { - create("release") { + register("release") { try { def keystorePropertiesFile = rootProject.file("app/keystore.properties") def keystoreProperties = new Properties() @@ -41,10 +52,12 @@ android { buildTypes { debug { debuggable true + initWith(buildTypes.release) + signingConfig signingConfigs.debug } release { minifyEnabled true - shrinkResources false + shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } signedRelease { @@ -86,10 +99,8 @@ android { disable 'UsingMaterialAndMaterial3Libraries' disable 'PreviewAnnotationInFunctionWithParameters' } - } - dependencies { implementation 'androidx.compose.ui:ui' implementation 'androidx.compose.material3:material3:1.4.0' diff --git a/app/src/main/java/net/helcel/fidelity/activity/fragment/CreateEntry.kt b/app/src/main/java/net/helcel/fidelity/activity/fragment/CreateEntry.kt index c04e156..a90d2c9 100644 --- a/app/src/main/java/net/helcel/fidelity/activity/fragment/CreateEntry.kt +++ b/app/src/main/java/net/helcel/fidelity/activity/fragment/CreateEntry.kt @@ -62,6 +62,7 @@ import net.helcel.fidelity.tools.FidelityEntry import net.helcel.fidelity.tools.FidelityRepository import net.helcel.fidelity.tools.FidelityRepository.activeEntry import net.helcel.fidelity.tools.FidelityRepository.addEntry +import kotlin.time.Duration.Companion.milliseconds @Preview @@ -81,7 +82,7 @@ fun CreateEntryScreen(navController: NavHostController?) { LaunchedEffect(entry) { isValidBarcode = false - delay(500) + delay(500.milliseconds) if (entry.code.isEmpty()) return@LaunchedEffect try { val bmp = generateBarcode(entry.code, entry.format, 600) @@ -158,8 +159,9 @@ fun CreateEntryScreen(navController: NavHostController?) { ), label = { Text("Code") }, isError = errorCode.isNotEmpty(), - modifier = Modifier.fillMaxWidth(), - singleLine = true + maxLines = 5, + singleLine = false, + modifier = Modifier.fillMaxWidth() ) if (errorCode.isNotEmpty()) { Text(errorCode, color = MaterialTheme.colors.error) @@ -358,7 +360,13 @@ private fun onSubmitIfValid( object CreateEntryEventHandler { fun onSubmit(navController: NavHostController){ navController.popBackStack() - activeEntry.value = activeEntry.value.copy(null,"","","",false) + activeEntry.value = activeEntry.value.copy( + uid = null, + title = "", + code = "", + format = "", + protected = false + ) } fun onFileScan(navController: NavHostController){ diff --git a/app/src/main/java/net/helcel/fidelity/activity/fragment/Launcher.kt b/app/src/main/java/net/helcel/fidelity/activity/fragment/Launcher.kt index f3f2279..87b8a51 100644 --- a/app/src/main/java/net/helcel/fidelity/activity/fragment/Launcher.kt +++ b/app/src/main/java/net/helcel/fidelity/activity/fragment/Launcher.kt @@ -1,12 +1,14 @@ package net.helcel.fidelity.activity.fragment import android.content.Context +import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.interaction.MutableInteractionSource 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.fillMaxSize @@ -24,9 +26,12 @@ import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.FloatingActionButton import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme +import androidx.compose.material.OutlinedTextField import androidx.compose.material.Text +import androidx.compose.material.TextFieldDefaults import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.HideSource import androidx.compose.material.icons.filled.PushPin @@ -36,6 +41,7 @@ import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -44,6 +50,8 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -51,6 +59,8 @@ import androidx.navigation.NavHostController import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import net.helcel.fidelity.activity.ToastHelper +import net.helcel.fidelity.activity.fragment.LauncherEventHandlers.isSearchVisible import net.helcel.fidelity.activity.fragment.LauncherEventHandlers.onAdd import net.helcel.fidelity.activity.fragment.LauncherEventHandlers.onEdit import net.helcel.fidelity.activity.fragment.LauncherEventHandlers.onHide @@ -58,6 +68,7 @@ import net.helcel.fidelity.activity.fragment.LauncherEventHandlers.onPin import net.helcel.fidelity.activity.fragment.LauncherEventHandlers.onQuery import net.helcel.fidelity.activity.fragment.LauncherEventHandlers.onRefresh import net.helcel.fidelity.activity.fragment.LauncherEventHandlers.onView +import net.helcel.fidelity.activity.fragment.LauncherEventHandlers.searchQuery import net.helcel.fidelity.tools.CredentialResult import net.helcel.fidelity.tools.FidelityEntry import net.helcel.fidelity.tools.FidelityRepository.activeEntry @@ -79,9 +90,18 @@ fun LauncherScreen( var showHidden by remember { mutableStateOf(false) } val context = LocalContext.current val scope = rememberCoroutineScope() - val sortedEntries = remember(entries) { + val focusRequester = remember { FocusRequester() } + + BackHandler(enabled = isSearchVisible) { + onQuery() + } + + val sortedEntries = remember(entries, showHidden, searchQuery) { derivedStateOf { - entries.filter{showHidden || !it.hidden}.sortedWith( + entries.filter { + (showHidden || !it.hidden) && + (searchQuery.isEmpty() || it.title.contains(searchQuery, ignoreCase = true)) + }.sortedWith( compareByDescending { it.pinned } .thenBy { it.hidden } .thenByDescending { it.lastUse } @@ -105,17 +125,47 @@ fun LauncherScreen( isRefreshing = isRefreshingState, modifier = Modifier.fillMaxSize() ) { - LazyVerticalGrid( - columns = GridCells.Fixed(2), - modifier = Modifier - .fillMaxSize() - .fillMaxSize() - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(sortedEntries.value) { entry -> - FidelityRow(navController, entry) + Column(modifier = Modifier.fillMaxSize()) { + if (isSearchVisible) { + LaunchedEffect(Unit) { + focusRequester.requestFocus() + } + OutlinedTextField( + value = searchQuery, + onValueChange = { searchQuery = it }, + colors = TextFieldDefaults.textFieldColors( + textColor = MaterialTheme.colors.onBackground + ), + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + .focusRequester(focusRequester), + label = { Text("Search") }, + singleLine = true, + trailingIcon = { + Icon( + Icons.Default.Close, + contentDescription = "Clear", + modifier = Modifier.clickable { + searchQuery = "" + onQuery() + } + ) + } + ) + } + LazyVerticalGrid( + columns = GridCells.Fixed(2), + modifier = Modifier + .fillMaxSize() + .fillMaxSize() + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(sortedEntries.value) { entry -> + FidelityRow(navController, entry) + } } } FloatingActionButton( @@ -262,21 +312,24 @@ fun FidelityRow( object LauncherEventHandlers { + var isSearchVisible by mutableStateOf(false) + var searchQuery by mutableStateOf("") + var CRED: CredentialResult.Success? = null + fun onAdd(navController: NavHostController) { navController.navigate("edit") } fun onQuery() { - //TODO + isSearchVisible = !isSearchVisible + if (!isSearchVisible) searchQuery = "" } - var CRED: CredentialResult.Success? = null suspend fun onSave(context: Context, navController: NavHostController){ try { if (CRED == null) { - val res = loadCredentials(context) - when (res) { - CredentialResult.AuthFailed, CredentialResult.NoData -> null + when (val res = loadCredentials(context)) { + CredentialResult.AuthFailed, CredentialResult.NoData -> ToastHelper.show(context, "Unable to Load Credentials") is CredentialResult.Success -> CRED = res } } @@ -297,11 +350,9 @@ object LauncherEventHandlers { suspend fun onRefresh(context: Context, navController: NavHostController) { try { if (CRED == null) { - val res = loadCredentials(context) - when (res) { - CredentialResult.AuthFailed, CredentialResult.NoData -> null + when (val res = loadCredentials(context)) { + CredentialResult.AuthFailed, CredentialResult.NoData -> ToastHelper.show(context, "Unable to Load Credentials") is CredentialResult.Success -> CRED = res - } } CRED!! @@ -309,8 +360,8 @@ object LauncherEventHandlers { genCredentials(context, CRED!!) } if (withContext(Dispatchers.IO) { - start(context, CRED!!.db, cred) - }) + start(context, CRED!!.db, cred) + }) importDB(context) } catch (e: Exception) { println(e.toString()) diff --git a/app/src/main/java/net/helcel/fidelity/activity/fragment/Setup.kt b/app/src/main/java/net/helcel/fidelity/activity/fragment/Setup.kt index b5f34c7..291e612 100644 --- a/app/src/main/java/net/helcel/fidelity/activity/fragment/Setup.kt +++ b/app/src/main/java/net/helcel/fidelity/activity/fragment/Setup.kt @@ -53,6 +53,7 @@ import net.helcel.fidelity.activity.ToastHelper import net.helcel.fidelity.activity.fragment.SetupEventHandlers.onOpen import net.helcel.fidelity.tools.CredentialResult import net.helcel.fidelity.tools.FidelityRepository.genCredentials +import net.helcel.fidelity.tools.FidelityRepository.importDB import net.helcel.fidelity.tools.FidelityRepository.start import net.helcel.fidelity.tools.KeePassStore.loadCredentials import net.helcel.fidelity.tools.KeePassStore.packCredentials @@ -116,8 +117,8 @@ fun InitialScreen( LaunchedEffect(Unit) { scope.launch(Dispatchers.Main) { when(val res = loadCredentials(context)) { - CredentialResult.AuthFailed -> null - CredentialResult.NoData -> null + CredentialResult.AuthFailed -> ToastHelper.show(context, "Unable to Load Credentials") + CredentialResult.NoData -> ToastHelper.show(context, "Unable to Load Credentials") is CredentialResult.Success -> { if (res.db != null) dbFile = res.db if (res.key != null) keyFile = res.key @@ -219,13 +220,17 @@ fun InitialScreen( onClick = { loading = true scope.launch { - if(onOpen(context, dbFile!!, password, keyFile)){ + val res = onOpen(context, dbFile!!, password, keyFile) + if(res != null){ + ToastHelper.show(context, "Successful... Importing") + withContext(Dispatchers.IO) { + start(context, dbFile!!,genCredentials(context, res)) + } + importDB(context) navController!!.popBackStack() - navController.navigate("init") + navController.navigate("launcher") }else{ - ToastHelper.show(context, "Auth failed...") - navController!!.popBackStack() - navController.navigate("exit") + ToastHelper.show(context, "Failed... Retry") } } }, @@ -249,7 +254,7 @@ fun InitialScreen( } object SetupEventHandlers { - suspend fun onOpen(context: Context, db: Uri, p: String, key: Uri?): Boolean { + suspend fun onOpen(context: Context, db: Uri, p: String, key: Uri?): CredentialResult.Success? { try { val packCred = packCredentials(db, p, key) withContext(Dispatchers.IO) { @@ -261,14 +266,14 @@ object SetupEventHandlers { saveCredentials(context, packCred) } return when (res) { - CredentialResult.AuthFailed, CredentialResult.NoData -> false - is CredentialResult.Success -> true + CredentialResult.AuthFailed, CredentialResult.NoData -> null + is CredentialResult.Success -> res } } catch (e: Exception) { ToastHelper.show(context, e.message.toString()) println("Err${e.toString()}") println(e.message) - return false + return null } } } \ No newline at end of file diff --git a/app/src/main/java/net/helcel/fidelity/tools/BarcodeScanner.kt b/app/src/main/java/net/helcel/fidelity/tools/BarcodeScanner.kt index c186dec..bb64e4a 100644 --- a/app/src/main/java/net/helcel/fidelity/tools/BarcodeScanner.kt +++ b/app/src/main/java/net/helcel/fidelity/tools/BarcodeScanner.kt @@ -13,7 +13,6 @@ import com.google.zxing.common.HybridBinarizer import net.helcel.fidelity.tools.BarcodeFormatConverter.formatToString import java.util.concurrent.Executors - @OptIn(ExperimentalGetImage::class) object BarcodeScanner { @@ -56,6 +55,4 @@ object BarcodeScanner { fun bitmapUseCase(bitmap: Bitmap, cb: (String?, String?) -> Unit) { processImage(bitmap, cb) } - - } \ No newline at end of file diff --git a/app/src/main/java/net/helcel/fidelity/tools/BiometricStore.kt b/app/src/main/java/net/helcel/fidelity/tools/BiometricStore.kt index 2f59d91..a22f98c 100644 --- a/app/src/main/java/net/helcel/fidelity/tools/BiometricStore.kt +++ b/app/src/main/java/net/helcel/fidelity/tools/BiometricStore.kt @@ -113,13 +113,21 @@ suspend fun showBiometricPrompt(activity: FragmentActivity, enc: Boolean): Ciphe activity, executor, object : BiometricPrompt.AuthenticationCallback() { - override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { cont.resume(result.cryptoObject?.cipher) {} } - override fun onAuthenticationError(code: Int, msg: CharSequence) { cont.resume(null) {} } - override fun onAuthenticationFailed() { cont.resume(null) {} } + override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { + cont.resume(result.cryptoObject?.cipher) { _, _, _ -> } + } + override fun onAuthenticationError(code: Int, msg: CharSequence) { + cont.resume(null) { _, _, _ -> } + } + override fun onAuthenticationFailed() { + cont.resume(null) { _, _, _ -> } + } } ) val iv = if(enc) null else prefs[KeePassKeys.IV]?.let { Base64.decode(it, Base64.DEFAULT) } - if (!enc && iv == null) { cont.resume(null) {} } + if (!enc && iv == null) { + cont.resume(null) { _, _, _ -> } + } val cipher = getCipherForDecryption(getOrCreateBiometricKey(), iv) val promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Unlock KeePass") diff --git a/app/src/main/java/net/helcel/fidelity/tools/Keepass.kt b/app/src/main/java/net/helcel/fidelity/tools/Keepass.kt index d2ecd90..410aff4 100644 --- a/app/src/main/java/net/helcel/fidelity/tools/Keepass.kt +++ b/app/src/main/java/net/helcel/fidelity/tools/Keepass.kt @@ -59,7 +59,7 @@ object FidelityRepository { db.loadData( bitStream, c, { hardwareKey, seed -> retrieveResponseFromChallenge(hardwareKey, seed) }, - false, binaryDir!!, + readOnly=false, allowUserVerification = false,binaryDir!!, { BinaryData.canMemoryBeAllocatedInRAM(ctx, it) }, false, null ) @@ -84,7 +84,7 @@ object FidelityRepository { hardwareKey: HardwareKey? = null ): MasterCredential { return MasterCredential( - cred.password, + cred.password.toCharArray(), cred.key?.let { ctx.contentResolver.openInputStream(cred.key)?.readBytes() }, hardwareKey ) @@ -103,8 +103,8 @@ object FidelityRepository { val newEntry = FidelityEntry( uid=it.nodeId.id.toString(), title=it.title, - code=code.protectedValue.stringValue, - format=format.protectedValue.stringValue, + code=code.protectedValue.toString(), + format=format.protectedValue.toString(), protected=code.protectedValue.isProtected, ) val idx = entries.indexOfFirst { e -> e.uid == newEntry.uid } @@ -172,7 +172,7 @@ object FidelityRepository { putExtraField( Field( FidelityKeepassFields.FIDELITYFORMAT, - ProtectedString(string= entry.format) + ProtectedString(true, entry.format.toCharArray()) ) ) if(dbParent!=null) title = entry.title diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi/ic_launcher.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to app/src/main/res/mipmap-anydpi/ic_launcher.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml similarity index 79% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to app/src/main/res/mipmap-anydpi/ic_launcher_round.xml index 7353dbd..ef49c99 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml @@ -2,4 +2,5 @@ + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 42c7193..e7ce9c0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,9 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { -// ext.kotlin_version = '1.8.20' -// ext.android_core_version = '1.10.1' -// ext.android_appcompat_version = '1.6.1' -// ext.android_material_version = '1.9.0' - ext.android_test_version = '1.5.2' + ext.joda_time_version = '2.14.1' + ext.commons_io_version = '2.21.0' + ext.android_test_version = '1.7.0' } plugins { diff --git a/external/KeePassDX b/external/KeePassDX index 1b98bd7..581df55 160000 --- a/external/KeePassDX +++ b/external/KeePassDX @@ -1 +1 @@ -Subproject commit 1b98bd740cda9d0c6f4942e4901f1c943e391c5f +Subproject commit 581df551ea3ad70562c6d72a3fb49780d03da6a8 diff --git a/gradle.properties b/gradle.properties index d7d6ba3..3f51bcc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,4 +21,8 @@ kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +android.onlyEnableUnitTestForTheTestedBuildType=false +android.uniquePackageNames=false +android.r8.strictFullModeForKeepRules=false +android.dependency.useConstraints=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8bdaf60..b1b8ef5 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5dd3c01..df6a6ad 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,6 +2,8 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index adff685..b9bb139 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/gradlew.bat b/gradlew.bat index e509b2d..aa5f10b 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -23,8 +23,8 @@ @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,7 +65,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line @@ -73,21 +73,10 @@ goto fail @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/patch_submodule.sh b/patch_submodule.sh new file mode 100755 index 0000000..f8bcb83 --- /dev/null +++ b/patch_submodule.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +for file in external/KeePassDX/{crypto,database}/build.gradle; do + if [ -f "$file" ]; then + sed -i "/id 'kotlin-android'/d" "$file" + sed -i "/apply plugin: 'kotlin-android'/d" "$file" + sed -i '/kotlinOptions {/,/}/d' "$file" + fi +done