plaid icon indicating copy to clipboard operation
plaid copied to clipboard

[Bug] Upvote count does not decrease when an upvote is removed.

Open tiembo opened this issue 5 years ago • 2 comments

To reproduce:

  • Go to a post and tap the upvote button. Upvote count increases by 1
  • Tap the upvote button again. Count does not decrease by one.

Note - backing out of the post detail view and then loading the detail view again will result in the proper upvotes being displayed.

tiembo avatar Nov 02 '18 20:11 tiembo

I think that's a lacking feature, not a bug 😅 The DesignerNewsService only has POST /api/v2/upvotes but hasn't got DELETE /api/v2/upvotes yet.

This could be a related bug though:

  • go to a post with X upvotes and tap the upvote button. upvote count becomes X+1
  • press back, and load it again. upvote count is X

This is because the response from upvotes doesn't get saved (see the next comment though, can't save it without checking response values) and I guess the second time it loads the post, it's loading it from disk and not refreshing so

loading the detail view again will result in the proper upvotes being displayed.

is not quite right.

upvotes

ataulm avatar Nov 02 '18 22:11 ataulm

Sequential calls to upvote a story /api/v2/upvotes/ will toggle the vote. This is undocumented in the API as far as I could see. Using the @DELETE method that's documented to undo a vote will result in an error for now.

This means that it's not sufficient to check for a successful response to determine if an upvote succeeded (or undo upvote succeeded). We need to check the value of the upvote block in the upvotes array (I assume it'll just be one item in the array) to see if it's null or not:

{
    "upvotes": [
        {
            "id": "493986", // the ID of the upvote
            "href": "https://api.designernews.co/api/v2/upvotes/493986",
            "links": {
                "user": "95963", // the user ID
                "story": "98237" // the ID of the upvoted resource
            },
            "created_at": "2018-11-02T23:15:03Z",
            "updated_at": "2018-11-02T23:15:03Z"
        }
    ],
    ...
}

The response when undo-ing an upvote (same API call):

{
    "upvotes": [
        null
    ],
    ...
}

/api/v2/me returns a user resource which has the list of upvotes for the logged in user:

{
    "users": [
        {
            "id": "95963",
            ...
            "links": {
                ...
                "upvotes": [
                    "493989", // the ID of the upvote
                    "494052"
                ]
            },
            ...

Locally, we should keep this list of upvoted resources cached, and update it whenever the user performs an upvote/undo-upvote in the app. It should be synced with the remote user resource regularly too (maybe on opening the app).

Then, the state of the upvote button in story details should be dependent on this cached value. The story will contain a list of upvote IDs:

{
    "stories": [
        {
            "id": "98279",
            "href": "https://api.designernews.co/api/v2/stories/98279",
            "links": {
                ...
                "upvotes": [
                    "493559",
                    "493566",
                    "493567",
                    ...

and whenever the user upvotes a story from in the app, the local story cache (StoriesRepository), should be updated with the upvote ID, or it should be removed if the response indicates that it's null (deleted).

Finally, story details could sync individual stories from the network whenever the details are opened, falling back on the cached version if the network fails to load it - this would sync the upvote state if the user has upvoted/removed an upvote from a different device.

Or just ditch the upvote mechanism in Plaid :eyes:

ataulm avatar Nov 02 '18 23:11 ataulm