diff options
author | Ansh Nanda <anshnanda10@gmail.com> | 2023-05-22 16:35:37 -0700 |
---|---|---|
committer | Ansh Nanda <anshnanda10@gmail.com> | 2023-05-22 16:35:37 -0700 |
commit | 64e303d911d351a2f492a23ae97207e5c6035b6e (patch) | |
tree | d0ce38c7d9e41ce1ae6b9623352864bde972071f /src | |
parent | 762bd15ed625c9a7d50b0ee832a1422bac3321eb (diff) | |
download | voidsky-64e303d911d351a2f492a23ae97207e5c6035b6e.tar.zst |
optimistic updates for liking custom feeds
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/async/revertible.ts | 16 | ||||
-rw-r--r-- | src/state/models/feeds/custom-feed.ts | 36 |
2 files changed, 40 insertions, 12 deletions
diff --git a/src/lib/async/revertible.ts b/src/lib/async/revertible.ts index 3c8e3e8f9..43383b61e 100644 --- a/src/lib/async/revertible.ts +++ b/src/lib/async/revertible.ts @@ -4,6 +4,22 @@ import set from 'lodash.set' const ongoingActions = new Set<any>() +/** + * This is a TypeScript function that optimistically updates data on the client-side before sending a + * request to the server and rolling back changes if the request fails. + * @param {T} model - The object or record that needs to be updated optimistically. + * @param preUpdate - `preUpdate` is a function that is called before the server update is executed. It + * can be used to perform any necessary actions or updates on the model or UI before the server update + * is initiated. + * @param serverUpdate - `serverUpdate` is a function that returns a Promise representing the server + * update operation. This function is called after the previous state of the model has been recorded + * and the `preUpdate` function has been executed. If the server update is successful, the `postUpdate` + * function is called with the result + * @param [postUpdate] - `postUpdate` is an optional callback function that will be called after the + * server update is successful. It takes in the response from the server update as its parameter. If + * this parameter is not provided, nothing will happen after the server update. + * @returns A Promise that resolves to `void`. + */ export const updateDataOptimistically = async < T extends Record<string, any>, U, diff --git a/src/state/models/feeds/custom-feed.ts b/src/state/models/feeds/custom-feed.ts index e457d2d1e..9ac69ac28 100644 --- a/src/state/models/feeds/custom-feed.ts +++ b/src/state/models/feeds/custom-feed.ts @@ -2,6 +2,7 @@ import {AppBskyFeedDefs} from '@atproto/api' import {makeAutoObservable, runInAction} from 'mobx' import {RootStoreModel} from 'state/models/root-store' import {sanitizeDisplayName} from 'lib/strings/display-names' +import {updateDataOptimistically} from 'lib/async/revertible' export class CustomFeedModel { // data @@ -58,12 +59,19 @@ export class CustomFeedModel { async like() { try { - const res = await this.rootStore.agent.like(this.data.uri, this.data.cid) - runInAction(() => { - this.data.viewer = this.data.viewer || {} - this.data.viewer.like = res.uri - this.data.likeCount = (this.data.likeCount || 0) + 1 - }) + await updateDataOptimistically( + this.data, + () => { + this.data.viewer = this.data.viewer || {} + this.data.viewer.like = 'pending' + this.data.likeCount = (this.data.likeCount || 0) + 1 + }, + () => this.rootStore.agent.like(this.data.uri, this.data.cid), + res => { + this.data.viewer = this.data.viewer || {} + this.data.viewer.like = res.uri + }, + ) } catch (e: any) { this.rootStore.log.error('Failed to like feed', e) } @@ -74,12 +82,16 @@ export class CustomFeedModel { return } try { - await this.rootStore.agent.deleteLike(this.data.viewer.like!) - runInAction(() => { - this.data.viewer = this.data.viewer || {} - this.data.viewer.like = undefined - this.data.likeCount = (this.data.likeCount || 1) - 1 - }) + const likeUri = this.data.viewer.like + await updateDataOptimistically( + this.data, + () => { + this.data.viewer = this.data.viewer || {} + this.data.viewer.like = undefined + this.data.likeCount = (this.data.likeCount || 1) - 1 + }, + () => this.rootStore.agent.deleteLike(likeUri), + ) } catch (e: any) { this.rootStore.log.error('Failed to unlike feed', e) } |