Completely revamp decrypted password screen (#817)

* Completely revamp decrypted password screen

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>

* update changelog

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>

Co-authored-by: Fabian Henneke <FabianHenneke@users.noreply.github.com>
This commit is contained in:
Harsh Shandilya
2020-05-31 13:42:31 +05:30
committed by GitHub
parent 523f2afc53
commit 5a34f444c2
10 changed files with 91 additions and 247 deletions

View File

@@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file.
## [Unreleased] ## [Unreleased]
### Added
- Completely revamped decypted password view
### Changed ### Changed
- **BREAKING**: Remove support for HOTP/TOTP secrets - Please use FIDO keys or a dedicated app like [Aegis](https://github.com/beemdevelopment/Aegis) or [andOTP](https://github.com/andOTP/andOTP). - **BREAKING**: Remove support for HOTP/TOTP secrets - Please use FIDO keys or a dedicated app like [Aegis](https://github.com/beemdevelopment/Aegis) or [andOTP](https://github.com/andOTP/andOTP).
- Reduce Autofill false positives on username fields by removing "name" from list of heuristic terms - Reduce Autofill false positives on username fields by removing "name" from list of heuristic terms

View File

@@ -4,7 +4,6 @@
*/ */
package com.zeapo.pwdstore.crypto package com.zeapo.pwdstore.crypto
import android.annotation.SuppressLint
import android.app.PendingIntent import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ClipData import android.content.ClipData
@@ -23,13 +22,9 @@ import android.text.format.DateUtils
import android.text.method.PasswordTransformationMethod import android.text.method.PasswordTransformationMethod
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.widget.doOnTextChanged import androidx.core.widget.doOnTextChanged
@@ -48,19 +43,15 @@ import com.zeapo.pwdstore.autofill.oreo.AutofillPreferences
import com.zeapo.pwdstore.autofill.oreo.DirectoryStructure import com.zeapo.pwdstore.autofill.oreo.DirectoryStructure
import com.zeapo.pwdstore.ui.dialogs.PasswordGeneratorDialogFragment import com.zeapo.pwdstore.ui.dialogs.PasswordGeneratorDialogFragment
import com.zeapo.pwdstore.ui.dialogs.XkPasswordGeneratorDialogFragment import com.zeapo.pwdstore.ui.dialogs.XkPasswordGeneratorDialogFragment
import kotlinx.android.synthetic.main.decrypt_layout.crypto_container_decrypt
import kotlinx.android.synthetic.main.decrypt_layout.crypto_copy_username
import kotlinx.android.synthetic.main.decrypt_layout.crypto_extra_show
import kotlinx.android.synthetic.main.decrypt_layout.crypto_extra_show_layout
import kotlinx.android.synthetic.main.decrypt_layout.crypto_extra_toggle_show
import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_category_decrypt import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_category_decrypt
import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_file import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_file
import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_last_changed import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_last_changed
import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_show import kotlinx.android.synthetic.main.decrypt_layout.extra_content
import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_show_label import kotlinx.android.synthetic.main.decrypt_layout.extra_content_container
import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_toggle_show import kotlinx.android.synthetic.main.decrypt_layout.password_text
import kotlinx.android.synthetic.main.decrypt_layout.crypto_username_show import kotlinx.android.synthetic.main.decrypt_layout.password_text_container
import kotlinx.android.synthetic.main.decrypt_layout.crypto_username_show_label import kotlinx.android.synthetic.main.decrypt_layout.username_text
import kotlinx.android.synthetic.main.decrypt_layout.username_text_container
import kotlinx.android.synthetic.main.encrypt_layout.crypto_extra_edit import kotlinx.android.synthetic.main.encrypt_layout.crypto_extra_edit
import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_category import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_category
import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_edit import kotlinx.android.synthetic.main.encrypt_layout.crypto_password_edit
@@ -119,7 +110,7 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
val settings: SharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) } val settings: SharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) }
private val keyIDs get() = _keyIDs private val keyIDs get() = _keyIDs
private var _keyIDs = emptySet<String>() private var _keyIDs = emptySet<String>()
private var mServiceConnection: OpenPgpServiceConnection? = null private var serviceConnection: OpenPgpServiceConnection? = null
private var delayTask: DelayShow? = null private var delayTask: DelayShow? = null
private val receiver = object : BroadcastReceiver() { private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
@@ -142,8 +133,8 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
startActivityForResult(intent, OPEN_PGP_BOUND) startActivityForResult(intent, OPEN_PGP_BOUND)
} else { } else {
// bind to service // bind to service
mServiceConnection = OpenPgpServiceConnection(this, providerPackageName, this) serviceConnection = OpenPgpServiceConnection(this, providerPackageName, this)
mServiceConnection?.bindToService() serviceConnection?.bindToService()
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
} }
@@ -156,12 +147,12 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
val clipboard = clipboard ?: return@setOnLongClickListener false val clipboard = clipboard ?: return@setOnLongClickListener false
val clip = ClipData.newPlainText("pgp_handler_result_pm", name) val clip = ClipData.newPlainText("pgp_handler_result_pm", name)
clipboard.setPrimaryClip(clip) clipboard.setPrimaryClip(clip)
showSnackbar(this.resources.getString(R.string.clipboard_username_toast_text)) showSnackbar(resources.getString(R.string.clipboard_copied_text))
true true
} }
crypto_password_last_changed.text = try { crypto_password_last_changed.text = try {
this.resources.getString(R.string.last_changed, lastChangedString) resources.getString(R.string.last_changed, lastChangedString)
} catch (e: RuntimeException) { } catch (e: RuntimeException) {
showSnackbar(getString(R.string.get_last_changed_failed)) showSnackbar(getString(R.string.get_last_changed_failed))
"" ""
@@ -277,7 +268,7 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
mServiceConnection?.unbindFromService() serviceConnection?.unbindFromService()
} }
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu?): Boolean {
@@ -354,7 +345,7 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
} }
private fun initOpenPgpApi() { private fun initOpenPgpApi() {
api = api ?: OpenPgpApi(this, mServiceConnection!!.service!!) api = api ?: OpenPgpApi(this, serviceConnection!!.service!!)
} }
private fun decryptAndVerify(receivedIntent: Intent? = null) { private fun decryptAndVerify(receivedIntent: Intent? = null) {
@@ -372,7 +363,7 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
val showPassword = settings.getBoolean("show_password", true) val showPassword = settings.getBoolean("show_password", true)
val showExtraContent = settings.getBoolean("show_extra_content", true) val showExtraContent = settings.getBoolean("show_extra_content", true)
crypto_container_decrypt.visibility = View.VISIBLE password_text_container.visibility = View.VISIBLE
val monoTypeface = Typeface.createFromAsset(assets, "fonts/sourcecodepro.ttf") val monoTypeface = Typeface.createFromAsset(assets, "fonts/sourcecodepro.ttf")
val entry = PasswordEntry(oStream) val entry = PasswordEntry(oStream)
@@ -385,61 +376,34 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
} }
if (entry.password.isEmpty()) { if (entry.password.isEmpty()) {
crypto_password_show.visibility = View.GONE password_text_container.visibility = View.GONE
crypto_password_show_label.visibility = View.GONE
} else { } else {
crypto_password_show.visibility = View.VISIBLE password_text_container.visibility = View.VISIBLE
crypto_password_show_label.visibility = View.VISIBLE password_text.setText(entry.password)
crypto_password_show.typeface = monoTypeface if (!showPassword) {
crypto_password_show.text = entry.password password_text.transformationMethod = PasswordTransformationMethod.getInstance()
} }
crypto_password_show.typeface = monoTypeface password_text_container.setOnClickListener { copyPasswordToClipBoard() }
crypto_password_show.text = entry.password password_text.setOnClickListener { copyPasswordToClipBoard() }
crypto_password_toggle_show.visibility = if (showPassword) View.GONE else View.VISIBLE
crypto_password_show.transformationMethod = if (showPassword) {
null
} else {
HoldToShowPasswordTransformation(
crypto_password_toggle_show,
Runnable { crypto_password_show.text = entry.password }
)
} }
if (entry.hasExtraContent()) { if (entry.hasExtraContent()) {
crypto_extra_show.typeface = monoTypeface extra_content_container.visibility = View.VISIBLE
crypto_extra_show.text = entry.extraContent extra_content.typeface = monoTypeface
extra_content.setText(entry.extraContentWithoutUsername)
if (showExtraContent) { if (!showExtraContent) {
crypto_extra_show_layout.visibility = View.VISIBLE extra_content.transformationMethod = PasswordTransformationMethod.getInstance()
crypto_extra_toggle_show.visibility = View.GONE
crypto_extra_show.transformationMethod = null
} else {
crypto_extra_show_layout.visibility = View.GONE
crypto_extra_toggle_show.visibility = View.VISIBLE
crypto_extra_toggle_show.setOnCheckedChangeListener { _, _ ->
crypto_extra_show.text = entry.extraContent
}
crypto_extra_show.transformationMethod = object : PasswordTransformationMethod() {
override fun getTransformation(source: CharSequence, view: View): CharSequence {
return if (crypto_extra_toggle_show.isChecked) source else super.getTransformation(source, view)
}
}
} }
extra_content_container.setOnClickListener { copyTextToClipboard(entry.extraContentWithoutUsername) }
extra_content.setOnClickListener { copyTextToClipboard(entry.extraContentWithoutUsername) }
if (entry.hasUsername()) { if (entry.hasUsername()) {
crypto_username_show.visibility = View.VISIBLE username_text.typeface = monoTypeface
crypto_username_show_label.visibility = View.VISIBLE username_text.setText(entry.username)
crypto_copy_username.visibility = View.VISIBLE username_text_container.setEndIconOnClickListener { copyTextToClipboard(entry.username!!) }
username_text_container.visibility = View.VISIBLE
crypto_copy_username.setOnClickListener { copyUsernameToClipBoard(entry.username!!) }
crypto_username_show.typeface = monoTypeface
crypto_username_show.text = entry.username
} else { } else {
crypto_username_show.visibility = View.GONE username_text_container.visibility = View.GONE
crypto_username_show_label.visibility = View.GONE
crypto_copy_username.visibility = View.GONE
} }
} }
@@ -657,47 +621,9 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
} }
} }
@SuppressLint("ClickableViewAccessibility")
private inner class HoldToShowPasswordTransformation constructor(button: Button, private val onToggle: Runnable) :
PasswordTransformationMethod(), View.OnTouchListener {
private var shown = false
init {
button.setOnTouchListener(this)
}
override fun getTransformation(charSequence: CharSequence, view: View): CharSequence {
return if (shown) charSequence else super.getTransformation("12345", view)
}
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
when (motionEvent.action) {
MotionEvent.ACTION_DOWN -> {
shown = true
onToggle.run()
}
MotionEvent.ACTION_UP -> {
shown = false
onToggle.run()
}
}
return false
}
}
private fun copyPasswordToClipBoard() { private fun copyPasswordToClipBoard() {
val clipboard = clipboard ?: return val clipboard = clipboard ?: return
var pass = passwordEntry?.password val pass = passwordEntry?.password
if (findViewById<TextView>(R.id.crypto_password_show) == null) {
if (editPass == null) {
return
} else {
pass = editPass
}
}
val clip = ClipData.newPlainText("pgp_handler_result_pm", pass) val clip = ClipData.newPlainText("pgp_handler_result_pm", pass)
clipboard.setPrimaryClip(clip) clipboard.setPrimaryClip(clip)
@@ -710,23 +636,20 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
if (clearAfter != 0) { if (clearAfter != 0) {
setTimer() setTimer()
showSnackbar(this.resources.getString(R.string.clipboard_password_toast_text, clearAfter)) showSnackbar(resources.getString(R.string.clipboard_password_toast_text, clearAfter))
} else { } else {
showSnackbar(this.resources.getString(R.string.clipboard_password_no_clear_toast_text)) showSnackbar(resources.getString(R.string.clipboard_password_no_clear_toast_text))
} }
} }
private fun copyUsernameToClipBoard(username: String) { private fun copyTextToClipboard(text: String) {
val clipboard = clipboard ?: return val clipboard = clipboard ?: return
val clip = ClipData.newPlainText("pgp_handler_result_pm", username) val clip = ClipData.newPlainText("pgp_handler_result_pm", text)
clipboard.setPrimaryClip(clip) clipboard.setPrimaryClip(clip)
showSnackbar(resources.getString(R.string.clipboard_username_toast_text)) showSnackbar(resources.getString(R.string.clipboard_copied_text))
} }
private fun shareAsPlaintext() { private fun shareAsPlaintext() {
if (findViewById<View>(R.id.share_password_as_plaintext) == null)
return
val sendIntent = Intent() val sendIntent = Intent()
sendIntent.action = Intent.ACTION_SEND sendIntent.action = Intent.ACTION_SEND
sendIntent.putExtra(Intent.EXTRA_TEXT, passwordEntry?.password) sendIntent.putExtra(Intent.EXTRA_TEXT, passwordEntry?.password)
@@ -800,25 +723,18 @@ class PgpActivity : AppCompatActivity(), OpenPgpServiceConnection.OnBound {
} catch (e: NumberFormatException) { } catch (e: NumberFormatException) {
45 45
} }
password_text_container?.visibility = View.VISIBLE
val container = findViewById<ConstraintLayout>(R.id.crypto_container_decrypt) if (extra_content?.text?.isNotEmpty() == true)
container?.visibility = View.VISIBLE extra_content_container?.visibility = View.VISIBLE
val extraText = findViewById<TextView>(R.id.crypto_extra_show)
if (extraText?.text?.isNotEmpty() == true)
findViewById<View>(R.id.crypto_extra_show_layout)?.visibility = View.VISIBLE
} }
fun doOnPostExecute() { fun doOnPostExecute() {
if (skip) return if (skip) return
if (crypto_password_show != null) { if (password_text != null) {
passwordEntry = null passwordEntry = null
crypto_password_show.text = "" extra_content_container.visibility = View.INVISIBLE
crypto_extra_show.text = "" password_text_container.visibility = View.INVISIBLE
crypto_extra_show_layout.visibility = View.INVISIBLE
crypto_container_decrypt.visibility = View.INVISIBLE
finish() finish()
} }
} }

