aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/dev/msfjarvis/aps/util/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/dev/msfjarvis/aps/util/extensions')
-rw-r--r--app/src/main/java/dev/msfjarvis/aps/util/extensions/AndroidExtensions.kt133
-rw-r--r--app/src/main/java/dev/msfjarvis/aps/util/extensions/Extensions.kt98
-rw-r--r--app/src/main/java/dev/msfjarvis/aps/util/extensions/FragmentExtensions.kt41
-rw-r--r--app/src/main/java/dev/msfjarvis/aps/util/extensions/FragmentViewBindingDelegate.kt70
4 files changed, 0 insertions, 342 deletions
diff --git a/app/src/main/java/dev/msfjarvis/aps/util/extensions/AndroidExtensions.kt b/app/src/main/java/dev/msfjarvis/aps/util/extensions/AndroidExtensions.kt
deleted file mode 100644
index cc243a09..00000000
--- a/app/src/main/java/dev/msfjarvis/aps/util/extensions/AndroidExtensions.kt
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package dev.msfjarvis.aps.util.extensions
-
-import android.app.KeyguardManager
-import android.content.ClipboardManager
-import android.content.Context
-import android.content.Intent
-import android.content.SharedPreferences
-import android.content.pm.PackageManager
-import android.util.Base64
-import android.util.TypedValue
-import android.view.View
-import android.view.autofill.AutofillManager
-import androidx.annotation.RequiresApi
-import androidx.core.content.ContextCompat
-import androidx.core.content.getSystemService
-import androidx.fragment.app.FragmentActivity
-import androidx.security.crypto.EncryptedSharedPreferences
-import androidx.security.crypto.MasterKey
-import com.github.michaelbull.result.Ok
-import com.github.michaelbull.result.Result
-import com.google.android.material.snackbar.Snackbar
-import dev.msfjarvis.aps.BuildConfig
-import dev.msfjarvis.aps.R
-import dev.msfjarvis.aps.data.repo.PasswordRepository
-import dev.msfjarvis.aps.util.git.operation.GitOperation
-import logcat.logcat
-
-/** Get an instance of [AutofillManager]. Only available on Android Oreo and above */
-val Context.autofillManager: AutofillManager?
- @RequiresApi(26) get() = getSystemService()
-
-/** Get an instance of [ClipboardManager] */
-val Context.clipboard
- get() = getSystemService<ClipboardManager>()
-
-/** Wrapper for [getEncryptedPrefs] to avoid open-coding the file name at each call site */
-fun Context.getEncryptedGitPrefs() = getEncryptedPrefs("git_operation")
-
-/** Get an instance of [EncryptedSharedPreferences] with the given [fileName] */
-private 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
- )
-}
-
-/** Get an instance of [KeyguardManager] */
-val Context.keyguardManager: KeyguardManager
- get() = getSystemService()!!
-
-/** Get the default [SharedPreferences] instance */
-val Context.sharedPrefs: SharedPreferences
- get() = getSharedPreferences("${BuildConfig.APPLICATION_ID}_preferences", 0)
-
-/** Resolve [attr] from the [Context]'s theme */
-fun Context.resolveAttribute(attr: Int): Int {
- val typedValue = TypedValue()
- this.theme.resolveAttribute(attr, typedValue, true)
- return typedValue.data
-}
-
-/**
- * Commit changes to the store from a [FragmentActivity] using a custom implementation of
- * [GitOperation]
- */
-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 {
- logcat { "Committing with message: '$message'" }
- return true
- }
- }
- .execute()
-}
-
-/** Check if [permission] has been granted to the app. */
-fun FragmentActivity.isPermissionGranted(permission: String): Boolean {
- return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
-}
-
-/**
- * Show a [Snackbar] in a [FragmentActivity] and correctly anchor it to a
- * [com.google.android.material.floatingactionbutton.FloatingActionButton] if one exists in the
- * [view]
- */
-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
-}
-
-/** Launch an activity denoted by [clazz]. */
-fun <T : FragmentActivity> FragmentActivity.launchActivity(clazz: Class<T>) {
- startActivity(Intent(this, clazz))
-}
-
-/** Simplifies the common `getString(key, null) ?: defaultValue` case slightly */
-fun SharedPreferences.getString(key: String): String? = getString(key, null)
-
-/** Convert this [String] to its [Base64] representation */
-fun String.base64(): String {
- return Base64.encodeToString(encodeToByteArray(), Base64.NO_WRAP)
-}
diff --git a/app/src/main/java/dev/msfjarvis/aps/util/extensions/Extensions.kt b/app/src/main/java/dev/msfjarvis/aps/util/extensions/Extensions.kt
deleted file mode 100644
index 8530a216..00000000
--- a/app/src/main/java/dev/msfjarvis/aps/util/extensions/Extensions.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-package dev.msfjarvis.aps.util.extensions
-
-import com.github.michaelbull.result.Err
-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 dev.msfjarvis.aps.data.repo.PasswordRepository
-import java.io.File
-import java.util.Date
-import logcat.asLog
-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
-}
-
-/** Checks whether this [File] is a directory that contains [other]. */
-fun File.contains(other: File): Boolean {
- if (!isDirectory) return false
- if (!other.exists()) return false
- val relativePath =
- runCatching { other.relativeTo(this) }
- .getOrElse {
- return false
- }
- // Direct containment is equivalent to the relative path being equal to the filename.
- return relativePath.path == other.name
-}
-
-/**
- * Checks if this [File] is in the password repository directory as given by
- * [PasswordRepository.getRepositoryDirectory]
- */
-fun File.isInsideRepository(): Boolean {
- return canonicalPath.contains(PasswordRepository.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.getId
- */
-val RevCommit.hash: String
- get() = ObjectId.toString(id)
-
-/**
- * Time this commit was made with second precision.
- *
- * @see RevCommit.commitTime
- */
-val RevCommit.time: Date
- get() {
- val epochSeconds = commitTime.toLong()
- 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()
-}
-
-/** Alias to [lazy] with thread safety mode always set to [LazyThreadSafetyMode.NONE]. */
-fun <T> unsafeLazy(initializer: () -> T) = lazy(LazyThreadSafetyMode.NONE) { initializer.invoke() }
-
-/** A convenience extension to turn a [Throwable] with a message into a loggable string. */
-fun Throwable.asLog(message: String): String = "$message\n${asLog()}"
-
-/** Extension on [Result] that returns if the type is [Ok] */
-fun <V, E> Result<V, E>.isOk(): Boolean {
- return this is Ok<V>
-}
-
-/** Extension on [Result] that returns if the type is [Err] */
-fun <V, E> Result<V, E>.isErr(): Boolean {
- return this is Err<E>
-}
diff --git a/app/src/main/java/dev/msfjarvis/aps/util/extensions/FragmentExtensions.kt b/app/src/main/java/dev/msfjarvis/aps/util/extensions/FragmentExtensions.kt
deleted file mode 100644
index 3a256ee7..00000000
--- a/app/src/main/java/dev/msfjarvis/aps/util/extensions/FragmentExtensions.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package dev.msfjarvis.aps.util.extensions
-
-import androidx.annotation.IdRes
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentManager
-import androidx.fragment.app.commit
-import dev.msfjarvis.aps.R
-
-/** Check if [permission] is granted to the app. Aliases to [isPermissionGranted] internally. */
-fun Fragment.isPermissionGranted(permission: String): Boolean {
- return requireActivity().isPermissionGranted(permission)
-}
-
-/** Calls `finish()` on the enclosing [androidx.fragment.app.FragmentActivity] */
-fun Fragment.finish() = requireActivity().finish()
-
-/**
- * Perform a [commit] on this [FragmentManager] with custom animations and adding the
- * [destinationFragment] to the fragment backstack
- */
-fun FragmentManager.performTransactionWithBackStack(
- destinationFragment: Fragment,
- @IdRes containerViewId: Int = android.R.id.content
-) {
- commit {
- beginTransaction()
- addToBackStack(destinationFragment.tag)
- setCustomAnimations(
- R.animator.slide_in_left,
- R.animator.slide_out_left,
- R.animator.slide_in_right,
- R.animator.slide_out_right
- )
- replace(containerViewId, destinationFragment)
- }
-}
diff --git a/app/src/main/java/dev/msfjarvis/aps/util/extensions/FragmentViewBindingDelegate.kt b/app/src/main/java/dev/msfjarvis/aps/util/extensions/FragmentViewBindingDelegate.kt
deleted file mode 100644
index fe885c86..00000000
--- a/app/src/main/java/dev/msfjarvis/aps/util/extensions/FragmentViewBindingDelegate.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package dev.msfjarvis.aps.util.extensions
-
-import android.view.LayoutInflater
-import android.view.View
-import androidx.appcompat.app.AppCompatActivity
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.DefaultLifecycleObserver
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleOwner
-import androidx.viewbinding.ViewBinding
-import kotlin.properties.ReadOnlyProperty
-import kotlin.reflect.KProperty
-
-/**
- * Imported from
- * https://medium.com/@Zhuinden/simple-one-liner-viewbinding-in-fragments-and-activities-with-kotlin-961430c6c07c
- */
-class FragmentViewBindingDelegate<T : ViewBinding>(
- val fragment: Fragment,
- val viewBindingFactory: (View) -> T
-) : ReadOnlyProperty<Fragment, T> {
-
- private var binding: T? = null
-
- init {
- fragment.lifecycle.addObserver(
- object : DefaultLifecycleObserver {
- override fun onCreate(owner: LifecycleOwner) {
- fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner ->
- viewLifecycleOwner.lifecycle.addObserver(
- object : DefaultLifecycleObserver {
- override fun onDestroy(owner: LifecycleOwner) {
- binding = null
- }
- }
- )
- }
- }
- }
- )
- }
-
- override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
- val binding = binding
- if (binding != null) {
- return binding
- }
-
- val lifecycle = fragment.viewLifecycleOwner.lifecycle
- if (!lifecycle.currentState.isAtLeast(Lifecycle.State.INITIALIZED)) {
- throw IllegalStateException(
- "Should not attempt to get bindings when Fragment views are destroyed."
- )
- }
-
- return viewBindingFactory(thisRef.requireView()).also { this.binding = it }
- }
-}
-
-fun <T : ViewBinding> Fragment.viewBinding(viewBindingFactory: (View) -> T) =
- FragmentViewBindingDelegate(this, viewBindingFactory)
-
-inline fun <T : ViewBinding> AppCompatActivity.viewBinding(
- crossinline bindingInflater: (LayoutInflater) -> T
-) = unsafeLazy { bindingInflater.invoke(layoutInflater) }