diff --git a/.github/workflows/build-apks.yml b/.github/workflows/build-apks.yml
index 414fcc1f..c874c22e 100644
--- a/.github/workflows/build-apks.yml
+++ b/.github/workflows/build-apks.yml
@@ -29,6 +29,18 @@ jobs:
distribution: "temurin"
java-version: "17"
+ - name: Decode Keystore
+ run: |
+ echo "$KEYSTORE_BASE64" | base64 --decode > passcodes-staging.jks
+ env:
+ KEYSTORE_BASE64: ${{ secrets.STAGING_KEYSTORE_BASE64 }}
+
+ - name: Decode Keystore Properties
+ run: |
+ echo "$KEYSTORE_PROPERTIES_BASE64" | base64 --decode > keystore.properties
+ env:
+ KEYSTORE_PROPERTIES_BASE64: ${{ secrets.STAGING_KEYSTORE_PROPERTIES_BASE64 }}
+
- name: Setup Gradle
uses: gradle/gradle-build-action@v3
diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/ui/ViewPasswordActivity.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/ui/ViewPasswordActivity.kt
index 3c2a28cd..c0ae1f1d 100644
--- a/app/src/main/kotlin/com/jeeldobariya/passcodes/ui/ViewPasswordActivity.kt
+++ b/app/src/main/kotlin/com/jeeldobariya/passcodes/ui/ViewPasswordActivity.kt
@@ -1,6 +1,7 @@
package com.jeeldobariya.passcodes.ui
-import android.annotation.SuppressLint
+import android.content.ClipData;
+import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.os.Bundle
@@ -27,12 +28,13 @@ class ViewPasswordActivity : AppCompatActivity() {
private var passwordEntityId: Int = 0
private lateinit var binding: ActivityViewPasswordBinding
private lateinit var controller: Controller
+ private lateinit var passwordEntity: Password
override fun onCreate(savedInstanceState: Bundle?) {
val sharedPrefs = getSharedPreferences(SettingsActivity.THEME_PREFS_NAME, Context.MODE_PRIVATE)
val savedThemeStyle = sharedPrefs.getInt(SettingsActivity.THEME_KEY, R.style.PasscodesTheme_Default)
setTheme(savedThemeStyle)
-
+
super.onCreate(savedInstanceState)
binding = ActivityViewPasswordBinding.inflate(layoutInflater)
setContentView(binding.root)
@@ -58,7 +60,7 @@ class ViewPasswordActivity : AppCompatActivity() {
private fun fillDataInTextview() {
lifecycleScope.launch {
try {
- val passwordEntity: Password = controller.getPasswordById(passwordEntityId)
+ passwordEntity = controller.getPasswordById(passwordEntityId)
withContext(Dispatchers.Main) {
binding.tvDomain.text = "${getString(R.string.domain_prefix)} ${passwordEntity.domain}"
binding.tvUsername.text = "${getString(R.string.username_prefix)} ${passwordEntity.username}"
@@ -90,6 +92,30 @@ class ViewPasswordActivity : AppCompatActivity() {
// Added all the onclick event listeners
private fun addOnClickListenerOnButton() {
+ binding.copyPasswordBtn.setOnClickListener {
+ val confirmDialog = AlertDialog.Builder(this@ViewPasswordActivity)
+ .setTitle(R.string.copy_password_dialog_title)
+ .setMessage(R.string.danger_copy_to_clipboard_desc)
+ .setPositiveButton(R.string.confirm_dialog_button_text) { dialog, which ->
+ val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
+ val clip: ClipData = ClipData.newPlainText(passwordEntity.username, passwordEntity.password)
+
+ // Set the ClipData to the clipboard
+ if (clipboard != null) {
+ clipboard.setPrimaryClip(clip)
+ Toast.makeText(this, getString(R.string.copy_success), Toast.LENGTH_SHORT).show()
+ } else {
+ Toast.makeText(this, "Clipboard service not available.", Toast.LENGTH_SHORT).show()
+ }
+ }
+ .setNegativeButton(R.string.discard_dialog_button_text) { dialog, which ->
+ Toast.makeText(this, getString(R.string.action_discard), Toast.LENGTH_SHORT).show();
+ }
+ .create();
+
+ confirmDialog.show();
+ }
+
binding.updatePasswordBtn.setOnClickListener {
val viewPasswordIntent = Intent(this, UpdatePasswordActivity::class.java)
viewPasswordIntent.putExtra("id", passwordEntityId)
@@ -101,18 +127,18 @@ class ViewPasswordActivity : AppCompatActivity() {
.setTitle(R.string.delete_password_dialog_title)
.setMessage(R.string.irreversible_dialog_desc)
.setPositiveButton(R.string.confirm_dialog_button_text) { dialog, which ->
- performDeletePasswordAction();
+ performDeletePasswordAction()
}
.setNegativeButton(R.string.discard_dialog_button_text) { dialog, which ->
Toast.makeText(this, getString(R.string.action_discard), Toast.LENGTH_SHORT).show();
}
.create();
-
+
confirmDialog.show();
}
}
- fun performDeletePasswordAction() {
+ private fun performDeletePasswordAction() {
lifecycleScope.launch {
try {
val rowsDeleted = controller.deletePassword(passwordEntityId)
diff --git a/app/src/main/res/layout/activity_view_password.xml b/app/src/main/res/layout/activity_view_password.xml
index f3141af0..0035efdd 100644
--- a/app/src/main/res/layout/activity_view_password.xml
+++ b/app/src/main/res/layout/activity_view_password.xml
@@ -71,7 +71,16 @@
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
-
+
+
+
+
+ - English (en-us)
+ - Hindi (hi)
+ - Indonesian (in)
+ - Korean (ko)
+ - Korean Romanized (kr)
+ - Japanese (ja)
+ - German (de)
+ - Spanish (es)
+ - Chinese (zh)
+ - Vietnamese (vi)
+
+
+
+ - en
+ - hi
+ - id
+ - ko
+ - kr
+ - ja
+ - de
+ - es
+ - zh
+ - vi
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0d743087..e8fddd99 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -21,10 +21,12 @@
Username
Password
Notes
+ Copied Successfully
e.g. Google, Instagram, WhatsApp, etc.
e.g. Liam15, Noha, Olivia, Ava_25, etc.
e.g. 12345, abc123xyz, qwerty, etc.
Password Manager
+ Copy Password
Save Password
Load Password
Update Password
@@ -83,35 +85,11 @@
Something Went Wrong: Invalid ID!!
+ Copy to Clipboard?
Update password?
Delete password?
This action cannot be undone.
+ Copying sensitive data like passwords to clipboard is not so good for security!!!
Confirm
Discard
-
-
- - English (en-us)
- - Hindi (hi)
- - Indonesian (in)
- - Korean (ko)
- - Korean Romanized (kr)
- - Japanese (ja)
- - German (de)
- - Spanish (es)
- - Chinese (zh)
- - Vietnamese (vi)
-
-
-
- - en
- - hi
- - id
- - ko
- - kr
- - ja
- - de
- - es
- - zh
- - vi
-