View File

@@ -68,137 +68,68 @@
app:layout_constraintTop_toBottomOf="@id/crypto_password_last_changed" app:layout_constraintTop_toBottomOf="@id/crypto_password_last_changed"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<androidx.constraintlayout.widget.ConstraintLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/crypto_container_decrypt" android:id="@+id/password_text_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_vertical_margin" android:layout_marginTop="16dp"
android:visibility="invisible" android:hint="@string/password"
android:visibility="gone"
app:endIconMode="password_toggle"
app:layout_constraintTop_toBottomOf="@id/divider" app:layout_constraintTop_toBottomOf="@id/divider"
tools:visibility="visible"> tools:visibility="visible">
<androidx.appcompat.widget.AppCompatTextView <com.google.android.material.textfield.TextInputEditText
android:id="@+id/crypto_password_show_label" android:id="@+id/password_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/password"
android:textColor="?android:attr/textColor"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/crypto_password_show"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="fill"
android:gravity="bottom"
android:textColor="?android:attr/textColor"
android:typeface="monospace"
app:layout_constraintBaseline_toBaselineOf="@id/crypto_password_show_label"
app:layout_constraintStart_toEndOf="@id/crypto_password_show_label" />
<com.google.android.material.button.MaterialButton
android:id="@+id/crypto_password_toggle_show"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:editable="false"
android:text="@string/show_password" android:fontFamily="@font/sourcecodepro"
app:layout_constraintTop_toBottomOf="@id/crypto_password_show_label" /> android:textIsSelectable="true"
tools:text="p@55w0rd!" />
</androidx.constraintlayout.widget.ConstraintLayout> </com.google.android.material.textfield.TextInputLayout>
<androidx.constraintlayout.widget.ConstraintLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/crypto_extra_show_layout" android:id="@+id/username_text_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="invisible" android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/crypto_container_decrypt" android:hint="@string/username"
android:visibility="gone"
app:endIconDrawable="@drawable/ic_content_copy"
app:endIconMode="custom"
app:layout_constraintTop_toBottomOf="@id/password_text_container"
tools:visibility="visible"> tools:visibility="visible">
<androidx.appcompat.widget.AppCompatImageButton <com.google.android.material.textfield.TextInputEditText
android:id="@+id/crypto_copy_username" android:id="@+id/username_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:background="?android:attr/windowBackground"
android:contentDescription="@string/copy_username"
android:src="@drawable/ic_content_copy"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/crypto_username_show_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_toStartOf="@id/crypto_copy_username"
android:text="@string/username"
android:textColor="?android:attr/textColor"
android:textStyle="bold"
android:visibility="invisible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/crypto_username_show"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/crypto_username_show_label" android:editable="false"
android:layout_alignParentStart="true"
android:layout_toStartOf="@id/crypto_copy_username"
android:textColor="?android:attr/textColor"
android:textIsSelectable="true" android:textIsSelectable="true"
android:typeface="monospace" tools:text="totally_real_user@example.com" />
android:visibility="invisible" </com.google.android.material.textfield.TextInputLayout>
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/crypto_username_show_label"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatTextView <com.google.android.material.textfield.TextInputLayout
android:id="@+id/crypto_extra_show_label" android:id="@+id/extra_content_container"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/crypto_username_show" android:layout_marginTop="16dp"
android:layout_alignParentStart="true" android:hint="@string/extra_content"
android:text="@string/extra_content" android:visibility="gone"
android:textColor="?android:attr/textColor" app:endIconMode="password_toggle"
android:textStyle="bold" app:layout_constraintTop_toBottomOf="@id/username_text_container"
app:layout_constraintStart_toStartOf="parent" tools:visibility="visible">
app:layout_constraintTop_toBottomOf="@id/crypto_username_show" />
<androidx.appcompat.widget.AppCompatTextView <com.google.android.material.textfield.TextInputEditText
android:id="@+id/crypto_extra_show" android:id="@+id/extra_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/crypto_extra_show_label" android:editable="false"
android:layout_alignParentStart="true"
android:textColor="?android:attr/textColor"
android:textIsSelectable="true" android:textIsSelectable="true"
android:typeface="monospace" tools:text="lots of extra content that will surely fill this \n up well" />
app:layout_constraintTop_toBottomOf="@id/crypto_extra_show_label" /> </com.google.android.material.textfield.TextInputLayout>
<ToggleButton
android:id="@+id/crypto_extra_toggle_show"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/crypto_extra_show"
android:layout_alignParentStart="true"
android:backgroundTint="?attr/colorSecondary"
android:checked="false"
android:paddingTop="8dp"
android:textColor="?android:attr/windowBackground"
android:textOff="@string/show_extra"
android:textOn="@string/hide_extra"
app:layout_constraintTop_toBottomOf="@id/crypto_extra_show" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -16,7 +16,6 @@
<string name="delete">حذف</string> <string name="delete">حذف</string>
<!-- PGPHandler --> <!-- PGPHandler -->
<string name="provider_toast_text">لم يتم إختيار مزود الأوبن بي جي بي بعد !</string> <string name="provider_toast_text">لم يتم إختيار مزود الأوبن بي جي بي بعد !</string>
<string name="clipboard_username_toast_text">تم نسخ إسم المستخدم إلى الحافظة</string>
<string name="file_toast_text">الرجاء إدخال إسم ملف</string> <string name="file_toast_text">الرجاء إدخال إسم ملف</string>
<!-- Git Async Task --> <!-- Git Async Task -->
<string name="running_dialog_text">جاري تنفيذ الأمر ...</string> <string name="running_dialog_text">جاري تنفيذ الأمر ...</string>

