-
Notifications
You must be signed in to change notification settings - Fork 246
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
[SuperEditor][Android] Honor handle builders (Resolves #1934) #2272
base: main
Are you sure you want to change the base?
Conversation
@angelosilvestre is this PR both connecting the existing builders, and also modifying the tooling to build them? If so, can you split this into two PRs: one for fixing the existing bug, and another for whatever improvements you want to make? |
@matthew-carroll I think that at least we should keep |
@matthew-carroll Updated removing |
@angelosilvestre can you update the PR description so that it only describes the changes in this PR after you split this PR into two? |
@matthew-carroll Updated the description. |
@angelosilvestre since you focused in this PR around making it simpler and easier to create custom handles, can you add a code sample to the PR description that shows a minimum setup for a custom drag handle? That will probably help evaluate those decisions. WRT the |
@angelosilvestre did you update the description? I see that my last comment was the last activity on this thread, so I wasn't sure if that happened, or not. |
In this PR I focused on just making the handle builder be honored. Making it simpler and easier would be moved to a separate PR, right? |
I would defer to the earlier conversation in the thread. I think that's all the conversation we've had about this. What I don't know is whether your current PR description describes what's actually in this PR, or whether the description is still about the original PR, which included stuff that you later removed. |
I updated the description. |
I'm not sure what this means. Can you try to describe this in a clearer way? |
Updated it again. Does it look better now? |
Ok, now it reads:
Wouldn't it be accurate to say if the user moves left, or up its an upstream selection, and if the user moves right or down then it's a downstream selection? There should probably be a little slop before making that choice, but we shouldn't have to wait for the handle to actually move for us to know the direction of the drag, right? |
The change is basically adding that left/right move handling. Do we need to change the whole behavior on this PR? |
super_editor/lib/src/default_editor/document_gestures_touch_android.dart
Outdated
Show resolved
Hide resolved
key: DocumentKeys.upstreamHandle, | ||
handleType: HandleType.upstream, | ||
color: _controlsController!.controlsColor ?? Theme.of(context).primaryColor, | ||
Widget _buildExpandedHandles() { |
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.
Do we need to change this from List<Widget>
to Widget
? I'm hesitant to add more layout widgets when not needed, because it increases the odds that at some point something isn't aligned correctly because of we've got a Stack
in a Stack
in a Stack
, etc.
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.
We can keep it as a list. Reverted.
|
||
return Stack( | ||
children: [ | ||
Follower.withOffset( |
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.
When you mentioned in the issue ticket that it's difficult for users to configure their own handles, did you include the Follower
in your description of it being difficult? I.e., did you want to wrap the custom handle with a Follower
so the user doesn't have to? Or is it better like this to have the user provide the Follower
?
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 think we should have the user provide the Follower
, to have full control on the alignment, expansion, etc. We could add a default following handle to make it easier for those who don't need this kind of control.
super_editor/lib/src/infrastructure/platforms/mobile_documents.dart
Outdated
Show resolved
Hide resolved
@@ -304,6 +305,91 @@ void main() { | |||
expect(SuperEditorInspector.isCaretVisible(), true); | |||
}); | |||
|
|||
testWidgetsOnAndroid("allows customizing the collapsed handle", (tester) async { |
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.
Given that most of this PR is based on delegating gesture behavior, should this PR add a number of tests that use those gestures? Or is that fully covered by existing tests?
Also, why are we only testing for Android?
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.
We currently have test ensuring that dragging the expanded handle changes the selection. Should we add a test for the collapsed handle? We have properties for handle customization on Android only.
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.
Seems like tests for the collapsed handle would be as important as for expanded handles.
@@ -309,6 +309,18 @@ class TestSuperEditorConfigurator { | |||
return this; | |||
} | |||
|
|||
/// Configures the [SuperEditor] to use the given [builder] as its android collapsed handle builder. | |||
TestSuperEditorConfigurator withAndroidCollapsedHandleBuilder(DocumentCollapsedHandleBuilder? builder) { |
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 only for Android?
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.
The original ticket is only about Android. We don't have handle builders for iOS.
1074a91
to
a309fc8
Compare
@@ -23,12 +23,24 @@ class DocumentKeys { | |||
/// The [handleKey] is used to find the handle in the widget tree for various purposes, | |||
/// e.g., within tests to verify the presence or absence of the handle. | |||
/// | |||
/// The [gestureDelegate] hold event handles that should be attached to the gesture recognizer |
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.
This paragraph is confusing - I'm not sure what exactly it's trying to say.
"The [gestureDelegate] hold event handles". First, it sounds like "hold" -> "holds". Beyond that, I don't know what it means to "hold event handles"...do you mean "handlers"? If so, the delegate doesn't "hold event handlers", a delegate "defines handlers for gesture events that occur on a given handle".
"For example, set [gestureDelegate.onTap] to the handle's onTap
event."
I don't know what this is telling me to do. How do I set a method on the handle's onTap
? Is this a statement about what I need to do as a reader, or a description of what is happening behind the scenes? I can't tell.
/// The [gestureDelegate] hold event handles that should be attached to the gesture recognizer | ||
/// attached to the handle. For example, set [gestureDelegate.onTap] to the handle's `onTap` event. | ||
/// | ||
/// Use [shouldShow] to fade in/out the handle entrance/exit, for example, using an [AnimatedOpacity] |
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.
This paragraph is also unclear. When reading this, I can't really tell what you want me to do, or what Super Editor does. I generally understand that something is going on with fading, but there seems to be like 3 distinct details that are smushed into one statement and it's confusing.
/// These callbacks are intended to make it easier for developers to customize | ||
/// the drag handles, without having to re-implement the gesture logic. | ||
/// | ||
/// To use it, for example, wrap the handle in a `GestureDetector` and pass |
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.
Can you replace this last sentence with a minimal code example showing this in use?
[SuperEditor][Android] Honor handle builders. Resolves #1934
SuperEditorAndroidControlsController
exposescollapsedHandleBuilder
andexpandedHandlesBuilder
, but neither of them are being used anywhere.This PR changes the android touch interactor to honor the provided builders.
The drag handles involve various gesture callbacks to place/expand/collapse the selection, start/stop the blinking caret, show/hide the toolbar, among other things. It would be very difficult for developers to do that on their own.
Because of that, this PR introduces an object called
DocumentHandleGestureCallbacks
, which holds the gesture callbacks that should be attached to the drag handle. Developers would wrap the handle with aGestureDetector
and set each property to its correspondingGestureDetector
callback.I needed to modify the expanded handles selection logic, because after these changes, when the user starts dragging the expanded handle, the pan update event is trigger before the user moves the drag handle to another character, so we couldn't determine if the user is dragging upstream or downstream. This breaks our logic of selecting by word or character.
The original ticket also mentions that we use
magnifierBuilder
andtoolbarBuilder
in different ways. FormagnifierBuilder
, we expect that developers will include theFollower
in the returned widget, while intoolbarBuilder
we wrap the returned widget with aFollower
. Letting the developers attach theFollower
to the tree seems more logical to me, because it would be able to customize the offset and anchors. But changing that now seems like a big breaking change. Should we do that?