Skip to content
This repository has been archived by the owner on Dec 14, 2021. It is now read-only.

Copy and reveal credentials #124

Merged
merged 12 commits into from
Oct 8, 2018
Merged

Copy and reveal credentials #124

merged 12 commits into from
Oct 8, 2018

Conversation

mihainisipeanusv
Copy link
Contributor

@mihainisipeanusv mihainisipeanusv commented Oct 3, 2018

Fixes #13
Fixes #12

Adding the username and password copy in ItemDetailFragment, also reveal / hide password

  • please let me know is adding a EditText in ItemDetailsView passed to presenter is the correct approach
  • please let me know what is the correct approach to mock a EditText in tests.

@mihainisipeanusv mihainisipeanusv requested a review from a team as a code owner October 3, 2018 12:42
@ghost ghost assigned mihainisipeanusv Oct 3, 2018
@ghost ghost added the in progress label Oct 3, 2018
@devinreams
Copy link
Contributor

Thanks for your first contribution, @mihainisipeanusv. I'll defer to the engineering and UX teams to help review this. A few pointers, since I failed to explain these the other day:

  1. Adding "Fixed {issue number}" to the PR description will link this up to the corresponding issues and help us keep our issue/PRs organized

  2. bitrise runs linting so you may see failures on the build if not explicitly running them locally (we don't have any shared idea files yet or pre-commit hooks or anything). in this case you'll see :app:ktlint FAILED on your commits here which probably can all be resolved with ./gradlew ktlintFormat and committing the results 🤞

Thanks again! 🏅

@devinreams devinreams changed the title Copy credentials Copy and reveal credentials Oct 3, 2018
Copy link
Contributor

@jhugman jhugman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR seems to work well, but I think it needs some work before it lands.

The uni-directional data flow would demand that we set up an ItemDetailStore and perhaps a ClipboardStore; this would get rid of a bunch view layer code in your presenter, and make it more testable. You can see how the swift version works in the ItemDetailStore and CopyDisplayStore.

Please also read the rest of the comments, and ask questions if they don't make sense.

get() = tapStub

override val editUsername: EditText
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: unwanted TODO, and generated comments.


override fun updateItem(item: ItemDetailViewModel) {
this.item = item
}

override fun copyNotification(strId: Int) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: have you forgotten to git add something, or should this be a // NOOP comment?

}

override fun updatePasswordField(visible: Boolean){

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

override val editUsername: EditText
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val editPassword: EditText
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

@@ -6,23 +6,69 @@

package mozilla.lockbox.presenter

import android.util.Log
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use log, which is declared in LockboxApplication.


this.view.btnPasswordCopyClicks
.subscribe {
clipboardCopy("password", view.editPassword.text.toString())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be using the ServerPassword or the ItemDetailViewModel version of the username/password, rather than the UI version.

private val dispatcher: Dispatcher = Dispatcher.shared,
private val dataStore: DataStore = DataStore.shared

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: whitespace.


interface ItemDetailView {
var itemId: String?
fun updateItem(item: ItemDetailViewModel)
fun copyNotification(strId: Int)
fun updatePasswordField(visible: Boolean)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a boolean flag like this, consider using a field with a getter/setter.

inputPassword.transformationMethod = null
btnPasswordToggle.setImageResource(R.drawable.ic_hide)
} else {
inputPassword.transformationMethod = PasswordTransformationMethod()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using PasswordTransformationMethod.getInstance()

val subject = ItemDetailPresenter(view, dataStore = dataStore)
val clipboardManager = Mockito.mock(ClipboardManager::class.java)

val subject = ItemDetailPresenter(view, clipboardManager, dataStore = dataStore)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests needed.

@nickbrandt
Copy link
Contributor

@mihainisipeanusv this looks great and functions as expected.

I did notice an issue with the icon sizes & color. After digging into Zeplin, I realized that although the icons were exportable, they were retaining the original size & color of our icon symbol within Sketch. Meaning although we had resized this icon to 18px by 18px and changed the color in the design, it was exporting at 16px as well as not including the transparent bounding box. I apologize for this and have fixed this in Zeplin now, as well as am including the icons below.

My assumption is that we will take care of styling the snackbar for the copy notifications in a later issue, is that correct?

screen shot 2018-10-03 at 10 41 30 am
icon_hide_2018-10-03.zip
icon_copy_2018-10-03.zip
icon_show_2018-10-03.zip

@mihainisipeanusv
Copy link
Contributor Author

@mihainisipeanusv this looks great and functions as expected.

I did notice an issue with the icon sizes & color. After digging into Zeplin, I realized that although the icons were exportable, they were retaining the original size & color of our icon symbol within Sketch. Meaning although we had resized this icon to 18px by 18px and changed the color in the design, it was exporting at 16px as well as not including the transparent bounding box. I apologize for this and have fixed this in Zeplin now, as well as am including the icons below.

My assumption is that we will take care of styling the snackbar for the copy notifications in a later issue, is that correct?

screen shot 2018-10-03 at 10 41 30 am
icon_hide_2018-10-03.zip
icon_copy_2018-10-03.zip
icon_show_2018-10-03.zip

nick I had noticed that the new version of the hide and show icon are not ok. In the hide one the eye is at the image center and in the show is not, and when you change image it just jump up and down

Copy link
Contributor

@jhugman jhugman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your hard work on this. This is starting to look like the right shape. :)

I've added some more comments. Ask in #Lockbox slack or in the PR itself if you have any questions.

inputPassword.transformationMethod = PasswordTransformationMethod.getInstance()
btnPasswordToggle.setImageResource(R.drawable.ic_icon_show)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

) : Presenter() {

override fun onViewReady() {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: whitespace

Copy link
Contributor

@jhugman jhugman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is getting really close.

Please make the final changes and land this.

Lovely work, thank you.

view.itemId?.let {
dataStore.get(it)
.subscribe {
dispatcher.dispatch(ClipboardAction.Clip("username", it!!.username!!))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when there is no username?


this.view.passwordCopyClicks
.subscribe {
view.itemId?.let {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract this statement into a method, parameterized for username and password.

At some point, it would be good to not hit the database each time, and stash the itemViewModel, but I don't think we need to worry about that now.

when (it) {
is ClipboardAction.Clip -> {
addToClipboard(it.label, it.str)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good. Consider making a CopyUsername / CopyPassword objects, but this shouldn't stop you landing this at this point.

}

fun addToClipboard(label: String, str: String) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace.


val clipboardManager: ClipboardManager = RuntimeEnvironment.application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
assertTrue(clipboardManager.primaryClip.getItemAt(0).text.equals(testString))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be made into a property?

RuntimeEnvironment.application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager


override fun showToastNotification(@StringRes strId: Int) {
Toast.makeText(activity, getString(strId), Toast.LENGTH_SHORT).show()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


sealed class ClipboardAction : Action {
data class Clip(val label: String, val str: String) : ClipboardAction()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider CopyUsername, CopyPassword.

@mihainisipeanusv mihainisipeanusv merged commit 1ee365b into master Oct 8, 2018
@ghost ghost removed the in progress label Oct 8, 2018
@devinreams
Copy link
Contributor

The unit tests were failing on the last two commits and this merged branch now has master failing:
https://app.bitrise.io/build/b0f43db64a0b5751

:app:compileDebugUnitTestKotline: /bitrise/src/app/src/test/java/mozilla/lockbox/store/ClipboardStoreTest.kt: (41, 45): Unresolved reference: Clip

@devinreams devinreams deleted the copy-credentials branch October 8, 2018 19:30
@linuxwolf
Copy link
Contributor

There are also 6 new linting errors (full list isn't enumerated on bitrise)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants