-
-
Notifications
You must be signed in to change notification settings - Fork 868
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
Support inner links #555
Support inner links #555
Conversation
… into feature/268-inner-links
Yeah I'm going to go ahead and say this is what we should merge, don't even consider mine as an alternative lol - I'll close #535 once this is reviewed. Really intrigued as to why this worked but when I tried with |
@tneotia I am not sure what you tried exactly of course, but the tricky part here is that you want to retrieve a certain context via a globalkey, but for the plain |
I was accessing the GlobalKeys via a Map, where the key is the id of the widget and the value is its GlobalKey. If I understand correctly you have a similar idea, instead you just created an extension on GlobalKey to make it a little more seamless? If that's the case then that raises more questions than answers. At least it works now though! |
@tneotia That approach could have worked (and I tried something very similar until I found our how GlobalKey works internally, which is pretty much exactly this - a map between the keys and the build context (element, to be precise). If you have time, could you try to test and break my solution, maybe test some edge cases? |
Also what do you think about exposing a |
Right, I did see that, but it sounds like something the implementer can do herself? We don't even have control over the scroll container, as it stands. Moreover, what scroll to top and not to bottom? |
It just depends. In my use case of the package, I am getting HTML from an API that I don't have access to on the other side to ensure there is a scroll to top button/implementation. If I really wanted, I could parse the HTML and add those elements in, but the convenience of a method would be way nicer. I suggested scroll to top just since its more common than scroll to bottom. Also I don't think scroll to bottom would be feasible unless we put an empty container with an id and a I didn't even notice you didn't include a Whatever you think is best, I was just trying to provide different perspectives. |
I like the different perspectives. It's healthy and you've shown more than once that it's necessary. For this case, indeed no scrollable is even needed (to support the feature). If (and only if) the html is embedded in a scrollable container, the scrolling would work, and I think this is reasonable. Scrolling to the top, even though indeed being the most likely action, is something easily implemented by the implementer via her own scolling container. |
I see what you're saying now. The user would do
in their own app. That's fine by me! |
@ryan-berger how about this one? Perhaps decide on this before we make a new release again? |
This one still needs some fixes before merging as per my review I think (don't know if you saw those, maybe they are resolved but just not marked, I haven't tested it since then). |
…-links # Conflicts: # example/lib/main.dart # lib/flutter_html.dart # lib/html_parser.dart # lib/src/layout_element.dart
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 looks good to me. The only problem that I can foresee is that we are creating a UniqueKey
if the key does not exist. This may become a problem since the HTML widget gets rebuilt often due to it being a stateless widget, and there are performance implications.
Is there any reason why we need it? If the AnchorKey
doesn't exist, we should be safe due to null-safety right?
@ryan-berger what do you mean by creating a unique key if the key does not exist? Could you elaborate? Do you mean for the html widget itself? Yes indeed. Hmm ill have to see if we can do without that, though we'd have to assume in that case that there is no clashing ids in multiple Html widgets. |
@erickok In the constructor of the Html widget, we have |
Maybe creating a |
@tneotia The "correct" way of handling key instantiation would be to use a Stateful widget, which I'm not super keen on doing. I'm not quite sure why we need this anyway though..... I think we don't need the |
The The issue is that the As far as I know this issue is unavoidable without some sort of identifying information for each Html widget, and the easiest way would be a |
Indeed the reason I wanted to ensure a key is because you can otherwise have potential conflicting duplicate keys and Flutter will not like that (beyond being a potential bug). What would the performance impact be here? |
@erickok @tneotia My point is not that we don't need any keys, it is just that we don't need to be instantiating a new If people are not using the feature, do they need the From my understanding there may be a performance cost associated with constructing a key on every rebuild, but as I can't find where I found that yesterday, I also want to point out something else which I found which is that rebuilding a https://medium.com/flutter/keys-what-are-they-good-for-13cb51742e7d Basically my contention is summarized like this:
|
I completely agree, which is why I had suggested to make some sort of private final field for the Allowing the user to opt-in would be fine too, and the functionality can be disabled if a key is not passed to the widget, like you said. |
@tneotia The problem here is that, from my understanding: class Html extends StatelessWidget {
final _uniqueKey = UniqueKey();
// build fn goes here
} will run into the problem that: Html() Forces the evaluation of the The only way around this is a |
Hm I was under the impression that final variables declared in the class would not be re-created/re-evaluated on rebuild, since (in my mind) only the build function is called. If that is not the case then I guess the best option is to require the user to pass a key (if they'd like the anchor link functionality). |
You guys are confusing me... 😕 Keys are typically used for the exact opposite of that you are saying, namely they can be used (beyond identifying things) to prevent having to rebuild a widget (element). A key identifies a widget in the tree. Without a key the type would be used. With a key the key is used to identify it. |
@erickok It is true that a |
True, if a parent causes a rebuild, this Html would be a new widget. Do you see any solution to this problem? |
I think the safest option is to remove creating a new UniqueKey and activate this anchor links only when a developer ads a key by himself into the html widget. Of course we need some documentation in the class that it's only working when a key is added. An other question to this pull request, is it somehow possible to use anchor links also with multiple html widgets? We're creating a list of html widgets for a better performance and currently we have to implement the anchor links by ourself relatively complicated. |
At this moment in time I think this PR tries to avoid that situation and will only anchor link to the html in the immediate html widget. Maybe an option for this can be added? I don't know - @erickok maybe has an idea here.
We really need to try and up the performance. I'm going to see what I can figure out today and maybe report back with a discussion if I find anything. |
…using unneeded rebuilds
To use anchor links between html widgets is not possible with the current setup. Here is why:
To get back to the problem that |
Any feedback @ryan-berger ? I think I addressed your concerns? |
@erickok I added a PR to this PR in the linked PR above - just letting you know. |
…into feature/improve-linking � Conflicts: � lib/flutter_html.dart
@tneotia 1 comment on that PR |
Responded back :) |
This no longer works. Scrollable.ensureVisible(someKey) expects a context, not a key... |
Support for links to anchors inside the html document itself.
Fixes #268 and is an alternative implementation to #535.
This should work with links to ids applied wherever in your document tree. If you have multiple tags with the same id, errors will be thrown. Whilst this is a programmer's error, we might want to guard against that (in
AnchorKey
's factory constructor).If the Html is not used in a scroll container, the links are simply ignored (as in, nothing will happen when tapping). If the achor style link (
#some-id
) doesn't exist in the document, the link is ignored. Scrolling is 'instant' i.e. no smooth scrolling.An implementer could even link to known parts in the document by manually looking up the anchor key and scrolling to it:
Scrollable.ensureVisible(AnchorKey.forId(key, "some-id").currentContext)