Skip to content
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

apiVersioning and developerContact implementation for AnkiDroid functions call from WebView #6521

Merged
merged 25 commits into from
Aug 7, 2020

Conversation

krmanik
Copy link
Member

@krmanik krmanik commented Jun 21, 2020

Pull Request template

Purpose / Description

This is implementation for api versioning for usage of AnkiDroid native functions in WebView.

Fixes

Fixes #6328

Approach

Getting api version & developer contact from card developer, then allow them to call the above functions implementation.

How Has This Been Tested?

Tested on Emulator
Calling this function before calling #6307 implemented functions

<script>
   var jsApi = {"version" : "0.0.1", "developer" : "dev@mail.com"};

   var apiStatus = AnkiDroidJS.init(JSON.stringify(jsApi));
   console.log(apiStatus);
   
   api = JSON.parse(apiStatus);
   
   if (api['markCard']) {
      console.log("API mark card available");
   }   

   if (api['toggleFlag']) {
      console.log("API toggle flag available");
   }   
</script>

apiStatus contain enabled/disabled status of api in true/false (boolean value).

Learning (optional, can help others)

https://stackoverflow.com/questions/51513715/node-js-rest-api-versioning-the-right-way
https://stackoverflow.com/questions/32228300/how-to-prevent-my-snackbar-text-from-being-truncated-on-android

Checklist

Please, go through these checks before submitting the PR.

  • [ x ] You have not changed whitespace unnecessarily (it makes diffs hard to read)
  • [ x ] You have a descriptive commit message with a short title (first line, max 50 chars).
  • [ x ] Your code follows the style of the project (e.g. never omit braces in if statements)
  • [ x ] You have commented your code, particularly in hard-to-understand areas
  • [ x ] You have performed a self-review of your own code

@krmanik
Copy link
Member Author

krmanik commented Jun 21, 2020

This is clean PR for api versioning earlier one #6377 have conflicts. This may not have conflicts.

Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

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

@mikehardy These are mostly nits. Your thoughts?

Copy link
Member

@david-allison david-allison left a 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! Implementer's choice on whether more refactoring should occur.

Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

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

Few things that extraction to the class has raised.

RE: getHashCode, it'll be slightly complex. Probably best to remove .equals(), rather than implement it. If you do implement it, do it over the int array.

@krmanik
Copy link
Member Author

krmanik commented Jun 27, 2020

I will update it as suggested.

@mikehardy
Copy link
Member

Hey guys, SemVer is actually kind of complicated. We can just re-use this library, it already implements the Comparable interface as well: https://github.com/zafarkhaja/jsemver

Let's do that and not add code we don't need to

@krmanik
Copy link
Member Author

krmanik commented Jun 28, 2020

I have implemented it. It is far more easier than my implementation. But I have learned new things. Thanks

@mikehardy
Copy link
Member

Yeah, I think there is value in really looking deeply at semver to understand how much they really pack into it and how as even a very small problem domain it is still hard to get right! Then just using (and contributing to) a general-purpose library is the right way to go in in the end :)

@krmanik
Copy link
Member Author

krmanik commented Jun 30, 2020

Are there any improvements to this?

Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

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

Two comments - we'll need to improve the error messages as they'll confuse users.