View File

@@ -33,7 +33,6 @@
<string name="provider_toast_text">Nebyl vybrán poskytovatel OpenPGP!</string> <string name="provider_toast_text">Nebyl vybrán poskytovatel OpenPGP!</string>
<string name="clipboard_password_toast_text">Heslo zkopírováno do schránky, máte %d sekund na jeho zkopírování.</string> <string name="clipboard_password_toast_text">Heslo zkopírováno do schránky, máte %d sekund na jeho zkopírování.</string>
<string name="clipboard_password_no_clear_toast_text">Heslo zkopírováno do schránky</string> <string name="clipboard_password_no_clear_toast_text">Heslo zkopírováno do schránky</string>
<string name="clipboard_username_toast_text">Jméno zkopírováno do schránky</string>
<string name="file_toast_text">Zadejte prosím jméno souboru</string> <string name="file_toast_text">Zadejte prosím jméno souboru</string>
<string name="path_toast_text">Prosím zadejte cestu k souboru</string> <string name="path_toast_text">Prosím zadejte cestu k souboru</string>
<string name="empty_toast_text">Nelze zadat prázdné heslo nebo další obsah</string> <string name="empty_toast_text">Nelze zadat prázdné heslo nebo další obsah</string>

View File

@@ -20,7 +20,6 @@
<!-- PGPHandler --> <!-- PGPHandler -->
<string name="provider_toast_text">Kein OpenPGP-Provider ausgewählt!</string> <string name="provider_toast_text">Kein OpenPGP-Provider ausgewählt!</string>
<string name="clipboard_password_toast_text">Passwort ist in der Zwischenablage, du hast %d Sekunden, um es einzufügen.</string> <string name="clipboard_password_toast_text">Passwort ist in der Zwischenablage, du hast %d Sekunden, um es einzufügen.</string>
<string name="clipboard_username_toast_text">Benutzername ist in der Zwischenablage</string>
<string name="file_toast_text">Bitte setze einen Pfad</string> <string name="file_toast_text">Bitte setze einen Pfad</string>
<string name="empty_toast_text">Du kannst kein leeres Passwort setzen oder leere Extra-Angaben</string> <string name="empty_toast_text">Du kannst kein leeres Passwort setzen oder leere Extra-Angaben</string>

