Prepare R1.0
This commit is contained in:
parent
baee52c69b
commit
f14929cdf6
@ -41,8 +41,6 @@ dependencies {
|
||||
implementation 'androidx.core:core-ktx:1.12.0'
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.7'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.7.7'
|
||||
implementation 'androidx.camera:camera-camera2:1.3.2'
|
||||
implementation 'androidx.camera:camera-lifecycle:1.3.2'
|
||||
implementation 'androidx.camera:camera-view:1.3.2'
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
@ -21,27 +22,13 @@
|
||||
|
||||
<receiver
|
||||
android:name=".pluginSDK.PluginAccessBroadcastReceiver"
|
||||
android:exported="true">
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="keepass2android.ACTION_TRIGGER_REQUEST_ACCESS" />
|
||||
<action android:name="keepass2android.ACTION_RECEIVE_ACCESS" />
|
||||
<action android:name="keepass2android.ACTION_REVOKE_ACCESS" />
|
||||
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".pluginSDK.PluginActionBroadcastReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="keepass2android.ACTION_OPEN_ENTRY" />
|
||||
<action android:name="keepass2android.ACTION_ENTRY_OUTPUT_MODIFIED" />
|
||||
<action android:name="keepass2android.ACTION_CLOSE_ENTRY_VIEW" />
|
||||
<action android:name="keepass2android.ACTION_ADD_ENTRY_ACTION" />
|
||||
|
||||
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
</application>
|
||||
</manifest>
|
@ -9,8 +9,12 @@ import androidx.activity.addCallback
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import net.helcel.fidelity.R
|
||||
import net.helcel.fidelity.activity.fragment.Launcher
|
||||
import net.helcel.fidelity.activity.fragment.ViewEntry
|
||||
import net.helcel.fidelity.databinding.ActMainBinding
|
||||
import net.helcel.fidelity.pluginSDK.Kp2aControl.getEntryFieldsFromIntent
|
||||
import net.helcel.fidelity.tools.CacheManager
|
||||
import net.helcel.fidelity.tools.KeepassWrapper.bundleCreate
|
||||
import net.helcel.fidelity.tools.KeepassWrapper.entryExtract
|
||||
|
||||
@SuppressLint("SourceLockedOrientationActivity")
|
||||
class MainActivity : AppCompatActivity() {
|
||||
@ -38,7 +42,9 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
if (savedInstanceState == null)
|
||||
if (intent.extras != null)
|
||||
loadViewEntry()
|
||||
else if (savedInstanceState == null)
|
||||
loadLauncher()
|
||||
}
|
||||
|
||||
@ -47,5 +53,14 @@ class MainActivity : AppCompatActivity() {
|
||||
.replace(R.id.container, Launcher())
|
||||
.commit()
|
||||
}
|
||||
|
||||
private fun loadViewEntry() {
|
||||
val viewEntry = ViewEntry()
|
||||
val data = getEntryFieldsFromIntent(intent)
|
||||
viewEntry.arguments = bundleCreate(entryExtract(data))
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, viewEntry)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,6 @@ class FidelityListAdapter(
|
||||
|
||||
inner class FidelityViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
|
||||
fun bind(triple: Triple<String?, String?, String?>) {
|
||||
val text = "${triple.first}"
|
||||
binding.textView.text = text
|
||||
|
@ -7,9 +7,11 @@ import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.zxing.FormatException
|
||||
import net.helcel.fidelity.R
|
||||
import net.helcel.fidelity.databinding.FragCreateEntryBinding
|
||||
@ -34,7 +36,7 @@ class CreateEntry : Fragment() {
|
||||
startViewEntry(r.first, r.second, r.third)
|
||||
}
|
||||
|
||||
private var isValid: Boolean = false
|
||||
private var isValidBarcode: Boolean = false
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
@ -51,21 +53,89 @@ class CreateEntry : Fragment() {
|
||||
binding.editTextCode.setText(res.second)
|
||||
binding.editTextFormat.setText(res.third, false)
|
||||
|
||||
val changeListener = {
|
||||
isValid = false
|
||||
binding.editTextCode.addTextChangedListener { changeListener() }
|
||||
binding.editTextFormat.addTextChangedListener { changeListener() }
|
||||
binding.editTextFormat.addTextChangedListener { binding.editTextFormat.error = null }
|
||||
binding.btnSave.setOnClickListener { submit() }
|
||||
|
||||
binding.editTextTitle.onDone { submit() }
|
||||
binding.editTextCode.onDone { submit() }
|
||||
|
||||
|
||||
updatePreview()
|
||||
return binding.root
|
||||
}
|
||||
|
||||
private fun updatePreview() {
|
||||
try {
|
||||
val barcodeBitmap = generateBarcode(
|
||||
binding.editTextCode.text.toString(),
|
||||
binding.editTextFormat.text.toString(),
|
||||
600
|
||||
)
|
||||
binding.imageViewPreview.setImageBitmap(barcodeBitmap)
|
||||
isValidBarcode = true
|
||||
} catch (e: FormatException) {
|
||||
binding.imageViewPreview.setImageBitmap(null)
|
||||
binding.editTextCode.error = "Invalid format"
|
||||
} catch (e: IllegalArgumentException) {
|
||||
binding.imageViewPreview.setImageBitmap(null)
|
||||
binding.editTextCode.error = e.message
|
||||
} catch (e: Exception) {
|
||||
binding.imageViewPreview.setImageBitmap(null)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValidForm(): Boolean {
|
||||
var valid = true
|
||||
if (binding.editTextFormat.text.isNullOrEmpty()) {
|
||||
valid = false
|
||||
binding.editTextFormat.error = "Format cannot be empty"
|
||||
}
|
||||
if (binding.editTextCode.text.isNullOrEmpty()) {
|
||||
valid = false
|
||||
binding.editTextCode.error = "Code cannot be empty"
|
||||
}
|
||||
if (binding.editTextTitle.text.isNullOrEmpty()) {
|
||||
valid = false
|
||||
binding.editTextTitle.error = "Title cannot be empty"
|
||||
}
|
||||
return valid
|
||||
}
|
||||
|
||||
|
||||
private fun startViewEntry(title: String?, code: String?, fmt: String?) {
|
||||
val viewEntryFragment = ViewEntry()
|
||||
viewEntryFragment.arguments = KeepassWrapper.bundleCreate(title, code, fmt)
|
||||
|
||||
requireActivity().supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, viewEntryFragment).commit()
|
||||
}
|
||||
|
||||
|
||||
private fun changeListener() {
|
||||
isValidBarcode = false
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
handler.postDelayed({
|
||||
updatePreview()
|
||||
}, DEBOUNCE_DELAY)
|
||||
}
|
||||
|
||||
binding.editTextCode.addTextChangedListener { changeListener() }
|
||||
binding.editTextFormat.addTextChangedListener { changeListener() }
|
||||
binding.editTextFormat.addTextChangedListener { binding.editTextFormat.error = null }
|
||||
binding.btnSave.setOnClickListener {
|
||||
if (!isValid() || !isValid) {
|
||||
ErrorToaster.formIncomplete(requireActivity())
|
||||
|
||||
private fun TextInputEditText.onDone(callback: () -> Unit) {
|
||||
setOnEditorActionListener { _, actionId, _ ->
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
callback.invoke()
|
||||
return@setOnEditorActionListener true
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun submit() {
|
||||
if (!isValidForm() || !isValidBarcode) {
|
||||
ErrorToaster.formIncomplete(context)
|
||||
} else {
|
||||
val kpEntry = KeepassWrapper.entryCreate(
|
||||
this,
|
||||
@ -82,60 +152,11 @@ class CreateEntry : Fragment() {
|
||||
)
|
||||
)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
ErrorToaster.noKP2AFound(requireActivity())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updatePreview()
|
||||
return binding.root
|
||||
}
|
||||
|
||||
private fun updatePreview() {
|
||||
try {
|
||||
val barcodeBitmap = generateBarcode(
|
||||
binding.editTextCode.text.toString(),
|
||||
binding.editTextFormat.text.toString(),
|
||||
600
|
||||
)
|
||||
binding.imageViewPreview.setImageBitmap(barcodeBitmap)
|
||||
isValid = true
|
||||
} catch (e: FormatException) {
|
||||
binding.imageViewPreview.setImageBitmap(null)
|
||||
binding.editTextCode.error = "Invalid format"
|
||||
} catch (e: IllegalArgumentException) {
|
||||
binding.imageViewPreview.setImageBitmap(null)
|
||||
binding.editTextCode.error = e.message
|
||||
ErrorToaster.noKP2AFound(context)
|
||||
} catch (e: Exception) {
|
||||
binding.imageViewPreview.setImageBitmap(null)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValid(): Boolean {
|
||||
var valid = true
|
||||
if (binding.editTextTitle.text.isNullOrEmpty()) {
|
||||
valid = false
|
||||
binding.editTextTitle.error = "Title cannot be empty"
|
||||
}
|
||||
if (binding.editTextCode.text.isNullOrEmpty()) {
|
||||
valid = false
|
||||
binding.editTextCode.error = "Code cannot be empty"
|
||||
}
|
||||
if (binding.editTextFormat.text.isNullOrEmpty()) {
|
||||
valid = false
|
||||
binding.editTextFormat.error = "Format cannot be empty"
|
||||
}
|
||||
return valid
|
||||
}
|
||||
|
||||
|
||||
private fun startViewEntry(title: String?, code: String?, fmt: String?) {
|
||||
val viewEntryFragment = ViewEntry()
|
||||
viewEntryFragment.arguments = KeepassWrapper.bundleCreate(title, code, fmt)
|
||||
|
||||
requireActivity().supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.container, viewEntryFragment).commit()
|
||||
}
|
||||
|
||||
}
|
@ -6,9 +6,6 @@ import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
|
||||
|
||||
class PluginAccessException(msg: String) : Exception(msg)
|
||||
|
||||
|
||||
object AccessManager {
|
||||
private const val PREF_KEY_SCOPE = "scope"
|
||||
private const val PREF_KEY_TOKEN = "token"
|
||||
@ -94,12 +91,4 @@ object AccessManager {
|
||||
hostPrefs.edit().remove(hostPackage).apply()
|
||||
}
|
||||
}
|
||||
|
||||
fun getAccessToken(
|
||||
context: Context, hostPackage: String?,
|
||||
scopes: ArrayList<String?>
|
||||
): String {
|
||||
return tryGetAccessToken(context, hostPackage, scopes)
|
||||
?: throw PluginAccessException(hostPackage + scopes)
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package net.helcel.fidelity.pluginSDK
|
||||
|
||||
@Suppress("unused")
|
||||
object KeepassDef {
|
||||
var TitleField: String = "Title"
|
||||
var UserNameField: String = "UserName"
|
||||
var PasswordField: String = "Password"
|
||||
var UrlField: String = "URL"
|
||||
var NotesField: String = "Notes"
|
||||
}
|
||||
|
@ -32,10 +32,10 @@ object Kp2aControl {
|
||||
fun getEntryFieldsFromIntent(intent: Intent?): HashMap<String, String> {
|
||||
val res = HashMap<String, String>()
|
||||
try {
|
||||
val json = JSONObject(intent?.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA)!!)
|
||||
val iter = json.keys()
|
||||
while (iter.hasNext()) {
|
||||
val key = iter.next()
|
||||
val json = JSONObject(intent?.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA) ?: "")
|
||||
val itr = json.keys()
|
||||
while (itr.hasNext()) {
|
||||
val key = itr.next()
|
||||
val value = json[key].toString()
|
||||
res[key] = value
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ class PluginAccessBroadcastReceiver : BroadcastReceiver() {
|
||||
Strings.ACTION_TRIGGER_REQUEST_ACCESS -> requestAccess(ctx, intent)
|
||||
Strings.ACTION_RECEIVE_ACCESS -> receiveAccess(ctx, intent)
|
||||
Strings.ACTION_REVOKE_ACCESS -> revokeAccess(ctx, intent)
|
||||
else -> println(action)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,8 +46,6 @@ class PluginAccessBroadcastReceiver : BroadcastReceiver() {
|
||||
private val scopes: ArrayList<String?> = ArrayList(
|
||||
listOf(
|
||||
Strings.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE,
|
||||
Strings.SCOPE_DATABASE_ACTIONS,
|
||||
Strings.SCOPE_CURRENT_ENTRY,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -1,226 +0,0 @@
|
||||
package net.helcel.fidelity.pluginSDK
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
||||
class PluginActionBroadcastReceiver : BroadcastReceiver() {
|
||||
open class PluginActionBase
|
||||
(var context: Context, protected var _intent: Intent) {
|
||||
val hostPackage: String?
|
||||
get() = _intent.getStringExtra(Strings.EXTRA_SENDER)
|
||||
}
|
||||
|
||||
open class PluginEntryActionBase(context: Context, intent: Intent) :
|
||||
PluginActionBase(context, intent) {
|
||||
protected val entryFieldsFromIntent: HashMap<String, String>
|
||||
get() {
|
||||
val res = HashMap<String, String>()
|
||||
try {
|
||||
val json =
|
||||
JSONObject(_intent.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA) ?: "")
|
||||
val iter = json.keys()
|
||||
while (iter.hasNext()) {
|
||||
val key = iter.next()
|
||||
val value = json[key].toString()
|
||||
res[key] = value
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
protected val protectedFieldsListFromIntent: Array<String?>?
|
||||
get() {
|
||||
try {
|
||||
val json =
|
||||
JSONArray(_intent.getStringExtra(Strings.EXTRA_PROTECTED_FIELDS_LIST))
|
||||
val res = arrayOfNulls<String>(json.length())
|
||||
for (i in 0 until json.length()) res[i] = json.getString(i)
|
||||
return res
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open val entryId: String?
|
||||
get() = _intent.getStringExtra(Strings.EXTRA_ENTRY_ID)
|
||||
|
||||
|
||||
fun setEntryField(fieldId: String?, fieldValue: String?, isProtected: Boolean) {
|
||||
val i = Intent(Strings.ACTION_SET_ENTRY_FIELD)
|
||||
val scope = ArrayList<String?>()
|
||||
scope.add(Strings.SCOPE_CURRENT_ENTRY)
|
||||
i.putExtra(
|
||||
Strings.EXTRA_ACCESS_TOKEN, AccessManager.getAccessToken(
|
||||
context, hostPackage, scope
|
||||
)
|
||||
)
|
||||
i.setPackage(hostPackage)
|
||||
i.putExtra(Strings.EXTRA_SENDER, context.packageName)
|
||||
i.putExtra(Strings.EXTRA_FIELD_VALUE, fieldValue)
|
||||
i.putExtra(Strings.EXTRA_ENTRY_ID, entryId)
|
||||
i.putExtra(Strings.EXTRA_FIELD_ID, fieldId)
|
||||
i.putExtra(Strings.EXTRA_FIELD_PROTECTED, isProtected)
|
||||
|
||||
context.sendBroadcast(i)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ActionSelectedAction(ctx: Context, intent: Intent) :
|
||||
PluginEntryActionBase(ctx, intent) {
|
||||
val actionData: Bundle?
|
||||
/**
|
||||
*
|
||||
* @return the Bundle associated with the action. This bundle can be set in OpenEntry.add(Entry)FieldAction
|
||||
*/
|
||||
get() = _intent.getBundleExtra(Strings.EXTRA_ACTION_DATA)
|
||||
|
||||
private val fieldId: String?
|
||||
/**
|
||||
*
|
||||
* @return the field id which was selected. null if an entry action (in the options menu) was selected.
|
||||
*/
|
||||
get() = _intent.getStringExtra(Strings.EXTRA_FIELD_ID)
|
||||
|
||||
val isEntryAction: Boolean
|
||||
/**
|
||||
*
|
||||
* @return true if an entry action, i.e. an option from the options menu, was selected. False if an option
|
||||
* in a popup menu for a certain field was selected.
|
||||
*/
|
||||
get() = fieldId == null
|
||||
|
||||
val entryFields: HashMap<String, String>
|
||||
/**
|
||||
*
|
||||
* @return a hashmap containing the entry fields in key/value form
|
||||
*/
|
||||
get() = entryFieldsFromIntent
|
||||
|
||||
val protectedFieldsList: Array<String?>?
|
||||
/**
|
||||
*
|
||||
* @return an array with the keys of all protected fields in the entry
|
||||
*/
|
||||
get() = protectedFieldsListFromIntent
|
||||
}
|
||||
|
||||
private inner class CloseEntryViewAction(context: Context, intent: Intent) :
|
||||
PluginEntryActionBase(context, intent) {
|
||||
override val entryId: String?
|
||||
get() = _intent.getStringExtra(Strings.EXTRA_ENTRY_ID)
|
||||
}
|
||||
|
||||
private open inner class OpenEntryAction(context: Context, intent: Intent) :
|
||||
PluginEntryActionBase(context, intent) {
|
||||
val entryFields: HashMap<String, String>
|
||||
get() = entryFieldsFromIntent
|
||||
|
||||
val protectedFieldsList: Array<String?>?
|
||||
/**
|
||||
*
|
||||
* @return an array with the keys of all protected fields in the entry
|
||||
*/
|
||||
get() = protectedFieldsListFromIntent
|
||||
|
||||
fun addEntryAction(
|
||||
actionDisplayText: String?,
|
||||
actionIconResourceId: Int,
|
||||
actionData: Bundle?
|
||||
) {
|
||||
addEntryFieldAction(null, null, actionDisplayText, actionIconResourceId, actionData)
|
||||
}
|
||||
|
||||
fun addEntryFieldAction(
|
||||
actionId: String?,
|
||||
fieldId: String?,
|
||||
actionDisplayText: String?,
|
||||
actionIconResourceId: Int,
|
||||
actionData: Bundle?
|
||||
) {
|
||||
val i = Intent(Strings.ACTION_ADD_ENTRY_ACTION)
|
||||
val scope = ArrayList<String?>()
|
||||
scope.add(Strings.SCOPE_CURRENT_ENTRY)
|
||||
i.putExtra(
|
||||
Strings.EXTRA_ACCESS_TOKEN, AccessManager.getAccessToken(
|
||||
context, hostPackage!!, scope
|
||||
)
|
||||
)
|
||||
i.setPackage(hostPackage)
|
||||
i.putExtra(Strings.EXTRA_SENDER, context.packageName)
|
||||
i.putExtra(Strings.EXTRA_ACTION_DATA, actionData)
|
||||
i.putExtra(Strings.EXTRA_ACTION_DISPLAY_TEXT, actionDisplayText)
|
||||
i.putExtra(Strings.EXTRA_ACTION_ICON_RES_ID, actionIconResourceId)
|
||||
i.putExtra(Strings.EXTRA_ENTRY_ID, entryId)
|
||||
i.putExtra(Strings.EXTRA_FIELD_ID, fieldId)
|
||||
i.putExtra(Strings.EXTRA_ACTION_ID, actionId)
|
||||
|
||||
context.sendBroadcast(i)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class DatabaseAction(context: Context, intent: Intent) :
|
||||
PluginActionBase(context, intent) {
|
||||
val fileDisplayName: String?
|
||||
get() = _intent.getStringExtra(Strings.EXTRA_DATABASE_FILE_DISPLAYNAME)
|
||||
|
||||
val filePath: String?
|
||||
get() = _intent.getStringExtra(Strings.EXTRA_DATABASE_FILEPATH)
|
||||
|
||||
val action: String?
|
||||
get() = _intent.action
|
||||
}
|
||||
|
||||
//EntryOutputModified is very similar to OpenEntry because it receives the same
|
||||
//data (+ the field id which was modified)
|
||||
private inner class EntryOutputModifiedAction(context: Context, intent: Intent) :
|
||||
OpenEntryAction(context, intent) {
|
||||
val modifiedFieldId: String?
|
||||
get() = _intent.getStringExtra(Strings.EXTRA_FIELD_ID)
|
||||
}
|
||||
|
||||
override fun onReceive(ctx: Context, intent: Intent) {
|
||||
val action = intent.action ?: return
|
||||
Log.d(
|
||||
"KP2A.pluginsdk",
|
||||
"received broadcast in PluginActionBroadcastReceiver with action=$action"
|
||||
)
|
||||
println(action)
|
||||
|
||||
when (action) {
|
||||
Strings.ACTION_OPEN_ENTRY -> openEntry(OpenEntryAction(ctx, intent))
|
||||
Strings.ACTION_CLOSE_ENTRY_VIEW -> closeEntryView(CloseEntryViewAction(ctx, intent))
|
||||
Strings.ACTION_ENTRY_ACTION_SELECTED ->
|
||||
actionSelected(ActionSelectedAction(ctx, intent))
|
||||
|
||||
Strings.ACTION_ENTRY_OUTPUT_MODIFIED ->
|
||||
entryOutputModified(EntryOutputModifiedAction(ctx, intent))
|
||||
|
||||
Strings.ACTION_LOCK_DATABASE -> dbAction(DatabaseAction(ctx, intent))
|
||||
Strings.ACTION_UNLOCK_DATABASE -> dbAction(DatabaseAction(ctx, intent))
|
||||
Strings.ACTION_OPEN_DATABASE -> dbAction(DatabaseAction(ctx, intent))
|
||||
Strings.ACTION_CLOSE_DATABASE -> dbAction(DatabaseAction(ctx, intent))
|
||||
|
||||
else -> println(action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun closeEntryView(closeEntryView: CloseEntryViewAction?) {}
|
||||
|
||||
private fun actionSelected(actionSelected: ActionSelectedAction?) {}
|
||||
|
||||
private fun openEntry(oe: OpenEntryAction?) {}
|
||||
|
||||
private fun entryOutputModified(eom: EntryOutputModifiedAction?) {}
|
||||
|
||||
private fun dbAction(db: DatabaseAction?) {}
|
||||
}
|
@ -1,176 +1,30 @@
|
||||
package net.helcel.fidelity.pluginSDK
|
||||
|
||||
@Suppress("unused")
|
||||
object Strings {
|
||||
/**
|
||||
* Plugin is notified about actions like open/close/update a database.
|
||||
*/
|
||||
|
||||
const val SCOPE_DATABASE_ACTIONS = "keepass2android.SCOPE_DATABASE_ACTIONS"
|
||||
|
||||
/**
|
||||
* Plugin is notified when an entry is opened.
|
||||
*/
|
||||
const val SCOPE_CURRENT_ENTRY = "keepass2android.SCOPE_CURRENT_ENTRY"
|
||||
|
||||
/**
|
||||
* Plugin may query credentials for its own package
|
||||
*/
|
||||
const val SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE =
|
||||
"keepass2android.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE"
|
||||
|
||||
/**
|
||||
* Extra key to transfer a (json serialized) list of scopes
|
||||
*/
|
||||
const val EXTRA_SCOPES = "keepass2android.EXTRA_SCOPES"
|
||||
|
||||
|
||||
const val EXTRA_PLUGIN_PACKAGE = "keepass2android.EXTRA_PLUGIN_PACKAGE"
|
||||
|
||||
/**
|
||||
* Extra key for sending the package name of the sender of a broadcast.
|
||||
* Should be set in every broadcast.
|
||||
*/
|
||||
const val EXTRA_SENDER = "keepass2android.EXTRA_SENDER"
|
||||
|
||||
/**
|
||||
* Extra key for sending a request token. The request token is passed from
|
||||
* KP2A to the plugin. It's used in the authorization process.
|
||||
*/
|
||||
const val EXTRA_REQUEST_TOKEN = "keepass2android.EXTRA_REQUEST_TOKEN"
|
||||
|
||||
/**
|
||||
* Action to start KP2A with an AppTask
|
||||
*/
|
||||
const val ACTION_START_WITH_TASK = "keepass2android.ACTION_START_WITH_TASK"
|
||||
|
||||
/**
|
||||
* Action sent from KP2A to the plugin to indicate that the plugin should request
|
||||
* access (sending it's scopes)
|
||||
*/
|
||||
const val ACTION_TRIGGER_REQUEST_ACCESS = "keepass2android.ACTION_TRIGGER_REQUEST_ACCESS"
|
||||
|
||||
/**
|
||||
* Action sent from the plugin to KP2A including the scopes.
|
||||
*/
|
||||
const val ACTION_REQUEST_ACCESS = "keepass2android.ACTION_REQUEST_ACCESS"
|
||||
|
||||
/**
|
||||
* Action sent from the KP2A to the plugin when the user grants access.
|
||||
* Will contain an access token.
|
||||
*/
|
||||
const val ACTION_RECEIVE_ACCESS = "keepass2android.ACTION_RECEIVE_ACCESS"
|
||||
|
||||
/**
|
||||
* Action sent from KP2A to the plugin to indicate that access is not or no longer valid.
|
||||
*/
|
||||
const val ACTION_REVOKE_ACCESS = "keepass2android.ACTION_REVOKE_ACCESS"
|
||||
|
||||
|
||||
/**
|
||||
* Action for startActivity(). Opens an activity in the Plugin Host to edit the plugin settings (i.e. enable it)
|
||||
*/
|
||||
const val ACTION_EDIT_PLUGIN_SETTINGS = "keepass2android.ACTION_EDIT_PLUGIN_SETTINGS"
|
||||
|
||||
/**
|
||||
* Action sent from KP2A to the plugin to indicate that an entry was opened.
|
||||
* The Intent contains the full entry data.
|
||||
*/
|
||||
const val ACTION_OPEN_ENTRY = "keepass2android.ACTION_OPEN_ENTRY"
|
||||
|
||||
/**
|
||||
* Action sent from KP2A to the plugin to indicate that an entry output field was modified/added.
|
||||
* The Intent contains the full new entry data.
|
||||
*/
|
||||
const val ACTION_ENTRY_OUTPUT_MODIFIED = "keepass2android.ACTION_ENTRY_OUTPUT_MODIFIED"
|
||||
|
||||
/**
|
||||
* Action sent from KP2A to the plugin to indicate that an entry activity was closed.
|
||||
*/
|
||||
const val ACTION_CLOSE_ENTRY_VIEW = "keepass2android.ACTION_CLOSE_ENTRY_VIEW"
|
||||
|
||||
/**
|
||||
* Extra key for a string containing the GUID of the entry.
|
||||
*/
|
||||
const val EXTRA_ENTRY_ID = "keepass2android.EXTRA_ENTRY_DATA"
|
||||
|
||||
|
||||
/**
|
||||
* Json serialized list of fields, transformed using the database context (i.e. placeholders are replaced already)
|
||||
*/
|
||||
const val EXTRA_ENTRY_OUTPUT_DATA = "keepass2android.EXTRA_ENTRY_OUTPUT_DATA"
|
||||
|
||||
/**
|
||||
* Json serialized lisf of field keys, specifying which field of the EXTRA_ENTRY_OUTPUT_DATA is protected.
|
||||
*/
|
||||
const val EXTRA_PROTECTED_FIELDS_LIST = "keepass2android.EXTRA_PROTECTED_FIELDS_LIST"
|
||||
|
||||
|
||||
/**
|
||||
* Extra key for passing the access token (both ways)
|
||||
*/
|
||||
const val EXTRA_ACCESS_TOKEN = "keepass2android.EXTRA_ACCESS_TOKEN"
|
||||
|
||||
/**
|
||||
* Action for an intent from the plugin to KP2A to add menu options regarding the currently open entry.
|
||||
* Requires SCOPE_CURRENT_ENTRY.
|
||||
*/
|
||||
const val ACTION_ADD_ENTRY_ACTION = "keepass2android.ACTION_ADD_ENTRY_ACTION"
|
||||
|
||||
const val EXTRA_ACTION_DISPLAY_TEXT = "keepass2android.EXTRA_ACTION_DISPLAY_TEXT"
|
||||
const val EXTRA_ACTION_ICON_RES_ID = "keepass2android.EXTRA_ACTION_ICON_RES_ID"
|
||||
|
||||
const val EXTRA_FIELD_ID = "keepass2android.EXTRA_FIELD_ID"
|
||||
|
||||
/**
|
||||
* Used to pass an id for the action. Each actionId may occur only once per field, otherwise the previous
|
||||
* action with same id is replaced by the new action.
|
||||
*/
|
||||
const val EXTRA_ACTION_ID = "keepass2android.EXTRA_ACTION_ID"
|
||||
|
||||
/** Extra for ACTION_ADD_ENTRY_ACTION and ACTION_ENTRY_ACTION_SELECTED to pass data specifying the action parameters.*/
|
||||
const val EXTRA_ACTION_DATA = "keepass2android.EXTRA_ACTION_DATA"
|
||||
|
||||
/**
|
||||
* Action for an intent from KP2A to the plugin when an action added with ACTION_ADD_ENTRY_ACTION was selected by the user.
|
||||
*
|
||||
*/
|
||||
const val ACTION_ENTRY_ACTION_SELECTED = "keepass2android.ACTION_ENTRY_ACTION_SELECTED"
|
||||
|
||||
/**
|
||||
* Extra key for the string which is used to query the credentials. This should be either a URL for
|
||||
* a web login (google.com or a full URI) or something in the form "androidapp://com.my.package"
|
||||
*/
|
||||
const val EXTRA_QUERY_STRING = "keepass2android.EXTRA_QUERY_STRING"
|
||||
|
||||
/**
|
||||
* Action when plugin wants to query credentials for its own package
|
||||
*/
|
||||
const val ACTION_QUERY_CREDENTIALS_FOR_OWN_PACKAGE =
|
||||
"keepass2android.ACTION_QUERY_CREDENTIALS_FOR_OWN_PACKAGE"
|
||||
|
||||
/**
|
||||
* Action for an intent from the plugin to KP2A to set (i.e. add or update) a field in the entry.
|
||||
* May be used to update existing or add new fields at any time while the entry is opened.
|
||||
*/
|
||||
const val ACTION_SET_ENTRY_FIELD = "keepass2android.ACTION_SET_ENTRY_FIELD"
|
||||
|
||||
/** Actions for an intent from KP2A to the plugin to inform that a database was opened, closed, quicklocked or quickunlocked.*/
|
||||
const val ACTION_OPEN_DATABASE = "keepass2android.ACTION_OPEN_DATABASE"
|
||||
const val ACTION_CLOSE_DATABASE = "keepass2android.ACTION_CLOSE_DATABASE"
|
||||
const val ACTION_LOCK_DATABASE = "keepass2android.ACTION_LOCK_DATABASE"
|
||||
const val ACTION_UNLOCK_DATABASE = "keepass2android.ACTION_UNLOCK_DATABASE"
|
||||
|
||||
/** Extra for ACTION_OPEN_DATABASE and ACTION_CLOSE_DATABASE containing a filepath which is used
|
||||
* by KP2A internally to identify the file. Use only where necessary, might contain credentials
|
||||
* for accessing the file (on remote storage).*/
|
||||
const val EXTRA_DATABASE_FILEPATH = "keepass2android.EXTRA_DATABASE_FILEPATH"
|
||||
|
||||
/** Extra for ACTION_OPEN_DATABASE and ACTION_CLOSE_DATABASE containing a filepath which can be
|
||||
* displayed to the user.*/
|
||||
const val EXTRA_DATABASE_FILE_DISPLAYNAME = "keepass2android.EXTRA_DATABASE_FILE_DISPLAYNAME"
|
||||
|
||||
|
||||
const val EXTRA_FIELD_VALUE = "keepass2android.EXTRA_FIELD_VALUE"
|
||||
const val EXTRA_FIELD_PROTECTED = "keepass2android.EXTRA_FIELD_PROTECTED"
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,22 +1,23 @@
|
||||
package net.helcel.fidelity.tools
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
|
||||
object ErrorToaster {
|
||||
private fun helper(activity: Activity, message: String, length: Int) {
|
||||
private fun helper(activity: Context?, message: String, length: Int) {
|
||||
if (activity != null)
|
||||
Toast.makeText(activity, message, length).show()
|
||||
}
|
||||
|
||||
fun noKP2AFound(activity: Activity) {
|
||||
fun noKP2AFound(activity: Context?) {
|
||||
helper(activity, "KeePass2Android Not Installed", Toast.LENGTH_LONG)
|
||||
}
|
||||
|
||||
fun formIncomplete(activity: Activity) {
|
||||
fun formIncomplete(activity: Context?) {
|
||||
helper(activity, "Form Incomplete", Toast.LENGTH_SHORT)
|
||||
}
|
||||
|
||||
fun invalidFormat(activity: Activity) {
|
||||
fun invalidFormat(activity: Context?) {
|
||||
helper(activity, "Invalid Format", Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
|
@ -42,12 +42,8 @@ object KeepassWrapper {
|
||||
callback: (HashMap<String, String>) -> Unit
|
||||
): ActivityResultLauncher<Intent> {
|
||||
return fragment.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||
|
||||
println(result.resultCode)
|
||||
println(result.data.toString())
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
val credentials = Kp2aControl.getEntryFieldsFromIntent(result.data)
|
||||
println(credentials.toList().toString())
|
||||
callback(credentials)
|
||||
}
|
||||
}
|
||||
@ -69,6 +65,10 @@ object KeepassWrapper {
|
||||
return data
|
||||
}
|
||||
|
||||
fun bundleCreate(triple: Triple<String?, String?, String?>): Bundle {
|
||||
return bundleCreate(triple.first, triple.second, triple.third)
|
||||
}
|
||||
|
||||
fun bundleExtract(data: Bundle?): Triple<String?, String?, String?> {
|
||||
return Triple(
|
||||
data?.getString("title"),
|
||||
|
@ -22,7 +22,11 @@
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editTextTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:minLines="1" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
@ -45,7 +49,11 @@
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/editTextCode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:minLines="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
@ -75,6 +83,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:focusable="false"
|
||||
android:inputType="none" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
@ -14,5 +14,5 @@ dependencyResolutionManagement {
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
rootProject.name = "BeenDroid"
|
||||
rootProject.name = "Fidelity"
|
||||
include ':app'
|
||||
|
Loading…
x
Reference in New Issue
Block a user