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

Async actions (favorite/boost buttons) should show spinner while waiting. #632

Open
ericlathrop opened this issue Apr 20, 2024 · 4 comments

Comments

@ericlathrop
Copy link

Is your feature request related to a problem? Please describe.
Sometimes when I tap the favorite or boost buttons it takes a while to highlight. I'm guessing this be because it's waiting on the network.

Describe the solution you'd like
I think the app should replace the button wigh a loading spinner or something so I can know if its actually doing something.

Describe alternatives you've considered
There could be a global spinner, but I think each button having a separate spinner would be more clear.

@nikclayton
Copy link
Contributor

I've got a slightly different idea in mind (some of it already works like this).

Tapping a button (e.g., bookmark) should toggle the state immediately, and send an async network request to make the change on the backend.

If the backend request fails (possibly after some number of retries) the user is shown a "Retry" snackbar, and the button state resets to its previous value.

Although there's a couple of things that make this a bit more complicated in the UX:

  1. Suppose you bookmark a post, then scroll up several pages, and then the bookmark operation fails. The error message has to give you enough context to know what post is having a problem.

  2. Suppose you bookmark a post on your home timeline, then open your bookmarks timeline before the bookmark operation completes. The user is surprised that the post they just bookmarked doesn't appear in that list. And the error message about the bookmark operation failing won't appear, because it's tied to the previous screen...

I have thought about maintaining a persistent queue of outbound operations; bookmark a post and the network operation starts immediately, and if it fails the request is put in a queue to retry later.

But that opens thorny questions like "Should the user be able to see the queue?", "If they can see the queue, can they change it (e..g, delete a pending request)?", and "Should the queue be checked when displaying posts to indicate if a post has a pending operation associated with it?".

@ericlathrop
Copy link
Author

I don't like that idea of "lying" and showing the button highlighted when it's not actually completed on the server because it's not reliable. Sometimes I'll favorite something, the button highlights, then open the photo on the same post, and when I close the photo the favorite button is dimmed out, so I tap it again. No idea if it sends it twice or what happens.

I like the idea of a queue of all pending async actions and the buttons checking those for determining their state. I don't think users need to see the queue, because requests will drain naturally and if they error the current popup message is fine.

@nikclayton
Copy link
Contributor

I don't like that idea of "lying" and showing the button highlighted when it's not actually completed on the server because it's not reliable

I disagree with this a bit because I think it's a good idea for the UI to reflect the common case. Most of the time these operations are going to succeed. If every UI interaction that required a network request replaced the button with a spinning circle there'd be a lot of them in the UI. And users might start looking for ways to cancel those operations.

There are mitigations that can be taken; e.g., perform the request, and then wait for up to 500ms

  • If it completes within that time change the button state to show the result
  • Show the spinning circle

That's still a lot more complexity in the code for a (hopefully) rare case, which is why I haven't prioritised that sort of work yet.

Sometimes I'll favorite something, the button highlights, then open the photo on the same post, and when I close the photo the favorite button is dimmed out

That's a bug. If you didn't get an error message then it should show as favourited because the operation succeeded or is in progress. There are definitely places in the code where that doesn't happen properly yet.

Background

Pachli inherits a Tusky design choice that I haven't fixed yet. Only one timeline is cached to local storage, the home timeline. Everything else (notifications, local, federated, bookmarks, etc) is ephemeral, and re-fetched every time. So all the code for interacting with a post and maintaining local state has to be duplicated, and some of it's not in sync. That's why, for example, translations only work on the home timeline at the moment.

@mileskrell
Copy link
Contributor

mileskrell commented Apr 30, 2024

Tapping a button (e.g., bookmark) should toggle the state immediately, and send an async network request to make the change on the backend.

I generally see this "update the UI to reflect success immediately and then do the request in the background" pattern referred to as "optimistic UI", and I know a lot of folks are fans of it. My concern is that implementing this without also adding a request queue would make it hard to know when a request had failed. Users would need to wait for an unclear period of time before they could assume that that favoriting or boosting a post had (probably) succeeded. This would be a problem in situations with poor network connectivity.

I somewhat agree with the sentiment that optimistic UI is "lying" to users. I prefer for the UI to reflect reality, even though I know that many non-technical users will simply assume that apps that implement optimistic UI are faster than the ones that don't and may therefore prefer apps with optimistic UI. However, I would be okay with optimistic UI if we also added a queue of pending requests, such that the user has a guarantee that the "success" button state at least indicates that the request will definitely eventually succeed.

But if our primary goal is just to add immediate feedback, then loading indicators do seem like they would accomplish that while requiring less work to build. We would still want to have a reasonably short timeout, after which point the button would revert to its initial state and we would show an error modal/toast/snackbar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Todo
Development

No branches or pull requests

3 participants