View File

@@ -29,7 +29,6 @@
<string name="provider_toast_text">¡No se ha seleccionado ningún proveedor OpenGPG!</string> <string name="provider_toast_text">¡No se ha seleccionado ningún proveedor OpenGPG!</string>
<string name="clipboard_password_toast_text">Contraseña copiada al portapapeles, tienes %d segundos para pegarla.</string> <string name="clipboard_password_toast_text">Contraseña copiada al portapapeles, tienes %d segundos para pegarla.</string>
<string name="clipboard_password_no_clear_toast_text">Contraseña copiada al portapapeles</string> <string name="clipboard_password_no_clear_toast_text">Contraseña copiada al portapapeles</string>
<string name="clipboard_username_toast_text">Nombre de usuario copiado al portapapeles</string>
<string name="file_toast_text">Por favor selecciona un nombre de archivo</string> <string name="file_toast_text">Por favor selecciona un nombre de archivo</string>
<string name="empty_toast_text">No puedes dejar la contraseña y el contenido extra ambos vacíos</string> <string name="empty_toast_text">No puedes dejar la contraseña y el contenido extra ambos vacíos</string>

View File

@@ -35,7 +35,6 @@
<!-- PGPHandler --> <!-- PGPHandler -->
<string name="provider_toast_text">Aucun prestataire OpenPGP sélectionné !</string> <string name="provider_toast_text">Aucun prestataire OpenPGP sélectionné !</string>
<string name="clipboard_password_toast_text">Mot de passe copié dans le presse papier, vous avez %d secondes pour coller celui-ci.</string> <string name="clipboard_password_toast_text">Mot de passe copié dans le presse papier, vous avez %d secondes pour coller celui-ci.</string>
<string name="clipboard_username_toast_text">Nom d\'utilisateur copié</string>
<string name="file_toast_text">Renseignez un nom de fichier</string> <string name="file_toast_text">Renseignez un nom de fichier</string>
<string name="empty_toast_text">Vous ne pouvez pas utiliser un mot de passe vide ou des données supplémentaires vide</string> <string name="empty_toast_text">Vous ne pouvez pas utiliser un mot de passe vide ou des données supplémentaires vide</string>

