diff options
Diffstat (limited to 'app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt')
| -rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt | 151 |
1 files changed, 25 insertions, 126 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt index 2a11f56a..10a29cf0 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt +++ b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt @@ -4,74 +4,33 @@ */ package com.zeapo.pwdstore.utils -import android.app.KeyguardManager -import android.content.ClipboardManager -import android.content.Context -import android.content.SharedPreferences -import android.content.pm.PackageManager -import android.os.Build -import android.util.Base64 -import android.util.TypedValue -import android.view.View -import android.view.autofill.AutofillManager -import android.view.inputmethod.InputMethodManager -import androidx.annotation.IdRes -import androidx.annotation.RequiresApi -import androidx.appcompat.app.AlertDialog -import androidx.core.content.ContextCompat -import androidx.core.content.getSystemService -import androidx.fragment.app.FragmentActivity -import androidx.preference.PreferenceManager -import androidx.security.crypto.EncryptedSharedPreferences -import androidx.security.crypto.MasterKey -import com.github.ajalt.timberkt.d -import com.github.michaelbull.result.Ok -import com.github.michaelbull.result.Result import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.runCatching -import com.google.android.material.snackbar.Snackbar -import com.zeapo.pwdstore.R -import com.zeapo.pwdstore.git.operation.GitOperation import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory import java.io.File import java.util.Date import org.eclipse.jgit.lib.ObjectId import org.eclipse.jgit.revwalk.RevCommit +/** + * The default OpenPGP provider for the app + */ const val OPENPGP_PROVIDER = "org.sufficientlysecure.keychain" +/** + * Clears the given [flag] from the value of this [Int] + */ fun Int.clearFlag(flag: Int): Int { return this and flag.inv() } +/** + * Checks if this [Int] contains the given [flag] + */ infix fun Int.hasFlag(flag: Int): Boolean { return this and flag == flag } -fun String.splitLines(): Array<String> { - return split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() -} - -fun String.base64(): String { - return Base64.encodeToString(encodeToByteArray(), Base64.NO_WRAP) -} - -val Context.clipboard - get() = getSystemService<ClipboardManager>() - -fun FragmentActivity.snackbar( - view: View = findViewById(android.R.id.content), - message: String, - length: Int = Snackbar.LENGTH_SHORT, -): Snackbar { - val snackbar = Snackbar.make(view, message, length) - snackbar.anchorView = findViewById(R.id.fab) - snackbar.show() - return snackbar -} - -fun File.listFilesRecursively() = walkTopDown().filter { !it.isDirectory }.toList() - /** * Checks whether this [File] is a directory that contains [other]. */ @@ -89,91 +48,23 @@ fun File.contains(other: File): Boolean { return relativePath.path == other.name } -fun Context.resolveAttribute(attr: Int): Int { - val typedValue = TypedValue() - this.theme.resolveAttribute(attr, typedValue, true) - return typedValue.data -} - -fun Context.getEncryptedPrefs(fileName: String): SharedPreferences { - val masterKeyAlias = MasterKey.Builder(applicationContext) - .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) - .build() - return EncryptedSharedPreferences.create( - applicationContext, - fileName, - masterKeyAlias, - EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM - ) -} - -val Context.sharedPrefs: SharedPreferences - get() = PreferenceManager.getDefaultSharedPreferences(applicationContext) - -fun SharedPreferences.getString(key: String): String? = getString(key, null) - -suspend fun FragmentActivity.commitChange( - message: String, -): Result<Unit, Throwable> { - if (!PasswordRepository.isGitRepo()) { - return Ok(Unit) - } - return object : GitOperation(this@commitChange) { - override val commands = arrayOf( - // Stage all files - git.add().addFilepattern("."), - // Populate the changed files count - git.status(), - // Commit everything! If anything changed, that is. - git.commit().setAll(true).setMessage(message), - ) - - override fun preExecute(): Boolean { - d { "Committing with message: '$message'" } - return true - } - }.execute() -} - -fun FragmentActivity.isPermissionGranted(permission: String): Boolean { - return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED -} - /** - * Extension function for [AlertDialog] that requests focus for the - * view whose id is [id]. Solution based on a StackOverflow - * answer: https://stackoverflow.com/a/13056259/297261 + * Checks if this [File] is in the password repository directory as given + * by [getRepositoryDirectory] */ -fun <T : View> AlertDialog.requestInputFocusOnView(@IdRes id: Int) { - setOnShowListener { - findViewById<T>(id)?.apply { - setOnFocusChangeListener { v, _ -> - v.post { - context.getSystemService<InputMethodManager>() - ?.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT) - } - } - requestFocus() - } - } -} - -val Context.autofillManager: AutofillManager? - @RequiresApi(Build.VERSION_CODES.O) - get() = getSystemService() - -val Context.keyguardManager: KeyguardManager - get() = getSystemService()!! - fun File.isInsideRepository(): Boolean { return canonicalPath.contains(getRepositoryDirectory().canonicalPath) } /** + * Recursively lists the files in this [File], skipping any directories it encounters. + */ +fun File.listFilesRecursively() = walkTopDown().filter { !it.isDirectory }.toList() + +/** * Unique SHA-1 hash of this commit as hexadecimal string. * - * @see RevCommit.id + * @see RevCommit.getId */ val RevCommit.hash: String get() = ObjectId.toString(id) @@ -189,3 +80,11 @@ val RevCommit.time: Date val epochMilliseconds = epochSeconds * 1000 return Date(epochMilliseconds) } + +/** + * Splits this [String] into an [Array] of [String]s, split on the UNIX LF line ending + * and stripped of any empty lines. + */ +fun String.splitLines(): Array<String> { + return split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() +} |
