Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Optimistic rendering #382

Open
Open
@smashwilson

Description

@smashwilson

To improve the perceived responsiveness of git operations, we can use an optimistic rendering strategy throughout the package. When a git operation is requested, the UI should reflect the expected outcome immediately rather than waiting for the operation to actually complete.

For example:

  • A user double-clicks on a file to stage it.
  • The staging action is enqueued in the AsyncQueue of git operations.
  • The file moves from the unstaged list to the staged list on the very next render.
  • At some later event loop tick, the git operation completes, and the view accurately reflects the current states of the git index and working directory tree again.

Considerations

We'll need a consistent strategy for handling errors and failed operations. It would be jarring to stage a file and have it keep jumping back up to the unstaged list.

On a related note, we should decide how far we want to go to handle dependent operations and cancellability. The easiest route would be to ensure that optimistically rendered elements are read-only (you can't unstage an optimistically staged file until the index catches up). It would be possible, if complicated, to handle these though: if an operation hasn't begun yet it could be removed from the queue, for example, or operations could be explicitly linked to dependent state so that failed operations would propagate correctly... at some point we'll need to put a finite depth on that rabbit-hole.

It'd be nice to give users some subtle feedback that pending operations are still in progress. One idea would be to have a throbber in the status bar that animates while the view is known to be out of sync. We could also add animation or other indications directly to optimistically-rendered elements; for example, a filename rendered optimistically in the staged list could have its icon greyed out or at a lower alpha value and fade it in once the real index catches up.

Operations that touch the network (fetches, pushes and pulls) should likely be excluded from optimistic rendering and instead follow the current approach of disabling UI elements and blocking. Because these are "expected" to take more time to complete, optimistically rendering their results would cause doubt that they actually did anything. There's some grey area here about other operations like commit that I'd like to hear others' thoughts on.

Implementation

  • Introduce an Operation hierarchy into our models to represent a pending action. Each Operation implements two methods: one that returns a Promise performing the git command, and one that mutates the state of model objects (through a Repository argument, maybe) to reflect the change it will perform. Mutated model objects should likely be marked in some way (isOptimistic() === true?) to enable UI feedback.
  • Rather than storing Promises directly, AsyncQueue stores and executes Operations.
  • When the Repository is queried for its state, each Operation currently within the queue is given the opportunity to mutate its return value. The mutated state is then reported to the components for rendering.

Based on discussions with @kuychaco, @BinaryMuse and @nathansobo.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions