-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[GSoC'24] Add Right-Click Support to Long Click Listeners #16712
Conversation
@@ -399,6 +398,19 @@ open class DeckPicker : | |||
) | |||
) | |||
} | |||
} | |||
|
|||
private val deckLongClickListener = OnLongClickListener { v -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd have a slight preference for having it directly on top of showDeckPickerContextMenu
. Just to reduce the size of the diff.
And then deckContextClickListener
even on top of it
@@ -179,7 +179,11 @@ open class DeckSelectionDialog : AnalyticsDialogFragment() { | |||
} | |||
} | |||
|
|||
private fun showSubDeckDialog(parentDeckPath: String) { | |||
private fun showSubDeckDialog(parentDeckPath: String, deckID: DeckId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some javadoc.
It used to be very clear what this method was doing. Now that it may not open the subdeck dialog, it's important to note this special case
showSubDeckDialog(deckName, deckID) | ||
true | ||
} | ||
deckHolder.setOnContextClickListener { // creating sub deck with parent deck path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that each time you introduce setOnContextClickListener
in the codebase, it does the same thing as setOnLongClickListener
I'd suggest we do something such as
/**
* A listener that has the same action for both "context click" (i.e. mostly right click) and "long click" (i.e. holding the finger on the view).
*/
interface OnContextAndLongClickListener: OnContextClickListener, OnLongClickListener {
fun onAction(v: View): Boolean
override fun onContextClick(v: View): Boolean {
Timber.i("${this.javaClass}: user context clicked")
return onAction(v)
}
override fun onLongClick(v: View): Boolean {
Timber.i("${this.javaClass}: user long clicked")
return onAction(v)
}
companion object {
/**
* Ensures [this] gets both a long click and a context click listener.
* @see View.setOnLongClickListener
* @see View.setOnContextClickListener
*/
fun View.setContextAndLongClickListener(listener: OnContextAndLongClickListener) {
setOnLongClickListener(listener)
setOnContextClickListener(listener)
}
}
}
Maybe not exactly as-is, if we can improve the usage.
Still, it would ensure we don't need to duplicate code everywhere, given that we'll probably never want to have one listener and not the other
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, when I state "something such as", or similar requirement, you don't have to copy-paste it as-is. I don't guarantee that it's working properly.
In particular, if you tested the Timber, you'd see it gives
class com.ichi2.anki.DeckPicker$$ExternalSyntheticLambda6: user long clicked
Which to be honest I only realized because I could not guess what would be the class of this
with your implementation.
I admit that I have no great idea about how to solve that. I would have loved to have an extra parameter which is a string value, but that would make the code far less readable, since we could not use only the declaration as a single function.
Worse, the TagsArrayAdapter is not easy to correct
As I've no better idea, I guess we can leave it as is. Unless someone wiser find a good solution that don't require too much work.
I doubt it'll really impede debugging, given the small number of place it's used in each file.
@@ -114,6 +116,10 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context) | |||
deckLongClickListener = listener | |||
} | |||
|
|||
fun setDeckContextClickListener(listener: OnContextClickListener?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the parameter nullable ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reason:
var deckContextClickListener: OnContextClickListener? = null
@@ -114,6 +116,10 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context) | |||
deckLongClickListener = listener | |||
} | |||
|
|||
fun setDeckContextClickListener(listener: OnContextClickListener?) { | |||
deckContextClickListener = listener |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the setter is public, I think the whole var can be public.
15fb8bd
to
cada620
Compare
cada620
to
7553bb8
Compare
7553bb8
to
8c5d623
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed a comment - feels like a GitHub bug
Really clean, thanks! |
* * Ensure that using the same action for both is appropriate for your use case. | ||
*/ | ||
fun interface OnContextAndLongClickListener : View.OnContextClickListener, View.OnLongClickListener { | ||
fun onAction(v: View): Boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As usual, I'd like documentation. It can be very short, such as
The action to do for both contextClick and long click
@returns whether the operation was succesful
showSubDeckDialog(deckName, deckID) | ||
true | ||
} | ||
deckHolder.setOnContextClickListener { // creating sub deck with parent deck path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, when I state "something such as", or similar requirement, you don't have to copy-paste it as-is. I don't guarantee that it's working properly.
In particular, if you tested the Timber, you'd see it gives
class com.ichi2.anki.DeckPicker$$ExternalSyntheticLambda6: user long clicked
Which to be honest I only realized because I could not guess what would be the class of this
with your implementation.
I admit that I have no great idea about how to solve that. I would have loved to have an extra parameter which is a string value, but that would make the code far less readable, since we could not use only the declaration as a single function.
Worse, the TagsArrayAdapter is not easy to correct
As I've no better idea, I guess we can leave it as is. Unless someone wiser find a good solution that don't require too much work.
I doubt it'll really impede debugging, given the small number of place it's used in each file.
fun interface OnContextAndLongClickListener : View.OnContextClickListener, View.OnLongClickListener { | ||
fun onAction(v: View): Boolean | ||
override fun onContextClick(v: View): Boolean { | ||
Timber.i("${this.javaClass}: user context clicked") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, when I state "something such as", or similar requirement, you don't have to copy-paste it as-is. I don't guarantee that it's working properly.
In particular, if you tested the Timber, you'd see it gives
class com.ichi2.anki.DeckPicker$$ExternalSyntheticLambda6: user long clicked
Which to be honest I only realized because I could not guess what would be the class of this
with your implementation.
I admit that I have no great idea about how to solve that. I would have loved to have an extra parameter which is a string value, but that would make the code far less readable, since we could not use only the declaration as a single function.
Worse, the TagsArrayAdapter is not easy to correct
As I've no better idea, I guess we can leave it as is. Unless someone wiser find a good solution that don't require too much work.
I doubt it'll really impede debugging, given the small number of place it's used in each file.
true | ||
} | ||
|
||
private fun showDeckPickerContextMenu(deckId: DeckId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with having a function that is just a function. But in this case, I think you should not have the value deckContextAndLongClickListener and directly move its content at the only place where it's used
I'll want a little bit of changes, but essentially, I approve the commit as it is. If you find a way to improve timber let us know, otherwise I just want you to add the documentation/comment please |
-Added right-click support for all existing long click listeners. -Created an OnContextAndLongClickListener interface to handle both context click and long click events consistently. -This interface includes an onAction method to define the common action (context and long click). -The interface ensures that both listeners are set without duplicating code. -Applied the OnContextAndLongClickListener interface to handle right-click and long-click events uniformly.
8c5d623
to
c39cfe9
Compare
Purpose / Description
This PR introduces functionality to support right-click actions wherever long click listeners are implemented in the application. This enhancement aims to improve user experience by providing additional interaction capabilities on devices that support right-click actions.
Approach
yourView.setOnContextClickListener { showContextMenu() true }
How Has This Been Tested?
HP Chromebook
Checklist
Please, go through these checks before submitting the PR.