diff options
Diffstat (limited to 'app/src/main/java/dev/msfjarvis/aps/util/extensions')
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) } |