View File

@@ -36,7 +36,6 @@
<string name="provider_toast_text">Не выбран провайдер OpenPGP!</string> <string name="provider_toast_text">Не выбран провайдер OpenPGP!</string>
<string name="clipboard_password_toast_text">Пароль скопирован в буфер обмена, у вас есть %d секунд чтобы вставить его.</string> <string name="clipboard_password_toast_text">Пароль скопирован в буфер обмена, у вас есть %d секунд чтобы вставить его.</string>
<string name="clipboard_password_no_clear_toast_text">Пароль скопирован в буфер обмена</string> <string name="clipboard_password_no_clear_toast_text">Пароль скопирован в буфер обмена</string>
<string name="clipboard_username_toast_text">Имя пользователя скопировано в буфер обмена</string>
<string name="file_toast_text">Пожалуйста, укажите имя файла</string> <string name="file_toast_text">Пожалуйста, укажите имя файла</string>
<string name="path_toast_text">Пожалуйста, задайте путь к файлу</string> <string name="path_toast_text">Пожалуйста, задайте путь к файлу</string>
<string name="empty_toast_text">Вы не можете использовать пустой пароль или пустое поле информации</string> <string name="empty_toast_text">Вы не можете использовать пустой пароль или пустое поле информации</string>

View File

@@ -47,7 +47,7 @@
<string name="provider_toast_text">No OpenPGP provider selected!</string> <string name="provider_toast_text">No OpenPGP provider selected!</string>
<string name="clipboard_password_toast_text">Password copied to clipboard, you have %d seconds to paste it somewhere.</string> <string name="clipboard_password_toast_text">Password copied to clipboard, you have %d seconds to paste it somewhere.</string>
<string name="clipboard_password_no_clear_toast_text">Password copied to clipboard</string> <string name="clipboard_password_no_clear_toast_text">Password copied to clipboard</string>
<string name="clipboard_username_toast_text">Username copied to clipboard</string> <string name="clipboard_copied_text">Copied to clipboard</string>
<string name="file_toast_text">Please provide a file name</string> <string name="file_toast_text">Please provide a file name</string>
<string name="path_toast_text">Please provide a file path</string> <string name="path_toast_text">Please provide a file path</string>
<string name="empty_toast_text">You cannot use an empty password or empty extra content</string> <string name="empty_toast_text">You cannot use an empty password or empty extra content</string>