optimistic updates for fav/reblog
This commit is contained in:
		
							parent
							
								
									1786d737bb
								
							
						
					
					
						commit
						98b704f465
					
				
					 6 changed files with 52 additions and 18 deletions
				
			
		| 
						 | 
					@ -10,18 +10,16 @@ export async function setFavorited (statusId, favorited) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  let instanceName = store.get('currentInstance')
 | 
					  let instanceName = store.get('currentInstance')
 | 
				
			||||||
  let accessToken = store.get('accessToken')
 | 
					  let accessToken = store.get('accessToken')
 | 
				
			||||||
 | 
					  let networkPromise = favorited
 | 
				
			||||||
 | 
					    ? favoriteStatus(instanceName, accessToken, statusId)
 | 
				
			||||||
 | 
					    : unfavoriteStatus(instanceName, accessToken, statusId)
 | 
				
			||||||
 | 
					  store.setStatusFavorited(instanceName, statusId, favorited) // optimistic update
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    await (favorited
 | 
					    await networkPromise
 | 
				
			||||||
        ? favoriteStatus(instanceName, accessToken, statusId)
 | 
					 | 
				
			||||||
        : unfavoriteStatus(instanceName, accessToken, statusId))
 | 
					 | 
				
			||||||
    await database.setStatusFavorited(instanceName, statusId, favorited)
 | 
					    await database.setStatusFavorited(instanceName, statusId, favorited)
 | 
				
			||||||
    let statusModifications = store.get('statusModifications')
 | 
					 | 
				
			||||||
    let currentStatusModifications = statusModifications[instanceName] =
 | 
					 | 
				
			||||||
      (statusModifications[instanceName] || {favorites: {}, reblogs: {}})
 | 
					 | 
				
			||||||
    currentStatusModifications.favorites[statusId] = favorited
 | 
					 | 
				
			||||||
    store.set({statusModifications: statusModifications})
 | 
					 | 
				
			||||||
  } catch (e) {
 | 
					  } catch (e) {
 | 
				
			||||||
    console.error(e)
 | 
					    console.error(e)
 | 
				
			||||||
    toast.say(`Failed to ${favorited ? 'favorite' : 'unfavorite'}. ` + (e.message || ''))
 | 
					    toast.say(`Failed to ${favorited ? 'favorite' : 'unfavorite'}. ` + (e.message || ''))
 | 
				
			||||||
 | 
					    store.setStatusFavorited(instanceName, statusId, !favorited) // undo optimistic update
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,18 +10,16 @@ export async function setReblogged (statusId, reblogged) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  let instanceName = store.get('currentInstance')
 | 
					  let instanceName = store.get('currentInstance')
 | 
				
			||||||
  let accessToken = store.get('accessToken')
 | 
					  let accessToken = store.get('accessToken')
 | 
				
			||||||
 | 
					  let networkPromise = reblogged
 | 
				
			||||||
 | 
					    ? reblogStatus(instanceName, accessToken, statusId)
 | 
				
			||||||
 | 
					    : unreblogStatus(instanceName, accessToken, statusId)
 | 
				
			||||||
 | 
					  store.setStatusReblogged(instanceName, statusId, reblogged) // optimistic update
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    await (reblogged
 | 
					    await networkPromise
 | 
				
			||||||
        ? reblogStatus(instanceName, accessToken, statusId)
 | 
					 | 
				
			||||||
        : unreblogStatus(instanceName, accessToken, statusId))
 | 
					 | 
				
			||||||
    await database.setStatusReblogged(instanceName, statusId, reblogged)
 | 
					    await database.setStatusReblogged(instanceName, statusId, reblogged)
 | 
				
			||||||
    let statusModifications = store.get('statusModifications')
 | 
					 | 
				
			||||||
    let currentStatusModifications = statusModifications[instanceName] =
 | 
					 | 
				
			||||||
      (statusModifications[instanceName] || {favorites: {}, reblogs: {}})
 | 
					 | 
				
			||||||
    currentStatusModifications.reblogs[statusId] = reblogged
 | 
					 | 
				
			||||||
    store.set({statusModifications: statusModifications})
 | 
					 | 
				
			||||||
  } catch (e) {
 | 
					  } catch (e) {
 | 
				
			||||||
    console.error(e)
 | 
					    console.error(e)
 | 
				
			||||||
    toast.say(`Failed to ${reblogged ? 'boost' : 'unboost'}. ` + (e.message || ''))
 | 
					    toast.say(`Failed to ${reblogged ? 'boost' : 'unboost'}. ` + (e.message || ''))
 | 
				
			||||||
 | 
					    store.setStatusReblogged(instanceName, statusId, !reblogged) // undo optimistic update
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,9 @@
 | 
				
			||||||
import { timelineMixins } from './timelineMixins'
 | 
					import { timelineMixins } from './timelineMixins'
 | 
				
			||||||
import { instanceMixins } from './instanceMixins'
 | 
					import { instanceMixins } from './instanceMixins'
 | 
				
			||||||
 | 
					import { statusMixins } from './statusMixins'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function mixins (Store) {
 | 
					export function mixins (Store) {
 | 
				
			||||||
  instanceMixins(Store)
 | 
					  instanceMixins(Store)
 | 
				
			||||||
  timelineMixins(Store)
 | 
					  timelineMixins(Store)
 | 
				
			||||||
 | 
					  statusMixins(Store)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										22
									
								
								routes/_store/mixins/statusMixins.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								routes/_store/mixins/statusMixins.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					function getStatusModifications (store, instanceName) {
 | 
				
			||||||
 | 
					  let statusModifications = store.get('statusModifications')
 | 
				
			||||||
 | 
					  statusModifications[instanceName] = statusModifications[instanceName] || {
 | 
				
			||||||
 | 
					    favorites: {},
 | 
				
			||||||
 | 
					    reblogs: {}
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return statusModifications
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function statusMixins (Store) {
 | 
				
			||||||
 | 
					  Store.prototype.setStatusFavorited = function (instanceName, statusId, favorited) {
 | 
				
			||||||
 | 
					    let statusModifications = getStatusModifications(this, instanceName)
 | 
				
			||||||
 | 
					    statusModifications[instanceName].favorites[statusId] = favorited
 | 
				
			||||||
 | 
					    this.set({statusModifications})
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Store.prototype.setStatusReblogged = function (instanceName, statusId, reblogged) {
 | 
				
			||||||
 | 
					    let statusModifications = getStatusModifications(this, instanceName)
 | 
				
			||||||
 | 
					    statusModifications[instanceName].reblogs[statusId] = reblogged
 | 
				
			||||||
 | 
					    this.set({statusModifications})
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -16,3 +16,18 @@ export async function cacheFirstUpdateAfter (networkFetcher, dbFetcher, dbUpdate
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Make a change that we optimistically show to the user as successful, but which
 | 
				
			||||||
 | 
					// actually depends on a network operation. In the unlikely event that the network
 | 
				
			||||||
 | 
					// operation fails, revert the changes
 | 
				
			||||||
 | 
					export async function optimisticUpdate (doImmediately, networkUpdater, onSuccess, onFailure) {
 | 
				
			||||||
 | 
					  let networkPromise = networkUpdater()
 | 
				
			||||||
 | 
					  doImmediately()
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    let response = await networkPromise
 | 
				
			||||||
 | 
					    onSuccess(response)
 | 
				
			||||||
 | 
					  } catch (e) {
 | 
				
			||||||
 | 
					    console.error(e)
 | 
				
			||||||
 | 
					    onFailure(e)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,7 @@
 | 
				
			||||||
import { foobarRole } from '../roles'
 | 
					import { foobarRole } from '../roles'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  clickToNotificationsAndBackHome, forceOffline, forceOnline, getNthStatus, getUrl, homeNavButton,
 | 
					  clickToNotificationsAndBackHome, forceOffline, forceOnline, getNthStatus, getUrl, homeNavButton,
 | 
				
			||||||
  notificationsNavButton,
 | 
					  notificationsNavButton
 | 
				
			||||||
  sleep
 | 
					 | 
				
			||||||
} from '../utils'
 | 
					} from '../utils'
 | 
				
			||||||
import { deleteAs, postAs, postReplyAs } from '../serverActions'
 | 
					import { deleteAs, postAs, postReplyAs } from '../serverActions'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue