mirror of
https://github.com/yogeshpaliyal/KeyPass.git
synced 2026-01-04 01:29:39 -06:00
code formatter added
This commit is contained in:
@@ -3,6 +3,7 @@ plugins {
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-kapt'
|
||||
id 'androidx.navigation.safeargs.kotlin'
|
||||
// id("com.diffplug.spotless") version "5.10.2"
|
||||
|
||||
}
|
||||
|
||||
|
||||
BIN
app/production/release/app-production-release.apk
Normal file
BIN
app/production/release/app-production-release.apk
Normal file
Binary file not shown.
18
app/production/release/output-metadata.json
Normal file
18
app/production/release/output-metadata.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 2,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "com.yogeshpaliyal.keypass",
|
||||
"variantName": "processProductionReleaseResources",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"versionCode": 3,
|
||||
"versionName": "1.3",
|
||||
"outputFile": "app-production-release.apk"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
package com.yogeshpaliyal.keypass
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
@@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.yogeshpaliyal.keypass", appContext.packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,10 @@ package com.yogeshpaliyal.keypass
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.yogeshpaliyal.keypass.data.AccountModel
|
||||
import com.yogeshpaliyal.keypass.db.DbDao
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -31,10 +29,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
fun getInstance(): AppDatabase {
|
||||
if (!this::_instance.isInitialized)
|
||||
|
||||
|
||||
synchronized(this) {
|
||||
|
||||
|
||||
_instance = Room.databaseBuilder(
|
||||
MyApplication.instance,
|
||||
AppDatabase::class.java,
|
||||
@@ -48,7 +44,6 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
super.onDestructiveMigration(db)
|
||||
onCreate(db)
|
||||
}
|
||||
|
||||
})
|
||||
/* .addMigrations(object : Migration(3, 4) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
@@ -64,10 +59,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
return _instance
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package com.yogeshpaliyal.keypass
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
* https://techpaliyal.com
|
||||
* created on 23-01-2021 10:33
|
||||
*/
|
||||
data class InfoModel(var user_id: String,
|
||||
var username : String,
|
||||
var password : String,
|
||||
var notes: String,
|
||||
var insertedDate : Long,
|
||||
var lastUpdatedDate : Long)
|
||||
data class InfoModel(
|
||||
var user_id: String,
|
||||
var username: String,
|
||||
var password: String,
|
||||
var notes: String,
|
||||
var insertedDate: Long,
|
||||
var lastUpdatedDate: Long
|
||||
)
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.yogeshpaliyal.keypass
|
||||
|
||||
import android.app.Application
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -11,14 +10,12 @@ import android.app.Application
|
||||
*/
|
||||
class MyApplication : Application() {
|
||||
|
||||
companion object{
|
||||
companion object {
|
||||
lateinit var instance: MyApplication
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
instance = this
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,4 +44,4 @@ class MaskedCardView @JvmOverloads constructor(
|
||||
pathProvider.calculatePath(shapeAppearance, 1f, rectF, path)
|
||||
super.onSizeChanged(w, h, oldw, oldh)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.yogeshpaliyal.universal_adapter.model.BaseDiffUtil
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -31,7 +30,7 @@ class AccountModel(
|
||||
var tags: String? = null
|
||||
) : BaseDiffUtil {
|
||||
|
||||
fun getInitials() = (title?.firstOrNull() ?: username?.firstOrNull() ?: site?.firstOrNull() ?: notes?.firstOrNull() ?: 'K').toString()
|
||||
fun getInitials() = (title?.firstOrNull() ?: username?.firstOrNull() ?: site?.firstOrNull() ?: notes?.firstOrNull() ?: 'K').toString()
|
||||
|
||||
override fun getDiffId(): Any? {
|
||||
return id
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.yogeshpaliyal.keypass.data
|
||||
import com.google.gson.annotations.Expose
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -13,8 +12,8 @@ import com.google.gson.annotations.SerializedName
|
||||
data class BackupData(
|
||||
@SerializedName("version")
|
||||
@Expose
|
||||
val version : Int,
|
||||
val version: Int,
|
||||
@SerializedName("data")
|
||||
@Expose
|
||||
val data : List<AccountModel> ) {
|
||||
}
|
||||
val data: List<AccountModel>
|
||||
)
|
||||
|
||||
@@ -7,7 +7,6 @@ import androidx.room.Query
|
||||
import com.yogeshpaliyal.keypass.data.AccountModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -24,21 +23,18 @@ abstract class DbDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
abstract fun insertOrUpdateAccount(accountModel: List<AccountModel>)
|
||||
|
||||
|
||||
@Query("SELECT * from account")
|
||||
abstract fun getAllAccounts() : Flow<List<AccountModel>>
|
||||
abstract fun getAllAccounts(): Flow<List<AccountModel>>
|
||||
|
||||
@Query("SELECT * from account where tags = :tag")
|
||||
abstract fun getAllAccounts(tag: String) : Flow<List<AccountModel>>
|
||||
abstract fun getAllAccounts(tag: String): Flow<List<AccountModel>>
|
||||
|
||||
@Query("SELECT * from account where id = :id")
|
||||
abstract fun getAccount(id: Long?) : AccountModel?
|
||||
abstract fun getAccount(id: Long?): AccountModel?
|
||||
|
||||
@Query("SELECT DISTINCT tags from account")
|
||||
abstract fun getTags() : Flow<List<String>>
|
||||
abstract fun getTags(): Flow<List<String>>
|
||||
|
||||
@Query("DELETE from account where id = :id")
|
||||
abstract fun deleteAccount(id: Long?)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.yogeshpaliyal.keypass.db_helper
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
|
||||
@@ -2,23 +2,13 @@ package com.yogeshpaliyal.keypass.db_helper
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
import android.security.keystore.KeyGenParameterSpec
|
||||
import android.security.keystore.KeyProperties
|
||||
import androidx.room.withTransaction
|
||||
import com.google.gson.Gson
|
||||
import com.yogeshpaliyal.keypass.AppDatabase
|
||||
import com.yogeshpaliyal.keypass.data.AccountModel
|
||||
import com.yogeshpaliyal.keypass.data.BackupData
|
||||
import com.yogeshpaliyal.keypass.utils.getOrCreateBackupKey
|
||||
import com.yogeshpaliyal.keypass.utils.logD
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.io.OutputStream
|
||||
import javax.crypto.KeyGenerator
|
||||
import javax.crypto.SecretKey
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
@@ -27,24 +17,23 @@ import javax.crypto.SecretKey
|
||||
* created on 20-02-2021 19:31
|
||||
*/
|
||||
|
||||
suspend fun AppDatabase.createBackup(key: String,contentResolver : ContentResolver,fileUri: Uri?) = withContext(Dispatchers.IO){
|
||||
fileUri ?: return@withContext false
|
||||
suspend fun AppDatabase.createBackup(key: String, contentResolver: ContentResolver, fileUri: Uri?) = withContext(Dispatchers.IO) {
|
||||
fileUri ?: return@withContext false
|
||||
val data = getDao().getAllAccounts().first()
|
||||
|
||||
val json = Gson().toJson(BackupData(this@createBackup.openHelper.readableDatabase.version, data))
|
||||
val fileStream = contentResolver.openOutputStream(fileUri)
|
||||
EncryptionHelper.doCryptoEncrypt(key,json, fileStream)
|
||||
EncryptionHelper.doCryptoEncrypt(key, json, fileStream)
|
||||
|
||||
return@withContext true
|
||||
}
|
||||
|
||||
|
||||
suspend fun AppDatabase.restoreBackup(key: String,contentResolver : ContentResolver,fileUri: Uri?) = withContext(Dispatchers.IO){
|
||||
suspend fun AppDatabase.restoreBackup(key: String, contentResolver: ContentResolver, fileUri: Uri?) = withContext(Dispatchers.IO) {
|
||||
fileUri ?: return@withContext false
|
||||
|
||||
val restoredFile = try {
|
||||
EncryptionHelper.doCryptoDecrypt(key, contentResolver.openInputStream(fileUri))
|
||||
}catch (e:Exception){
|
||||
val restoredFile = try {
|
||||
EncryptionHelper.doCryptoDecrypt(key, contentResolver.openInputStream(fileUri))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return@withContext false
|
||||
}
|
||||
@@ -57,4 +46,3 @@ suspend fun AppDatabase.restoreBackup(key: String,contentResolver : ContentResol
|
||||
}
|
||||
return@withContext true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.yogeshpaliyal.keypass.db_helper
|
||||
|
||||
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
@@ -15,7 +14,6 @@ import javax.crypto.*
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -25,21 +23,20 @@ import javax.crypto.spec.SecretKeySpec
|
||||
*/
|
||||
object EncryptionHelper {
|
||||
private const val ALGORITHM = "AES"
|
||||
private const val TRANSFORMATION = "AES/CBC/PKCS5Padding"
|
||||
//private const val TRANSFORMATION = "AES"
|
||||
private const val TRANSFORMATION = "AES/CBC/PKCS5Padding"
|
||||
// private const val TRANSFORMATION = "AES"
|
||||
// private const val TRANSFORMATION = "DES/CBC/PKCS5Padding"
|
||||
|
||||
private val iV = byteArrayOf(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
|
||||
|
||||
private val iV = byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
|
||||
@Throws(CryptoException::class)
|
||||
fun doCryptoEncrypt(
|
||||
key: String, data: String,
|
||||
key: String,
|
||||
data: String,
|
||||
outputFile: OutputStream?
|
||||
) {
|
||||
try {
|
||||
|
||||
|
||||
val secretKey: Key =
|
||||
SecretKeySpec(key.toByteArray(), ALGORITHM)
|
||||
val cipher = Cipher.getInstance(TRANSFORMATION)
|
||||
@@ -47,7 +44,7 @@ object EncryptionHelper {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(iV))
|
||||
|
||||
data.byteInputStream().use {
|
||||
val inputStream = it
|
||||
val inputStream = it
|
||||
outputFile?.use {
|
||||
val outputStream = it
|
||||
CipherOutputStream(outputStream, cipher).use {
|
||||
@@ -62,7 +59,7 @@ object EncryptionHelper {
|
||||
// Log.d("TestingEnc","NoSuchAlgorithmException")
|
||||
throw CryptoException("Error encrypting/decrypting file", ex)
|
||||
} catch (ex: InvalidKeyException) {
|
||||
//Log.d("TestingEnc","InvalidKeyException")
|
||||
// Log.d("TestingEnc","InvalidKeyException")
|
||||
throw CryptoException("Error encrypting/decrypting file", ex)
|
||||
} catch (ex: BadPaddingException) {
|
||||
// Log.d("TestingEnc","BadPaddingException")
|
||||
@@ -76,11 +73,11 @@ object EncryptionHelper {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Throws(CryptoException::class)
|
||||
fun doCryptoDecrypt(
|
||||
key: String, inputFile: InputStream?
|
||||
) : String {
|
||||
key: String,
|
||||
inputFile: InputStream?
|
||||
): String {
|
||||
var data = ""
|
||||
try {
|
||||
val secretKey: Key =
|
||||
@@ -91,25 +88,24 @@ object EncryptionHelper {
|
||||
|
||||
inputFile.use {
|
||||
val inputStream = it
|
||||
CipherInputStream(inputStream, cipher).use {
|
||||
data = String(it.readBytes())
|
||||
}
|
||||
CipherInputStream(inputStream, cipher).use {
|
||||
data = String(it.readBytes())
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ex: NoSuchPaddingException) {
|
||||
//Log.d("TestingEnc","NoSuchPaddingException")
|
||||
// Log.d("TestingEnc","NoSuchPaddingException")
|
||||
throw CryptoException("Error encrypting/decrypting file", ex)
|
||||
} catch (ex: NoSuchAlgorithmException) {
|
||||
//Log.d("TestingEnc","NoSuchAlgorithmException")
|
||||
// Log.d("TestingEnc","NoSuchAlgorithmException")
|
||||
throw CryptoException("Error encrypting/decrypting file", ex)
|
||||
} catch (ex: InvalidKeyException) {
|
||||
//Log.d("TestingEnc","InvalidKeyException")
|
||||
// Log.d("TestingEnc","InvalidKeyException")
|
||||
throw CryptoException("Error encrypting/decrypting file", ex)
|
||||
} catch (ex: BadPaddingException) {
|
||||
//Log.d("TestingEnc","BadPaddingException")
|
||||
// Log.d("TestingEnc","BadPaddingException")
|
||||
throw CryptoException("Error encrypting/decrypting file", ex)
|
||||
} catch (ex: IllegalBlockSizeException) {
|
||||
//Log.d("TestingEnc","IllegalBlockSizeException")
|
||||
// Log.d("TestingEnc","IllegalBlockSizeException")
|
||||
throw CryptoException("Error encrypting/decrypting file", ex)
|
||||
} catch (ex: IOException) {
|
||||
// Log.d("TestingEnc","IOException")
|
||||
@@ -119,9 +115,7 @@ object EncryptionHelper {
|
||||
return data
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun encryptPassword(message: String, password: String): String{
|
||||
fun encryptPassword(message: String, password: String): String {
|
||||
/* Encrypt the message. */
|
||||
var cipher: Cipher? = null
|
||||
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
|
||||
@@ -147,11 +141,8 @@ object EncryptionHelper {
|
||||
return String(cipher.doFinal(encryptedMessage.toByteArray()))
|
||||
}
|
||||
|
||||
|
||||
@Throws(NoSuchAlgorithmException::class, InvalidKeySpecException::class)
|
||||
fun generateKey(passLockKey: String): SecretKey {
|
||||
return SecretKeySpec(passLockKey.encodeToByteArray(), "AES")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.yogeshpaliyal.keypass.listener
|
||||
|
||||
import android.view.View
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -11,4 +10,4 @@ import android.view.View
|
||||
*/
|
||||
interface UniversalClickListener<T> {
|
||||
fun onItemClick(view: View, model: T)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ class BasicService : AutofillService() {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Create the base response
|
||||
val response = FillResponse.Builder()
|
||||
|
||||
@@ -129,8 +128,9 @@ class BasicService : AutofillService() {
|
||||
fields[hint] = id
|
||||
} else {
|
||||
Log.v(
|
||||
TAG, "Ignoring hint '" + hint + "' on " + id
|
||||
+ " because it was already set"
|
||||
TAG,
|
||||
"Ignoring hint '" + hint + "' on " + id +
|
||||
" because it was already set"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -173,9 +173,9 @@ class BasicService : AutofillService() {
|
||||
text: CharSequence
|
||||
): RemoteViews {
|
||||
val presentation = RemoteViews(packageName, R.layout.multidataset_service_list_item)
|
||||
presentation.setTextViewText(R.id.text, "paliyal"+text)
|
||||
presentation.setTextViewText(R.id.text, "paliyal" + text)
|
||||
presentation.setImageViewResource(R.id.icon, R.mipmap.ic_launcher)
|
||||
return presentation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
package com.yogeshpaliyal.keypass.service
|
||||
|
||||
import android.app.assist.AssistStructure
|
||||
import android.app.assist.AssistStructure.ViewNode
|
||||
import android.os.Build
|
||||
import android.os.CancellationSignal
|
||||
import android.service.autofill.*
|
||||
import android.view.autofill.AutofillId
|
||||
import android.view.autofill.AutofillValue
|
||||
import android.widget.RemoteViews
|
||||
import androidx.annotation.NonNull
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -24,21 +17,13 @@ class MyAutoFillService : AutofillService() {
|
||||
private val TAG = "MyAutoFillService"
|
||||
private val NUMBER_DATASETS = 4
|
||||
|
||||
|
||||
override fun onFillRequest(
|
||||
request: FillRequest,
|
||||
cancellationSignal: CancellationSignal,
|
||||
callback: FillCallback
|
||||
) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun onSaveRequest(request: SaveRequest, callback: SaveCallback) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,24 +11,22 @@ import com.yogeshpaliyal.keypass.databinding.ActivityAuthenticationBinding
|
||||
import com.yogeshpaliyal.keypass.ui.nav.DashboardActivity
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
|
||||
class AuthenticationActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding : ActivityAuthenticationBinding
|
||||
private lateinit var binding: ActivityAuthenticationBinding
|
||||
|
||||
private lateinit var executor: Executor
|
||||
private lateinit var biometricPrompt: BiometricPrompt
|
||||
private lateinit var promptInfo: BiometricPrompt.PromptInfo
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityAuthenticationBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
|
||||
executor = ContextCompat.getMainExecutor(this)
|
||||
biometricPrompt = BiometricPrompt(this, executor,
|
||||
biometricPrompt = BiometricPrompt(
|
||||
this, executor,
|
||||
object : BiometricPrompt.AuthenticationCallback() {
|
||||
override fun onAuthenticationError(
|
||||
errorCode: Int,
|
||||
@@ -40,7 +38,7 @@ class AuthenticationActivity : AppCompatActivity() {
|
||||
"Authentication error: $errString", Toast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
// finish()
|
||||
// finish()
|
||||
}
|
||||
|
||||
override fun onAuthenticationSucceeded(
|
||||
@@ -59,8 +57,8 @@ class AuthenticationActivity : AppCompatActivity() {
|
||||
)
|
||||
.show()
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
promptInfo = BiometricPrompt.PromptInfo.Builder()
|
||||
.setTitle(getString(R.string.app_name))
|
||||
@@ -76,16 +74,13 @@ class AuthenticationActivity : AppCompatActivity() {
|
||||
|
||||
binding.btnRetry.setOnClickListener {
|
||||
biometricPrompt.authenticate(promptInfo)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun onAuthenticated(){
|
||||
// binding.passCodeView.isVisible = false
|
||||
private fun onAuthenticated() {
|
||||
// binding.passCodeView.isVisible = false
|
||||
val dashboardIntent = Intent(this, DashboardActivity::class.java)
|
||||
startActivity(dashboardIntent)
|
||||
finish()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import android.view.MenuItem
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.findNavController
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.yogeshpaliyal.keypass.AppDatabase
|
||||
import com.yogeshpaliyal.keypass.R
|
||||
@@ -18,7 +17,6 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -26,17 +24,16 @@ import kotlinx.coroutines.withContext
|
||||
* created on 31-01-2021 10:38
|
||||
*/
|
||||
class DetailActivity : AppCompatActivity() {
|
||||
|
||||
lateinit var binding : FragmentDetailBinding
|
||||
|
||||
lateinit var binding: FragmentDetailBinding
|
||||
|
||||
companion object{
|
||||
companion object {
|
||||
|
||||
private const val ARG_ACCOUNT_ID = "ARG_ACCOUNT_ID"
|
||||
@JvmStatic
|
||||
fun start(context: Context?, accountId: Long? = null) {
|
||||
val starter = Intent(context, DetailActivity::class.java)
|
||||
.putExtra(ARG_ACCOUNT_ID,accountId)
|
||||
.putExtra(ARG_ACCOUNT_ID, accountId)
|
||||
context?.startActivity(starter)
|
||||
}
|
||||
}
|
||||
@@ -45,7 +42,6 @@ class DetailActivity : AppCompatActivity() {
|
||||
initViewModel(DetailViewModel::class.java)
|
||||
}
|
||||
|
||||
|
||||
private val accountId by lazy {
|
||||
intent?.extras?.getLong(ARG_ACCOUNT_ID) ?: -1
|
||||
}
|
||||
@@ -57,9 +53,12 @@ class DetailActivity : AppCompatActivity() {
|
||||
binding.lifecycleOwner = this
|
||||
|
||||
mViewModel.loadAccount(accountId)
|
||||
mViewModel.accountModel.observe(this, Observer {
|
||||
binding.accountData = it
|
||||
})
|
||||
mViewModel.accountModel.observe(
|
||||
this,
|
||||
Observer {
|
||||
binding.accountData = it
|
||||
}
|
||||
)
|
||||
|
||||
if (accountId > 0) {
|
||||
binding.bottomAppBar.replaceMenu(R.menu.bottom_app_bar_detail)
|
||||
@@ -68,7 +67,7 @@ class DetailActivity : AppCompatActivity() {
|
||||
onBackPressed()
|
||||
}
|
||||
binding.bottomAppBar.setOnMenuItemClickListener { item ->
|
||||
if (item.itemId == R.id.action_delete){
|
||||
if (item.itemId == R.id.action_delete) {
|
||||
deleteAccount()
|
||||
return@setOnMenuItemClickListener true
|
||||
}
|
||||
@@ -93,7 +92,8 @@ class DetailActivity : AppCompatActivity() {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle("Are you sure?")
|
||||
.setMessage("Do you really want to delete this entry, it can't be restored")
|
||||
.setPositiveButton("Delete"
|
||||
.setPositiveButton(
|
||||
"Delete"
|
||||
) { dialog, which ->
|
||||
dialog?.dismiss()
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
@@ -105,10 +105,9 @@ class DetailActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
.setNegativeButton("Cancel"){dialog, which ->
|
||||
.setNegativeButton("Cancel") { dialog, which ->
|
||||
dialog.dismiss()
|
||||
}.show()
|
||||
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
@@ -120,4 +119,4 @@ class DetailActivity : AppCompatActivity() {
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.yogeshpaliyal.keypass.data.AccountModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -27,8 +26,5 @@ class DetailViewModel(application: Application) : AndroidViewModel(application)
|
||||
AppDatabase.getInstance().getDao().getAccount(accountId) ?: AccountModel()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.yogeshpaliyal.keypass.ui.generate
|
||||
|
||||
import android.R.attr.label
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.os.Bundle
|
||||
@@ -10,9 +9,8 @@ import androidx.core.content.getSystemService
|
||||
import com.yogeshpaliyal.keypass.databinding.ActivityGeneratePasswordBinding
|
||||
import com.yogeshpaliyal.keypass.utils.PasswordGenerator
|
||||
|
||||
|
||||
class GeneratePasswordActivity : AppCompatActivity() {
|
||||
private lateinit var binding : ActivityGeneratePasswordBinding
|
||||
private lateinit var binding: ActivityGeneratePasswordBinding
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityGeneratePasswordBinding.inflate(layoutInflater)
|
||||
@@ -25,15 +23,14 @@ class GeneratePasswordActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
binding.tilPassword.setEndIconOnClickListener {
|
||||
val clipboard= getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("random_password", binding.etPassword.text)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
Toast.makeText(this, "Copied to clipboard", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun generatePassword(){
|
||||
private fun generatePassword() {
|
||||
val password = PasswordGenerator(
|
||||
10, binding.cbCapAlphabets.isChecked,
|
||||
binding.cbLowerAlphabets.isChecked,
|
||||
@@ -43,4 +40,4 @@ class GeneratePasswordActivity : AppCompatActivity() {
|
||||
|
||||
binding.etPassword.setText(password)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,13 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import com.yogeshpaliyal.keypass.R
|
||||
import com.yogeshpaliyal.keypass.data.AccountModel
|
||||
import com.yogeshpaliyal.keypass.databinding.FragmentHomeBinding
|
||||
import com.yogeshpaliyal.keypass.db_helper.EncryptionHelper
|
||||
import com.yogeshpaliyal.keypass.listener.UniversalClickListener
|
||||
import com.yogeshpaliyal.keypass.ui.detail.DetailActivity
|
||||
import com.yogeshpaliyal.keypass.utils.initViewModel
|
||||
import com.yogeshpaliyal.keypass.utils.logD
|
||||
import com.yogeshpaliyal.universal_adapter.adapter.UniversalAdapterViewType
|
||||
import com.yogeshpaliyal.universal_adapter.adapter.UniversalRecyclerAdapter
|
||||
import com.yogeshpaliyal.universal_adapter.utils.Resource
|
||||
@@ -25,7 +22,6 @@ import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -33,7 +29,7 @@ import kotlinx.coroutines.withContext
|
||||
* created on 31-01-2021 09:25
|
||||
*/
|
||||
class HomeFragment : Fragment() {
|
||||
private lateinit var binding : FragmentHomeBinding
|
||||
private lateinit var binding: FragmentHomeBinding
|
||||
|
||||
private val mViewModel by lazy {
|
||||
initViewModel(HomeViewModel::class.java)
|
||||
@@ -41,16 +37,17 @@ class HomeFragment : Fragment() {
|
||||
|
||||
private val args: HomeFragmentArgs by navArgs()
|
||||
|
||||
|
||||
private val mAdapter by lazy {
|
||||
val adapterOptions = UniversalAdapterOptions<AccountModel>(this,
|
||||
content = UniversalAdapterViewType.Content(R.layout.item_accounts,mListener = mListener),
|
||||
noData = UniversalAdapterViewType.NoData(R.layout.layout_no_accounts))
|
||||
val adapterOptions = UniversalAdapterOptions<AccountModel>(
|
||||
this,
|
||||
content = UniversalAdapterViewType.Content(R.layout.item_accounts, mListener = mListener),
|
||||
noData = UniversalAdapterViewType.NoData(R.layout.layout_no_accounts)
|
||||
)
|
||||
|
||||
UniversalRecyclerAdapter<AccountModel>(adapterOptions)
|
||||
}
|
||||
|
||||
val mListener = object : UniversalClickListener<AccountModel>{
|
||||
val mListener = object : UniversalClickListener<AccountModel> {
|
||||
override fun onItemClick(view: View, model: AccountModel) {
|
||||
DetailActivity.start(context, model.id)
|
||||
}
|
||||
@@ -61,7 +58,7 @@ class HomeFragment : Fragment() {
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = FragmentHomeBinding.inflate(layoutInflater,container,false)
|
||||
binding = FragmentHomeBinding.inflate(layoutInflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
@@ -69,16 +66,12 @@ class HomeFragment : Fragment() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.recyclerView.adapter = mAdapter
|
||||
lifecycleScope.launch(Dispatchers.IO){
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
mViewModel.loadData(args.tag).collect {
|
||||
withContext(Dispatchers.Main) {
|
||||
mAdapter.updateData(Resource.success(ArrayList(it)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,7 @@ package com.yogeshpaliyal.keypass.ui.home
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.yogeshpaliyal.keypass.AppDatabase
|
||||
import com.yogeshpaliyal.keypass.data.AccountModel
|
||||
import com.yogeshpaliyal.universal_adapter.utils.Resource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
@@ -19,12 +12,9 @@ import kotlinx.coroutines.launch
|
||||
*/
|
||||
class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
|
||||
private val dao by lazy {
|
||||
AppDatabase.getInstance().getDao()
|
||||
}
|
||||
|
||||
|
||||
suspend fun loadData(tag : String?)= if (tag.isNullOrBlank())dao.getAllAccounts() else dao.getAllAccounts(tag)
|
||||
|
||||
}
|
||||
suspend fun loadData(tag: String?) = if (tag.isNullOrBlank())dao.getAllAccounts() else dao.getAllAccounts(tag)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.yogeshpaliyal.keypass.R
|
||||
import com.yogeshpaliyal.keypass.databinding.FragmentBottomNavDrawerBinding
|
||||
import com.yogeshpaliyal.keypass.utils.initViewModel
|
||||
import com.yogeshpaliyal.keypass.utils.themeColor
|
||||
|
||||
import kotlin.LazyThreadSafetyMode.NONE
|
||||
|
||||
/**
|
||||
@@ -31,8 +30,6 @@ class BottomNavDrawerFragment :
|
||||
Fragment(),
|
||||
NavigationAdapter.NavigationAdapterListener {
|
||||
|
||||
|
||||
|
||||
private lateinit var binding: FragmentBottomNavDrawerBinding
|
||||
|
||||
private val behavior: BottomSheetBehavior<FrameLayout> by lazy(NONE) {
|
||||
@@ -45,11 +42,8 @@ class BottomNavDrawerFragment :
|
||||
|
||||
private val bottomSheetCallback = BottomNavigationDrawerCallback()
|
||||
|
||||
|
||||
private val navigationListeners: MutableList<NavigationAdapter.NavigationAdapterListener> =
|
||||
mutableListOf()
|
||||
|
||||
|
||||
mutableListOf()
|
||||
|
||||
private val foregroundShapeDrawable: MaterialShapeDrawable by lazy(NONE) {
|
||||
val foregroundContext = binding.foregroundContainer.context
|
||||
@@ -78,7 +72,6 @@ class BottomNavDrawerFragment :
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val closeDrawerOnBackPressed = object : OnBackPressedCallback(false) {
|
||||
override fun handleOnBackPressed() {
|
||||
close()
|
||||
@@ -111,7 +104,7 @@ class BottomNavDrawerFragment :
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.run {
|
||||
//backgroundContainer.background = backgroundShapeDrawable
|
||||
// backgroundContainer.background = backgroundShapeDrawable
|
||||
foregroundContainer.background = foregroundShapeDrawable
|
||||
|
||||
scrimView.setOnClickListener { close() }
|
||||
@@ -130,7 +123,6 @@ class BottomNavDrawerFragment :
|
||||
// Close the sandwiching account picker if open
|
||||
addOnStateChangedAction(object : OnStateChangedAction {
|
||||
override fun onStateChanged(sheet: View, newState: Int) {
|
||||
|
||||
}
|
||||
})
|
||||
// If the drawer is open, pressing the system back button should close the drawer.
|
||||
@@ -141,8 +133,6 @@ class BottomNavDrawerFragment :
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
behavior.addBottomSheetCallback(bottomSheetCallback)
|
||||
behavior.state = STATE_HIDDEN
|
||||
|
||||
@@ -153,11 +143,9 @@ class BottomNavDrawerFragment :
|
||||
adapter.submitList(it)
|
||||
}
|
||||
mViewModel.setNavigationMenuItemChecked(0)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun open() {
|
||||
behavior.state = STATE_HALF_EXPANDED
|
||||
}
|
||||
@@ -178,8 +166,6 @@ class BottomNavDrawerFragment :
|
||||
navigationListeners.add(listener)
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun onNavMenuItemClicked(item: NavigationModelItem.NavMenuItem) {
|
||||
mViewModel.setNavigationMenuItemChecked(item.id)
|
||||
close()
|
||||
@@ -190,15 +176,13 @@ class BottomNavDrawerFragment :
|
||||
navigationListeners.forEach { it.onNavEmailFolderClicked(folder) }
|
||||
}
|
||||
|
||||
|
||||
fun toggle() {
|
||||
when {
|
||||
behavior.state == STATE_HIDDEN -> open()
|
||||
behavior.state == STATE_HIDDEN
|
||||
|| behavior.state == STATE_HALF_EXPANDED
|
||||
|| behavior.state == STATE_EXPANDED
|
||||
|| behavior.state == STATE_COLLAPSED -> close()
|
||||
behavior.state == STATE_HIDDEN ||
|
||||
behavior.state == STATE_HALF_EXPANDED ||
|
||||
behavior.state == STATE_EXPANDED
|
||||
|| behavior.state == STATE_COLLAPSED -> close()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.yogeshpaliyal.keypass.AppDatabase
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -20,13 +19,13 @@ class BottomNavViewModel(application: Application) : AndroidViewModel(applicatio
|
||||
private val _navigationList: MutableLiveData<List<NavigationModelItem>> = MutableLiveData()
|
||||
private val tagsDb = AppDatabase.getInstance().getDao().getTags()
|
||||
|
||||
private var tagsList : List<String> ?= null
|
||||
private var tagsList: List<String> ? = null
|
||||
|
||||
val navigationList: LiveData<List<NavigationModelItem>>
|
||||
get() = _navigationList
|
||||
|
||||
init {
|
||||
postListUpdate()
|
||||
postListUpdate()
|
||||
|
||||
viewModelScope.launch {
|
||||
tagsDb.collect {
|
||||
@@ -36,8 +35,6 @@ class BottomNavViewModel(application: Application) : AndroidViewModel(applicatio
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the currently selected menu item.
|
||||
*
|
||||
@@ -56,18 +53,13 @@ class BottomNavViewModel(application: Application) : AndroidViewModel(applicatio
|
||||
return updated
|
||||
}
|
||||
|
||||
|
||||
private fun postListUpdate() {
|
||||
val newList = if(tagsList.isNullOrEmpty().not()){
|
||||
val newList = if (tagsList.isNullOrEmpty().not()) {
|
||||
NavigationModel.navigationMenuItems + NavigationModelItem.NavDivider("Tags") + (tagsList?.filter { it != null }?.map { NavigationModelItem.NavEmailFolder(it) } ?: listOf())
|
||||
}else{
|
||||
} else {
|
||||
NavigationModel.navigationMenuItems
|
||||
}
|
||||
|
||||
|
||||
_navigationList.value = newList
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,4 +97,4 @@ class BottomNavigationDrawerCallback : BottomSheetBehavior.BottomSheetCallback()
|
||||
fun removeOnStateChangedAction(action: OnStateChangedAction): Boolean {
|
||||
return onStateChangedActions.remove(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,30 +11,24 @@ import androidx.annotation.MenuRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDestination
|
||||
import androidx.navigation.findNavController
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.transition.MaterialElevationScale
|
||||
import com.yogeshpaliyal.keypass.AppDatabase
|
||||
import com.yogeshpaliyal.keypass.R
|
||||
import com.yogeshpaliyal.keypass.databinding.ActivityDashboardBinding
|
||||
import com.yogeshpaliyal.keypass.ui.detail.DetailActivity
|
||||
import com.yogeshpaliyal.keypass.ui.generate.GeneratePasswordActivity
|
||||
import com.yogeshpaliyal.keypass.ui.home.HomeFragmentDirections
|
||||
import com.yogeshpaliyal.keypass.ui.settings.MySettingsFragmentDirections
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class DashboardActivity : AppCompatActivity(),
|
||||
class DashboardActivity :
|
||||
AppCompatActivity(),
|
||||
Toolbar.OnMenuItemClickListener,
|
||||
NavController.OnDestinationChangedListener,
|
||||
NavigationAdapter.NavigationAdapterListener {
|
||||
lateinit var binding: ActivityDashboardBinding
|
||||
|
||||
|
||||
private val bottomNavDrawer: BottomNavDrawerFragment by lazy(LazyThreadSafetyMode.NONE) {
|
||||
supportFragmentManager.findFragmentById(R.id.bottom_nav_drawer) as BottomNavDrawerFragment
|
||||
}
|
||||
@@ -47,22 +41,19 @@ class DashboardActivity : AppCompatActivity(),
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
|
||||
binding = ActivityDashboardBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
//setSupportActionBar(binding.bottomAppBar)
|
||||
|
||||
// setSupportActionBar(binding.bottomAppBar)
|
||||
|
||||
findNavController(R.id.nav_host_fragment).addOnDestinationChangedListener(
|
||||
this@DashboardActivity
|
||||
)
|
||||
|
||||
|
||||
/* val intent = Intent(this, AuthenticationActivity::class.java)
|
||||
startActivity(intent)*/
|
||||
|
||||
|
||||
/* val autoFillService = getAutoFillService()
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
if (autoFillService?.isAutofillSupported == true && autoFillService.hasEnabledAutofillServices().not()) {
|
||||
@@ -72,7 +63,6 @@ class DashboardActivity : AppCompatActivity(),
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
binding.btnAdd.setOnClickListener {
|
||||
currentNavigationFragment?.apply {
|
||||
exitTransition = MaterialElevationScale(false).apply {
|
||||
@@ -83,25 +73,26 @@ class DashboardActivity : AppCompatActivity(),
|
||||
}
|
||||
}
|
||||
|
||||
DetailActivity.start(this)
|
||||
DetailActivity.start(this)
|
||||
}
|
||||
|
||||
|
||||
bottomNavDrawer.apply {
|
||||
//addOnSlideAction(HalfClockwiseRotateSlideAction(binding.bottomAppBar))
|
||||
// addOnSlideAction(HalfClockwiseRotateSlideAction(binding.bottomAppBar))
|
||||
// addOnSlideAction(AlphaSlideAction(binding.bottomAppBarTitle, true))
|
||||
addOnStateChangedAction(ShowHideFabStateAction(binding.btnAdd))
|
||||
addOnStateChangedAction(ChangeSettingsMenuStateAction { showSettings ->
|
||||
// Toggle between the current destination's BAB menu and the menu which should
|
||||
// be displayed when the BottomNavigationDrawer is open.
|
||||
binding.bottomAppBar.replaceMenu(
|
||||
if (showSettings) {
|
||||
R.menu.bottom_app_bar_settings_menu
|
||||
} else {
|
||||
getBottomAppBarMenuForDestination()
|
||||
}
|
||||
)
|
||||
})
|
||||
addOnStateChangedAction(
|
||||
ChangeSettingsMenuStateAction { showSettings ->
|
||||
// Toggle between the current destination's BAB menu and the menu which should
|
||||
// be displayed when the BottomNavigationDrawer is open.
|
||||
binding.bottomAppBar.replaceMenu(
|
||||
if (showSettings) {
|
||||
R.menu.bottom_app_bar_settings_menu
|
||||
} else {
|
||||
getBottomAppBarMenuForDestination()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
// addOnSandwichSlideAction(HalfCounterClockwiseRotateSlideAction(binding.bottomAppBarChevron))
|
||||
addNavigationListener(this@DashboardActivity)
|
||||
@@ -114,8 +105,6 @@ class DashboardActivity : AppCompatActivity(),
|
||||
}
|
||||
setOnMenuItemClickListener(this@DashboardActivity)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||
@@ -129,8 +118,6 @@ class DashboardActivity : AppCompatActivity(),
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun onDestinationChanged(
|
||||
controller: NavController,
|
||||
destination: NavDestination,
|
||||
@@ -146,8 +133,8 @@ class DashboardActivity : AppCompatActivity(),
|
||||
|
||||
override fun onNavMenuItemClicked(item: NavigationModelItem.NavMenuItem) {
|
||||
// Swap the list of emails for the given mailbox
|
||||
//navigateToHome(item.titleRes, item.mailbox)
|
||||
when(item.id){
|
||||
// navigateToHome(item.titleRes, item.mailbox)
|
||||
when (item.id) {
|
||||
NavigationModel.GENERATE_PASSWORD -> {
|
||||
val intent = Intent(this, GeneratePasswordActivity::class.java)
|
||||
startActivity(intent)
|
||||
@@ -165,7 +152,6 @@ class DashboardActivity : AppCompatActivity(),
|
||||
bottomNavDrawer.close()
|
||||
}
|
||||
|
||||
|
||||
private fun hideBottomAppBar() {
|
||||
binding.run {
|
||||
bottomAppBar.performHide()
|
||||
@@ -202,21 +188,20 @@ class DashboardActivity : AppCompatActivity(),
|
||||
val dest = destination ?: findNavController(R.id.nav_host_fragment).currentDestination
|
||||
return when (dest?.id) {
|
||||
R.id.homeFragment -> R.menu.bottom_app_bar_settings_menu
|
||||
//R.id.emailFragment -> R.menu.bottom_app_bar_email_menu
|
||||
// R.id.emailFragment -> R.menu.bottom_app_bar_email_menu
|
||||
else -> R.menu.bottom_app_bar_settings_menu
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setBottomAppBarForHome(@MenuRes menuRes: Int) {
|
||||
binding.run {
|
||||
btnAdd.setImageState(intArrayOf(-android.R.attr.state_activated), true)
|
||||
bottomAppBar.visibility = View.VISIBLE
|
||||
bottomAppBar.replaceMenu(menuRes)
|
||||
//btnAdd.contentDescription = getString(R.string.fab_compose_email_content_description)
|
||||
//bottomAppBarTitle.visibility = View.VISIBLE
|
||||
// btnAdd.contentDescription = getString(R.string.fab_compose_email_content_description)
|
||||
// bottomAppBarTitle.visibility = View.VISIBLE
|
||||
bottomAppBar.performShow()
|
||||
btnAdd.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,4 +86,4 @@ class NavigationAdapter(
|
||||
) {
|
||||
holder.bind(getItem(position))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.yogeshpaliyal.keypass.ui.nav
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.yogeshpaliyal.keypass.R
|
||||
|
||||
/**
|
||||
@@ -12,7 +10,6 @@ object NavigationModel {
|
||||
const val HOME = 0
|
||||
const val GENERATE_PASSWORD = 1
|
||||
|
||||
|
||||
var navigationMenuItems = mutableListOf(
|
||||
NavigationModelItem.NavMenuItem(
|
||||
id = HOME,
|
||||
@@ -27,11 +24,4 @@ object NavigationModel {
|
||||
checked = false,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -50,14 +50,14 @@ sealed class NavigationModelItem {
|
||||
newItem: NavigationModelItem
|
||||
): Boolean {
|
||||
return when {
|
||||
oldItem is NavMenuItem && newItem is NavMenuItem ->
|
||||
oldItem.icon == newItem.icon &&
|
||||
oldItem.titleRes == newItem.titleRes &&
|
||||
oldItem.checked == newItem.checked
|
||||
oldItem is NavMenuItem && newItem is NavMenuItem ->
|
||||
oldItem.icon == newItem.icon &&
|
||||
oldItem.titleRes == newItem.titleRes &&
|
||||
oldItem.checked == newItem.checked
|
||||
oldItem is NavEmailFolder && newItem is NavEmailFolder ->
|
||||
StringDiffUtil.areContentsTheSame(oldItem.category, newItem.category)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.yogeshpaliyal.keypass.ui.nav
|
||||
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.yogeshpaliyal.keypass.databinding.NavDividerItemLayoutBinding
|
||||
@@ -11,7 +10,7 @@ sealed class NavigationViewHolder<T : NavigationModelItem>(
|
||||
view: View
|
||||
) : RecyclerView.ViewHolder(view) {
|
||||
|
||||
abstract fun bind(navItem : T)
|
||||
abstract fun bind(navItem: T)
|
||||
|
||||
class NavMenuItemViewHolder(
|
||||
private val binding: NavMenuItemLayoutBinding,
|
||||
@@ -49,4 +48,4 @@ sealed class NavigationViewHolder<T : NavigationModelItem>(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.yogeshpaliyal.keypass.ui.settings
|
||||
|
||||
import android.R.attr.label
|
||||
import android.app.Activity
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
@@ -25,7 +23,6 @@ import com.yogeshpaliyal.keypass.db_helper.restoreBackup
|
||||
import com.yogeshpaliyal.keypass.utils.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
private val CHOOSE_BACKUPS_LOCATION_REQUEST_CODE = 26212
|
||||
private val CHOOSE_RESTORE_FILE_REQUEST_CODE = 26213
|
||||
@@ -35,7 +32,7 @@ class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
|
||||
when(preference?.key){
|
||||
when (preference?.key) {
|
||||
"feedback" -> {
|
||||
context?.email("Feedback to KeyPass", "techpaliyal@gmail.com")
|
||||
return true
|
||||
@@ -66,19 +63,19 @@ class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
return super.onPreferenceTreeClick(preference)
|
||||
}
|
||||
|
||||
private fun selectBackupDirectory(){
|
||||
private fun selectBackupDirectory() {
|
||||
val selectedDirectory = Uri.parse(getBackupDirectory())
|
||||
|
||||
context?.let {
|
||||
if(it.canUserAccessBackupDirectory()){
|
||||
if (it.canUserAccessBackupDirectory()) {
|
||||
backup(selectedDirectory)
|
||||
}else{
|
||||
} else {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
|
||||
intent.addFlags(
|
||||
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
|
||||
try {
|
||||
@@ -88,30 +85,28 @@ class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun selectRestoreFile(){
|
||||
private fun selectRestoreFile() {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
intent.type = "*/*"
|
||||
|
||||
intent.addFlags(
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
|
||||
try {
|
||||
startActivityForResult(intent, CHOOSE_RESTORE_FILE_REQUEST_CODE)
|
||||
}catch (e: Exception){
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == CHOOSE_BACKUPS_LOCATION_REQUEST_CODE && resultCode == Activity.RESULT_OK){
|
||||
if (requestCode == CHOOSE_BACKUPS_LOCATION_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
||||
val contentResolver = context?.contentResolver
|
||||
val selectedDirectory = data?.data
|
||||
if (contentResolver != null && selectedDirectory != null) {
|
||||
@@ -123,7 +118,7 @@ class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
setBackupDirectory(selectedDirectory.toString())
|
||||
backup(selectedDirectory)
|
||||
}
|
||||
} else if (requestCode == CHOOSE_RESTORE_FILE_REQUEST_CODE && resultCode == Activity.RESULT_OK){
|
||||
} else if (requestCode == CHOOSE_RESTORE_FILE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
||||
val contentResolver = context?.contentResolver
|
||||
val selectedFile = data?.data
|
||||
if (contentResolver != null && selectedFile != null) {
|
||||
@@ -140,7 +135,7 @@ class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
"Restore"
|
||||
) { dialog, which ->
|
||||
lifecycleScope.launch {
|
||||
val result = AppDatabase.getInstance().restoreBackup(binding.etKeyPhrase.text.toString(),contentResolver, selectedFile)
|
||||
val result = AppDatabase.getInstance().restoreBackup(binding.etKeyPhrase.text.toString(), contentResolver, selectedFile)
|
||||
if (result) {
|
||||
dialog?.dismiss()
|
||||
Toast.makeText(
|
||||
@@ -148,7 +143,7 @@ class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
getString(R.string.backup_restored),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}else{
|
||||
} else {
|
||||
Toast.makeText(
|
||||
context,
|
||||
getString(R.string.invalid_keyphrase),
|
||||
@@ -157,13 +152,11 @@ class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
}
|
||||
}.show()
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun backup(selectedDirectory: Uri){
|
||||
fun backup(selectedDirectory: Uri) {
|
||||
|
||||
val keyPair = getOrCreateBackupKey()
|
||||
|
||||
@@ -174,10 +167,11 @@ class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
lifecycleScope.launch {
|
||||
context?.contentResolver?.let {
|
||||
AppDatabase.getInstance().createBackup(keyPair.second,
|
||||
it,
|
||||
tempFile?.uri
|
||||
)
|
||||
AppDatabase.getInstance().createBackup(
|
||||
keyPair.second,
|
||||
it,
|
||||
tempFile?.uri
|
||||
)
|
||||
if (keyPair.first) {
|
||||
val binding = LayoutBackupKeypharseBinding.inflate(layoutInflater)
|
||||
binding.txtCode.text = getOrCreateBackupKey().second
|
||||
@@ -191,14 +185,13 @@ class MySettingsFragment : PreferenceFragmentCompat() {
|
||||
MaterialAlertDialogBuilder(requireContext()).setView(binding.root)
|
||||
.setPositiveButton(
|
||||
"Yes"
|
||||
) { dialog, which -> dialog?.dismiss()
|
||||
) { dialog, which ->
|
||||
dialog?.dismiss()
|
||||
}.show()
|
||||
}else{
|
||||
} else {
|
||||
Toast.makeText(context, getString(R.string.backup_completed), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.yogeshpaliyal.keypass.ui.settings_activity
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.yogeshpaliyal.keypass.R
|
||||
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
@@ -9,4 +9,4 @@ class SettingsActivity : AppCompatActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_settings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,4 +132,4 @@ fun Float.normalize(
|
||||
|
||||
return outputMin * (1 - (this - inputMin) / (inputMax - inputMin)) +
|
||||
outputMax * ((this - inputMin) / (inputMax - inputMin))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.content.Context
|
||||
import android.view.autofill.AutofillManager
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -12,9 +11,8 @@ import androidx.core.content.ContextCompat.getSystemService
|
||||
* created on 31-01-2021 15:27
|
||||
*/
|
||||
|
||||
|
||||
fun Context?.getAutoFillService() = if (this != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
getSystemService(this, AutofillManager::class.java)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
fun Context?.getAutoFillService() = if (this != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
getSystemService(this, AutofillManager::class.java)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.text.TextUtils
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import java.security.SecureRandom
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -20,21 +19,21 @@ fun getRandomString(sizeOfRandomString: Int): String {
|
||||
val random = SecureRandom()
|
||||
val sb = StringBuilder(sizeOfRandomString)
|
||||
for (i in 0 until sizeOfRandomString) sb.append(
|
||||
ALLOWED_CHARACTERS[random.nextInt(
|
||||
ALLOWED_CHARACTERS.length
|
||||
)]
|
||||
ALLOWED_CHARACTERS[
|
||||
random.nextInt(
|
||||
ALLOWED_CHARACTERS.length
|
||||
)
|
||||
]
|
||||
)
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
|
||||
fun Context.canUserAccessBackupDirectory(): Boolean {
|
||||
val backupDirectoryUri = getUri(getBackupDirectory()) ?: return false
|
||||
val backupDirectory = DocumentFile.fromTreeUri(this, backupDirectoryUri)
|
||||
return backupDirectory != null && backupDirectory.exists() && backupDirectory.canRead() && backupDirectory.canWrite()
|
||||
}
|
||||
|
||||
|
||||
private fun getUri(string: String?): Uri? {
|
||||
val uri = string
|
||||
return if (TextUtils.isEmpty(uri)) {
|
||||
|
||||
@@ -15,31 +15,29 @@
|
||||
|
||||
package com.yogeshpaliyal.keypass.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowInsets
|
||||
import android.widget.ImageView
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.databinding.BindingAdapter
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.elevation.ElevationOverlayProvider
|
||||
|
||||
@BindingAdapter(
|
||||
"popupElevationOverlay"
|
||||
)
|
||||
fun Spinner.bindPopupElevationOverlay(popupElevationOverlay: Float) {
|
||||
setPopupBackgroundDrawable(ColorDrawable(
|
||||
ElevationOverlayProvider(context)
|
||||
.compositeOverlayWithThemeSurfaceColorIfNeeded(popupElevationOverlay)
|
||||
))
|
||||
setPopupBackgroundDrawable(
|
||||
ColorDrawable(
|
||||
ElevationOverlayProvider(context)
|
||||
.compositeOverlayWithThemeSurfaceColorIfNeeded(popupElevationOverlay)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@BindingAdapter(
|
||||
@@ -67,8 +65,6 @@ fun TextView.bindDrawables(
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@BindingAdapter("goneIf")
|
||||
fun View.bindGoneIf(gone: Boolean) {
|
||||
visibility = if (gone) {
|
||||
@@ -219,4 +215,4 @@ fun View.requestApplyInsetsWhenAttached() {
|
||||
override fun onViewDetachedFromWindow(v: View) = Unit
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.yogeshpaliyal.keypass.utils
|
||||
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
@@ -46,4 +45,4 @@ class ContentViewBindingDelegate<in R : AppCompatActivity, out T : ViewDataBindi
|
||||
|
||||
fun <R : AppCompatActivity, T : ViewDataBinding> contentView(
|
||||
@LayoutRes layoutRes: Int
|
||||
): ContentViewBindingDelegate<R, T> = ContentViewBindingDelegate(layoutRes)
|
||||
): ContentViewBindingDelegate<R, T> = ContentViewBindingDelegate(layoutRes)
|
||||
|
||||
@@ -67,4 +67,4 @@ fun Context.themeInterpolator(@AttrRes attr: Int): Interpolator {
|
||||
|
||||
fun Context.getDrawableOrNull(@DrawableRes id: Int?): Drawable? {
|
||||
return if (id == null || id == 0) null else AppCompatResources.getDrawable(this, id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -14,7 +13,6 @@ import android.net.Uri
|
||||
|
||||
@JvmName("IntentHelper")
|
||||
|
||||
|
||||
fun Context.email(
|
||||
chooserTitle: String,
|
||||
email: String = "",
|
||||
@@ -38,7 +36,6 @@ fun Context.email(
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
fun Context.makeCall(chooserTitle: String, number: String): Boolean {
|
||||
@@ -53,7 +50,6 @@ fun Context.makeCall(chooserTitle: String, number: String): Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun Context.sendSMS(chooserTitle: String, number: String, text: String = ""): Boolean {
|
||||
try {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("sms:$number"))
|
||||
@@ -66,7 +62,6 @@ fun Context.sendSMS(chooserTitle: String, number: String, text: String = ""): Bo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun Context.share(chooserTitle: String, text: String): Boolean {
|
||||
try {
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
@@ -80,7 +75,6 @@ fun Context.share(chooserTitle: String, text: String): Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun Context.navigate(address: String) {
|
||||
val gmmIntentUri =
|
||||
Uri.parse("google.navigation:q=$address")
|
||||
@@ -90,4 +84,3 @@ fun Context.navigate(address: String) {
|
||||
startActivity(mapIntent)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.yogeshpaliyal.keypass.utils
|
||||
import android.util.Log
|
||||
import com.yogeshpaliyal.keypass.BuildConfig
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -47,4 +46,4 @@ fun Any?.logV(tag: String?) {
|
||||
|
||||
fun Any?.logW(tag: String?) {
|
||||
if (BuildConfig.DEBUG) Log.w(tag, this.toString())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,39 @@
|
||||
package com.yogeshpaliyal.keypass.utils
|
||||
|
||||
class PasswordGenerator(private var length: Int, private var includeUpperCaseLetters : Boolean,
|
||||
private var includeLowerCaseLetters : Boolean,
|
||||
private var includeSymbols : Boolean, private var includeNumbers: Boolean) {
|
||||
class PasswordGenerator(
|
||||
private var length: Int,
|
||||
private var includeUpperCaseLetters: Boolean,
|
||||
private var includeLowerCaseLetters: Boolean,
|
||||
private var includeSymbols: Boolean,
|
||||
private var includeNumbers: Boolean
|
||||
) {
|
||||
|
||||
private val UPPER_CASE = 0
|
||||
private val LOWER_CASE = 1
|
||||
private val NUMBERS = 2
|
||||
private val SYMBOLS = 3
|
||||
|
||||
public fun generatePassword() : String {
|
||||
public fun generatePassword(): String {
|
||||
var password = ""
|
||||
val list = ArrayList<Int>()
|
||||
if(includeUpperCaseLetters)
|
||||
val list = ArrayList<Int>()
|
||||
if (includeUpperCaseLetters)
|
||||
list.add(UPPER_CASE)
|
||||
if(includeLowerCaseLetters)
|
||||
if (includeLowerCaseLetters)
|
||||
list.add(LOWER_CASE)
|
||||
if(includeNumbers)
|
||||
if (includeNumbers)
|
||||
list.add(NUMBERS)
|
||||
if(includeSymbols)
|
||||
if (includeSymbols)
|
||||
list.add(SYMBOLS)
|
||||
|
||||
for(i in 1..length){
|
||||
for (i in 1..length) {
|
||||
val choice = list.random()
|
||||
when(choice){
|
||||
when (choice) {
|
||||
UPPER_CASE -> password += ('A'..'Z').random().toString()
|
||||
LOWER_CASE -> password += ('a'..'z').random().toString()
|
||||
NUMBERS -> password += ('0'..'9').random().toString()
|
||||
SYMBOLS -> password += listOf('!','@','#','$','%','&','*','+','=','-','~','?','/','_').random().toString()
|
||||
SYMBOLS -> password += listOf('!', '@', '#', '$', '%', '&', '*', '+', '=', '-', '~', '?', '/', '_').random().toString()
|
||||
}
|
||||
}
|
||||
return password
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import androidx.security.crypto.MasterKey
|
||||
import com.yogeshpaliyal.keypass.MyApplication
|
||||
import java.util.*
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -17,27 +16,28 @@ import java.util.*
|
||||
* created on 21-02-2021 11:18
|
||||
*/
|
||||
|
||||
fun getSharedPreferences() : SharedPreferences{
|
||||
fun getSharedPreferences(): SharedPreferences {
|
||||
val masterKeyAlias = MasterKey.Builder(MyApplication.instance).also {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
// this is equivalent to using deprecated MasterKeys.AES256_GCM_SPEC
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
// this is equivalent to using deprecated MasterKeys.AES256_GCM_SPEC
|
||||
|
||||
// this is equivalent to using deprecated MasterKeys.AES256_GCM_SPEC
|
||||
val spec = KeyGenParameterSpec.Builder(
|
||||
MasterKey.DEFAULT_MASTER_KEY_ALIAS,
|
||||
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
|
||||
)
|
||||
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
||||
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
||||
.setKeySize(256)
|
||||
.build()
|
||||
it.setKeyGenParameterSpec(spec)
|
||||
}
|
||||
//it.setUserAuthenticationRequired(true)
|
||||
// this is equivalent to using deprecated MasterKeys.AES256_GCM_SPEC
|
||||
val spec = KeyGenParameterSpec.Builder(
|
||||
MasterKey.DEFAULT_MASTER_KEY_ALIAS,
|
||||
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
|
||||
)
|
||||
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
||||
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
||||
.setKeySize(256)
|
||||
.build()
|
||||
it.setKeyGenParameterSpec(spec)
|
||||
}
|
||||
// it.setUserAuthenticationRequired(true)
|
||||
}
|
||||
.build()
|
||||
|
||||
return EncryptedSharedPreferences.create(MyApplication.instance,
|
||||
return EncryptedSharedPreferences.create(
|
||||
MyApplication.instance,
|
||||
"secret_shared_prefs",
|
||||
masterKeyAlias,
|
||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||
@@ -45,38 +45,35 @@ fun getSharedPreferences() : SharedPreferences{
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pair
|
||||
* 1st => true if key is created now & false if key is created previously
|
||||
*
|
||||
*/
|
||||
fun getOrCreateBackupKey(reset: Boolean = false): Pair<Boolean,String>{
|
||||
fun getOrCreateBackupKey(reset: Boolean = false): Pair<Boolean, String> {
|
||||
val sp = getSharedPreferences()
|
||||
|
||||
return if (sp.contains(BACKUP_KEY) && reset.not()){
|
||||
Pair(false,sp.getString(BACKUP_KEY,"") ?: "")
|
||||
}else{
|
||||
return if (sp.contains(BACKUP_KEY) && reset.not()) {
|
||||
Pair(false, sp.getString(BACKUP_KEY, "") ?: "")
|
||||
} else {
|
||||
val randomKey = getRandomString(16)
|
||||
sp.edit {
|
||||
putString(BACKUP_KEY, randomKey)
|
||||
}
|
||||
Pair(true,randomKey)
|
||||
Pair(true, randomKey)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun setBackupDirectory(string: String){
|
||||
fun setBackupDirectory(string: String) {
|
||||
getSharedPreferences().edit {
|
||||
putString(BACKUP_DIRECTORY, string)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getBackupDirectory(): String{
|
||||
fun getBackupDirectory(): String {
|
||||
val sp = getSharedPreferences()
|
||||
return sp.getString(BACKUP_DIRECTORY,"") ?: ""
|
||||
return sp.getString(BACKUP_DIRECTORY, "") ?: ""
|
||||
}
|
||||
|
||||
private const val BACKUP_KEY = "backup_key"
|
||||
private const val BACKUP_DIRECTORY = "backup_directory"
|
||||
private const val BACKUP_DIRECTORY = "backup_directory"
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.yogeshpaliyal.keypass.utils
|
||||
|
||||
import java.util.*
|
||||
|
||||
|
||||
/*
|
||||
* @author Yogesh Paliyal
|
||||
* techpaliyal@gmail.com
|
||||
@@ -10,4 +9,4 @@ import java.util.*
|
||||
* created on 22-01-2021 23:14
|
||||
*/
|
||||
|
||||
fun getRandomString()= UUID.randomUUID().toString()
|
||||
fun getRandomString() = UUID.randomUUID().toString()
|
||||
|
||||
@@ -17,19 +17,8 @@
|
||||
package com.yogeshpaliyal.keypass.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Bitmap.Config.ARGB_8888
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.annotation.Px
|
||||
import androidx.core.graphics.applyCanvas
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.forEach
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun TextView.setTextAppearanceCompat(context: Context, resId: Int) {
|
||||
|
||||
@@ -32,4 +32,3 @@ fun <T : ViewModel> ViewModelStoreOwner.initViewModel(viewModel: Class<T>): T =
|
||||
this,
|
||||
ViewModelFactory()
|
||||
).get(viewModel)
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package com.yogeshpaliyal.keypass
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
@@ -14,4 +13,4 @@ class ExampleUnitTest {
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
29
build.gradle
29
build.gradle
@@ -21,6 +21,9 @@ buildscript {
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
id 'com.diffplug.spotless' version '5.10.2'
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
@@ -31,6 +34,30 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
/*task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
subprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
apply plugin: 'com.diffplug.spotless'
|
||||
spotless {
|
||||
kotlin {
|
||||
target '**/*.kt'
|
||||
targetExclude("$buildDir/**/*.kt")
|
||||
targetExclude('bin/**/*.kt')
|
||||
|
||||
java.util.HashMap<String, String> map = new HashMap<>();
|
||||
map.put("disabled_rules","no-wildcard-imports")
|
||||
ktlint("0.40.0").userData(map)
|
||||
// licenseHeaderFile rootProject.file('spotless/copyright.kt')
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user