private boolean requireApiVersion(String apiVer) {

Version mVersionCurrent = Version.valueOf(sCurrentJsApiVersion);
Version mVersionSupplied = Version.valueOf(apiVer);
Copy link
Member

Choose a reason for hiding this comment

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

Do you need validation here? What happens with an invalid version?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think apiVer passed to valueof so may be Sem Ver library may have internal check for invalid input.

Copy link
Member

Choose a reason for hiding this comment

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

What happens? Does it throw an exception? If not, which code path would it take?

Copy link
Member Author

Choose a reason for hiding this comment

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

Exception handling to be implemented.

<string name="api_version_no_developer_contact">This card uses unsupported AnkiDroid features. View the wiki to resolve this manually.</string>
<string name="invalid_json_data">Card provided invalid data. %s</string>
<string name="valid_js_api_version">Please provide a valid JavaScript API. Current API version is %s</string>
<string name="update_js_api_version">Please update JavaScript API version. Current API version is %s</string>
Copy link
Member

Choose a reason for hiding this comment

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

We'll need to go through these strings and make them user-friendly. Can't think about how to do this right now.

Possibly with error codes that can be given to a developer.

Copy link
Member Author

Choose a reason for hiding this comment

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

So error code should also defined.

Copy link
Member

Choose a reason for hiding this comment

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

We need some way of telling a user "something went wrong, it's not AnkiDroid's fault, please contact the deck author", but with additional information for the deck author to handle.

Copy link
Member Author

Choose a reason for hiding this comment

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

Okay, I will update it

Version mVersionCurrent = Version.valueOf(sCurrentJsApiVersion);
Version mVersionSupplied = Version.valueOf(apiVer);

if (mVersionCurrent.equals(mVersionSupplied)) {
Copy link
Member

@david-allison david-allison Jun 30, 2020

Choose a reason for hiding this comment

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

@mikehardy - I don't know enough about semVer to handle this one. What do we want here? We're going to get a lot of API version increases, and at what point do we want to say "break all API clients", and how do we provide a warning, or allow clients to update while keeping the legacy code going.

Copy link
Member

Choose a reason for hiding this comment

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

great question. So semVer allows for "compatible version range specification".
You always assume the requested version range will work

Ranges may be unbounded, saying just "anything higher than X.Y.Z is good". In practice most ranges are like that.

You just do a quick match and and if the requested API range is within our current API range, it's good to go. If it is not, then you say "Current AnkiDroid Javascript API is incompatible with the range requested by your template. Contact the author XXX or click here for more info" (or similar)

This link https://nodesource.com/blog/semver-a-primer/ has a good explanation of "Semver Ranges" with examples of how they are specified and what they mean.

Semver by itself is actually not useful without the range specification and comparison.

Thank goodness the library I pointed to implements it already or it would be nasty :-) https://github.com/zafarkhaja/jsemver#semver-expressions-api-ranges

Copy link
Member Author

Choose a reason for hiding this comment

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

I will update in between ranges.

@david-allison david-allison changed the title apiVersioning and developerContact implementation for AndkiDroid functions call from WebView apiVersioning and developerContact implementation for AnkiDroid functions call from WebView Jun 30, 2020
@krmanik krmanik requested a review from david-allison July 2, 2020 16:25
@krmanik krmanik force-pushed the js-api-version branch 2 times, most recently from d127e55 to ef8cdcb Compare July 4, 2020 21:19
@krmanik
Copy link
Member Author

krmanik commented Jul 27, 2020

Are there any improvement to these implementations?

@david-allison david-allison removed the Needs Author Reply Waiting for a reply from the original author label Aug 4, 2020
Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

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

A few queries about variables which aren't reset when a new card is shown, this leaves the Viewer with an incorrect state.

Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

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

Two minor requests - but nothing to stop this going in.

Thanks so much for your patience, looks awesome!

return false;
}
} catch (Exception e) {
Timber.i(e, "requireApiVersion::exception");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Timber.i(e, "requireApiVersion::exception");
Timber.w(e, "requireApiVersion::exception");

@@ -3531,12 +3643,58 @@ protected void showTagsDialog() {
showDialogFragment(dialog);
}

// list of api that can be accessed
private final String[] sApiList = {"toggleFlag", "markCard"};
Copy link
Member

Choose a reason for hiding this comment

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

Would be better at the top of the class

@david-allison
Copy link
Member

Needs a rebase onto current master to fix the CI failure. master was broken for a short while

@krmanik
Copy link
Member Author

krmanik commented Aug 6, 2020

To be updated

Copy link
Member

@mikehardy mikehardy left a comment

Choose a reason for hiding this comment

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

I had two minor nitpicks on variable naming to maintain consistency
But otherwise, I think this is good to go also, I'm excited to see this out there in use!

@mikehardy mikehardy added Needs Author Reply Waiting for a reply from the original author Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) and removed Needs Review labels Aug 7, 2020
Copy link
Member

@mikehardy mikehardy left a comment

Choose a reason for hiding this comment

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

Approved! 🤜 🤛

@mikehardy mikehardy removed Needs Author Reply Waiting for a reply from the original author Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) labels Aug 7, 2020
@mikehardy mikehardy merged commit 677eb00 into ankidroid:master Aug 7, 2020
@david-allison david-allison added this to the 2.13 release milestone Sep 7, 2020
@krmanik krmanik deleted the js-api-version branch July 10, 2021 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

implement AbstractFlashcardViewer / Javascript API versioning
3 participants