Skip to content

fix js-api: return parsed object from nextTime/deckName - #21497

Open
krmanik wants to merge 3 commits into
mainfrom
js-api
Open

fix js-api: return parsed object from nextTime/deckName#21497
krmanik wants to merge 3 commits into
mainfrom
js-api

Conversation

@krmanik

@krmanik krmanik commented Aug 14, 2026

Copy link
Copy Markdown
Member

Assisted-by: Claude Sonnet 5

Purpose / Description

Describe the problem or feature and motivation

ankiGetNextTime1-4 and ankiGetDeckName returned the raw response text instead of a parsed object, unlike the other API methods. The backend already emits valid JSON for these endpoints via ApiResult.String.

BREAKING CHANGE: these five methods now resolve to an object rather than a JSON string. Cards calling JSON.parse() on the result must drop it. API version bumped to 0.0.4.

Fixes

Approach

How does this change address the problem?

Removed the endpoint.includes("nextTime") || endpoint.includes("deckName") special case in handleRequest (js-api.js) so every endpoint goes through JSON.parse. Nothing else needed changing: AnkiDroidJsAPI.convertToByteArray(apiContract, string) already wraps these values in ApiResult.String, whose toString() builds a JSONObject — the same {"success": …, "value": …} envelope used by every other endpoint. The special case dates back to the sync-to-async conversion (#14564) and had no counterpart on the backend.

CURRENT_JS_API_VERSION bumped to 0.0.4 (MINIMUM_JS_API_VERSION left at 0.0.3), and the version comment in js-api.js updated to match. Cards still supplying 0.0.3 keep working and get the "update your API version" snackbar.

How Has This Been Tested?

Manually, in the reviewer WebView, using the reproduction from the issue:

const jsApiContract = { version: "0.0.4", developer: "test@test.com" };
const api = new AnkiDroidJS(jsApiContract);
api.ankiGetDeckName().then(r => console.log(typeof r, r));
api.ankiGetNextTime1().then(r => console.log(typeof r, r));

Before: string {"success" : true, "value": "…"}. After: object {success: true, value: "…"}, matching ankiIsDisplayingAnswer and the rest.

Learning (optional, can help others)

Describe the research stage

Links to blog posts, patterns, libraries or addons used to solve this problem

Checklist

Please, go through these checks before submitting the PR.

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

`ankiGetNextTime1-4` and `ankiGetDeckName` returned the raw response
text instead of a parsed object, unlike the other API methods. The
backend already emits valid JSON for these endpoints via
`ApiResult.String`, so the special case in `handleRequest` served no
purpose.

BREAKING CHANGE: these five methods now resolve to an object rather
than a JSON string. Cards calling `JSON.parse()` on the result must
drop it. API version bumped to 0.0.4.
Copilot AI lite review requested due to automatic review settings August 14, 2026 11:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the AnkiDroid JavaScript API so ankiGetNextTime1-4 and ankiGetDeckName resolve to parsed JavaScript objects (consistent with other JS API methods) rather than returning raw JSON strings, and bumps the declared JS API version accordingly.

Changes:

  • Bump CURRENT_JS_API_VERSION from 0.0.3 to 0.0.4.
  • Remove the JS-side special-casing that returned raw response.text() for nextTime* and deckName, so responses are parsed via JSON.parse() like other endpoints.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidJsAPIConstants.kt Bumps the current JS API version to 0.0.4.
AnkiDroid/src/main/assets/scripts/js-api.js Removes endpoint-specific raw string returns and updates the version header comment.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 109 to 110
const responseData = await response.text();
if (endpoint.includes("nextTime") || endpoint.includes("deckName")) {
return responseData;
}
return JSON.parse(responseData);
@krmanik

krmanik commented Aug 14, 2026

Copy link
Copy Markdown
Member Author

The js addons files need to be removed, because new js addons for whole ecosystem is under consideration.

Follow-up to the 0.0.4 bump in AnkiDroidJsAPIConstants: the JS API
contract helper and addon test fixtures still declared 0.0.3.
Comment thread AnkiDroid/src/main/assets/scripts/js-api.js
@david-allison

Copy link
Copy Markdown
Member

requireApiVersion needs improving before this strategy goes live: it executes a snackbar on each call, and the UX is suboptimal - many users would not be in control of their card templates

@david-allison david-allison added the Needs Author Reply Waiting for a reply from the original author label Aug 15, 2026
@krmanik

krmanik commented Aug 15, 2026

Copy link
Copy Markdown
Member Author

requireApiVersion needs improving before this strategy goes live: it executes a snackbar on each call, and the UX is suboptimal - many users would not be in control of their card templates

Now snackbar call once.

requireApiVersion() runs on every js api request, so a card declaring an
outdated version showed a snackbar for each call it made. The message asks
the user to contact the template developer, which most users cannot act on,
let alone repeatedly. Track the contracts already reported and show each
message once per reviewer session, including the developer contact snackbar
shown for unsupported calls.

Also keep the pre-0.0.4 raw string response for nextTime*/deckName when the
card declares 0.0.3, which is still accepted per MINIMUM_JS_API_VERSION,
rather than changing the return type under those cards.
@david-allison david-allison removed the Needs Author Reply Waiting for a reply from the original author label Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ankiGetDeckName api returns JSON-encoded string instead of a parsed javascript object

3 participants