-
Notifications
You must be signed in to change notification settings - Fork 14
feat: Adds navigationDelegate for handling links #15
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
feat: Adds navigationDelegate for handling links #15
Conversation
Thank you @Alexander-Ordina for your contribution to our plugin. We will review your PR and get it released. |
Hi @Alexander-Ordina, first off, thanks for contributing this PR! We're reviewing it, and while the code change is tiny, it may impact architecture changes we got lined up in the near future, so we'll need some time to evaluate it. (note that we'll also need a signed CLA, even for such tiny code changes unfortunately, as discussed in the other PR you made) Can you confirm that for your own project, you're unblocked since you can use your forked version of the SDK for the time being, until we merge this PR? |
Hi @eteeselink, I just got confirmation that the CLA is signed and send to your legal department. I'm guessing the architecture change you are talking about is the switch to InAppWebView, to get the same behavior with InAppWebView the shouldOverrideUrlLoading property can be used. We do not plan to use the fork I made, the fork was only to make is possible to create a Pull Request, so until this is solved we are still blocked for rolling out Talkjs in our App. |
Hi Alexander, Fantastic! For our understanding: we recently open-sourced the flutter SDK specificallly to make interactions like these possible, so we're very happy with your contributions. Sorry about our delay in addressing them. That said, another goal we had with open-sourcing the SDK was to unblock customers, ie not keep customers blocked on our development speed for things inside the SDK, if something is missing. I see that you're nevertheless unable to temporarily use your fork until we worked things out, which surprised me. Would you be able to shed some light on the dynamics on your side that prevent you from going live now using your fork, and switching over to our official SDK once we merged your PR? (or addressed the problem it solves in an alternative way) |
You're totally right about the architecture change being the switch to InAppWebView. |
@bugnano I have added a onUrlNavigation function on the chatbox widget, this property can be used for adding the navigation logic independent of which webview is used. It is still needed to have a webview dependent implementation to translate this function for the type of webview used, for this I added the private function _shouldNavigateToUrl which is used as the NavigationDelegate for the flutter webview. When switching to the InAppWebview this function will have to be rewritten to work with it. |
Hi @eteeselink, I understand that it might be surprising that we do not want to use the temporary fork. We want to prevent creating unnecessary forks which we have to maintain, we only do this if there is no other option. We try to make sure that we have plenty of time to solve issues with plugins before we release new features either by filing issues or creating pull requests. We expect that these issues can probably be solved before we go live with chat feature in our app, to make sure that is the case we would like to know when there is a new release for TalksJs plugin planned? |
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.
Good work, I like it, but before merging this PR, I'd like to have the UrlNavigationRequest
class to work with Dart's Uri regarding the url
parameter, and to be explicit about the type.
lib/src/chatbox.dart
Outdated
enum UrlNavigationAction { allow, deny } | ||
|
||
class UrlNavigationRequest { | ||
final url; |
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 would be better to explicitly state the type of the variable here (which should be preferably Dart's Uri)
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 Updated the UrlNavigationRequest it now had 3 properties:
final Uri? url;
final String rawUrl;
final bool isValidUrl;
This is to make sure that if the url is not a valid uri that it still is possible to pass the UrlNavigationRequest without throwing exceptions.
I'm also thinking that it might be better to just pass the url as a String, this way any error handling or conversion to Uri Objects can be handled by the specific app using the plugin.
What do you feel is best?
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.
OK, so in this case let's use String for the url, and the validation is done by the user's code.
I thought that the Uri type could be the more appropriate one, but given that there could be some cases where the url is not a valid Uri, then my previous assumption was wrong.
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.
Thank you for the update, we're close to merging this PR, but I still ask you to do one last change.
Given that the policy at TalkJS has been to support APIs forever, and never break compatibility, we can only achieve this if we expose the bare minimum, and we expose the correct types in the first place.
lib/src/chatbox.dart
Outdated
|
||
class UrlNavigationRequest { | ||
final Uri? url; | ||
final String rawUrl; |
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 would not expose the variables rawUrl and isValidUrl, because everything that's public needs to be supported forever, so the less we expose, the better.
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 problem is that the Uri.tryParse() method returns Null for an invalid url. If the rawUrl is not exposed there is no way for the app that uses plugin to figure out what the original Url was for the link.
It could be possible that a link is send with an invalid url, but in the app we still want to do something with this link. For example:
- We want to show an errormessage containing the url
- We could have a special url that opens a page in the app, maybe a url like: app://about would navigate to the app's about page. This is not a valid uri, but could be wanted behavior in a App.
I think it would best to make the type for url a String this way the plugin stays simple and the rawUrl and isValidUrl can be removed.
class UrlNavigationRequest {
final String url;
...
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.
Yes, let's keep things simple and use String.
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 updated the code, I also made the String Nullable to make sure it will work with any future implementation of the webview
lib/src/chatbox.dart
Outdated
this.isValidUrl, | ||
) ; | ||
|
||
factory UrlNavigationRequest(String url){ |
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 should not do the String to Uri conversion in a public API.
A simple constructor with an Uri parameter is the best here.
The whole String to Uri conversion is better to be done in the private _shouldNavigateToUrl function.
… will work with different implementations for the webview
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.
Thank you for the changes, I just have one question:
I appreciate very much that you got into the mentality of implementation-independence, but I don't get how a nullable string can achieve that.
Think of the user of the API:
If the url is nullable, then I expect to have an UrlNavigationRequest with a null url.
What does that mean to me, as a user?
Or, to put it another way: we decided that the url is of type String.
This means that whenever we change the implementation, we will convert whatever url type we have to String, I don't get how null can be helpful in this situation.
lib/src/chatbox.dart
Outdated
enum UrlNavigationAction { allow, deny } | ||
|
||
class UrlNavigationRequest { | ||
final String? url; |
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.
What's the practical use of an UrlNavigationRequest with a null url?
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.
InAppWebView sometimes returns null for the url so it will not always be a String the result could be null.
I did a little more research on how InAppWebview works with urls and they do use a Uri object this means they parse the Url String to a Uri in their implementation.
This means that invalid urls won't work with there implementation, so creating a special url is only an option if it is also a valid Uri.
More information can be found here: https://inappwebview.dev/docs/webview/in-app-webview/#handle-custom-urls
I think this invalidates my previous comment about why it should be a String looking at this I do feel making it a Nullable Uri should be better. And custom urls can be handled like described in the link above.
What do you think would be best?
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 you want we could also setup a meeting to discuss an maybe get this issue resolved a bit quicker?
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 believe that a non-nullable string is the best solution here, and here's why:
While not all Strings can be valid Uris, thus resulting in a null Uri, the same is not true for Uris, which are all valid Strings, so it's better to have a non-nullable String, and then let the user decide what to do with that string.
As I see from the documentation of the InAppWebView, if an Uri is invalid, the shouldOverrideUrlLoading method is not called anyway, so it's not a problem.
And the fact that the Uri can be null in the NavigationAction.URLRequest does not affect this functionality, as I'm sure that shouldOverrideUrlLoading will not be called with a null Uri (if you read the docs, a null Uri is equivalent to "about:blank").
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.
Good point, I've now changed it to a non nullable String
@eteeselink , hey! Seems like in last version you forgot add this functionality :( |
Hey @zSoNz, I'm a developer at TalkJS. Regarding the feature above, it was an intentional decision to not include it. For versions 0.6.0 and lower of our SDK, links inside the chat would open inside the webview rather than in an external browser. This was the initial motivation for implementing Was there another use case you intended to use |
Adds NavigationDelegate to the chatbox for handling links.
See #14