update fav boost accounts for stale views (#510)

This commit is contained in:
Nolan Lawson 2018-08-28 06:45:15 -07:00 committed by GitHub
parent 6d50c65352
commit 01b1d083a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 135 additions and 3 deletions

View File

@ -12,9 +12,22 @@ import {
getTimeline as getTimelineFromDatabase getTimeline as getTimelineFromDatabase
} from '../_database/timelines/pagination' } from '../_database/timelines/pagination'
import { getStatus, getStatusContext } from '../_api/statuses' import { getStatus, getStatusContext } from '../_api/statuses'
import { emit } from '../_utils/eventBus'
const FETCH_LIMIT = 20 const FETCH_LIMIT = 20
async function storeFreshTimelineItemsInDatabase (instanceName, timelineName, items) {
await insertTimelineItemsInDatabase(instanceName, timelineName, items)
if (timelineName.startsWith('status/')) {
// For status threads, we want to be sure to update the favorite/reblog counts even if
// this is a stale "view" of the status. See 119-status-counts-update.js for
// an example of why we need this.
items.forEach(item => {
emit('statusUpdated', item)
})
}
}
async function fetchTimelineItemsFromNetwork (instanceName, accessToken, timelineName, lastTimelineItemId) { async function fetchTimelineItemsFromNetwork (instanceName, accessToken, timelineName, lastTimelineItemId) {
if (timelineName.startsWith('status/')) { // special case - this is a list of descendents and ancestors if (timelineName.startsWith('status/')) { // special case - this is a list of descendents and ancestors
let statusId = timelineName.split('/').slice(-1)[0] let statusId = timelineName.split('/').slice(-1)[0]
@ -37,7 +50,7 @@ async function fetchTimelineItems (instanceName, accessToken, timelineName, last
} else { } else {
try { try {
items = await fetchTimelineItemsFromNetwork(instanceName, accessToken, timelineName, lastTimelineItemId) items = await fetchTimelineItemsFromNetwork(instanceName, accessToken, timelineName, lastTimelineItemId)
/* no await */ insertTimelineItemsInDatabase(instanceName, timelineName, items) /* no await */ storeFreshTimelineItemsInDatabase(instanceName, timelineName, items)
} catch (e) { } catch (e) {
console.error(e) console.error(e)
toast.say('Internet request failed. Showing offline content.') toast.say('Internet request failed. Showing offline content.')

View File

@ -133,16 +133,43 @@
import ExternalLink from '../ExternalLink.html' import ExternalLink from '../ExternalLink.html'
import { store } from '../../_store/store' import { store } from '../../_store/store'
import { getDateFormatter, getShortDateFormatter } from '../../_utils/formatters' import { getDateFormatter, getShortDateFormatter } from '../../_utils/formatters'
import { on } from '../../_utils/eventBus'
export default { export default {
oncreate () {
let { originalStatusId } = this.get()
on('statusUpdated', this, status => {
if (status.id === originalStatusId) {
this.set({
overrideNumReblogs: status.reblogs_count || 0,
overrideNumFavs: status.favourites_count || 0
})
}
})
},
store: () => store, store: () => store,
data: () => ({
overrideNumReblogs: void 0,
overrideNumFavs: void 0
}),
computed: { computed: {
originalStatusId: ({ originalStatus }) => originalStatus.id,
application: ({ originalStatus }) => originalStatus.application, application: ({ originalStatus }) => originalStatus.application,
applicationName: ({ application }) => (application && application.name), applicationName: ({ application }) => (application && application.name),
applicationWebsite: ({ application }) => (application && application.website), applicationWebsite: ({ application }) => (application && application.website),
createdAtDate: ({ originalStatus }) => originalStatus.created_at, createdAtDate: ({ originalStatus }) => originalStatus.created_at,
numReblogs: ({ originalStatus }) => originalStatus.reblogs_count || 0, numReblogs: ({ overrideNumReblogs, originalStatus }) => {
numFavs: ({ originalStatus }) => originalStatus.favourites_count || 0, if (typeof overrideNumReblogs === 'number') {
return overrideNumReblogs
}
return originalStatus.reblogs_count || 0
},
numFavs: ({ overrideNumFavs, originalStatus }) => {
if (typeof overrideNumFavs === 'number') {
return overrideNumFavs
}
return originalStatus.favourites_count || 0
},
formattedDate: ({ createdAtDate, $isMobileSize }) => { formattedDate: ({ createdAtDate, $isMobileSize }) => {
let formatter = $isMobileSize ? getShortDateFormatter() : getDateFormatter() let formatter = $isMobileSize ? getShortDateFormatter() : getDateFormatter()
return formatter.format(new Date(createdAtDate)) return formatter.format(new Date(createdAtDate))

View File

@ -7,6 +7,7 @@ import { deleteStatus } from '../routes/_api/delete'
import { authorizeFollowRequest, getFollowRequests } from '../routes/_actions/followRequests' import { authorizeFollowRequest, getFollowRequests } from '../routes/_actions/followRequests'
import { followAccount, unfollowAccount } from '../routes/_api/follow' import { followAccount, unfollowAccount } from '../routes/_api/follow'
import { updateCredentials } from '../routes/_api/updateCredentials' import { updateCredentials } from '../routes/_api/updateCredentials'
import { reblogStatus } from '../routes/_api/reblog'
global.fetch = fetch global.fetch = fetch
global.File = FileApi.File global.File = FileApi.File
@ -18,6 +19,10 @@ export async function favoriteStatusAs (username, statusId) {
return favoriteStatus(instanceName, users[username].accessToken, statusId) return favoriteStatus(instanceName, users[username].accessToken, statusId)
} }
export async function reblogStatusAs (username, statusId) {
return reblogStatus(instanceName, users[username].accessToken, statusId)
}
export async function postAs (username, text) { export async function postAs (username, text) {
return postStatus(instanceName, users[username].accessToken, text, return postStatus(instanceName, users[username].accessToken, text,
null, null, false, null, 'public') null, null, false, null, 'public')

View File

@ -0,0 +1,87 @@
import { loginAsFoobar } from '../roles'
import {
getFavoritesCount,
getNthStatus, getNthStatusContent, getReblogsCount, homeNavButton
} from '../utils'
import { favoriteStatusAs, postAs, reblogStatusAs } from '../serverActions'
fixture`119-status-counts-update.js`
.page`http://localhost:4002`
test('Fav stats update', async t => {
let status = await postAs('foobar', 'hey hello look at this toot')
let statusId = status.id
await favoriteStatusAs('admin', statusId)
await loginAsFoobar(t)
await t
.expect(getNthStatusContent(0).innerText).contains('hey hello look at this toot')
.click(getNthStatus(0))
.expect(getFavoritesCount()).eql(1)
.click(homeNavButton)
await favoriteStatusAs('quux', statusId)
await t
.click(getNthStatus(0))
.expect(getFavoritesCount()).eql(2)
.click(homeNavButton)
await favoriteStatusAs('baz', statusId)
await t
.click(getNthStatus(0))
.expect(getFavoritesCount()).eql(3)
.click(homeNavButton)
await favoriteStatusAs('LockedAccount', statusId)
await t
.click(getNthStatus(0))
.expect(getFavoritesCount()).eql(4)
})
test('Reblog stats update', async t => {
let status = await postAs('foobar', 'oh why hello it looks like another toot')
let statusId = status.id
await reblogStatusAs('admin', statusId)
await loginAsFoobar(t)
await t
.expect(getNthStatusContent(0).innerText).contains('oh why hello it looks like another toot')
.click(getNthStatus(0))
.expect(getReblogsCount()).eql(1)
.click(homeNavButton)
await reblogStatusAs('quux', statusId)
await t
.click(getNthStatus(0))
.expect(getReblogsCount()).eql(2)
.click(homeNavButton)
await reblogStatusAs('baz', statusId)
await t
.click(getNthStatus(0))
.expect(getReblogsCount()).eql(3)
.click(homeNavButton)
await reblogStatusAs('LockedAccount', statusId)
await t
.click(getNthStatus(0))
.expect(getReblogsCount()).eql(4)
})
test('Fav and reblog stats update for a boosted toot', async t => {
let status = await postAs('ExternalLinks', 'this will get boosted')
let statusId = status.id
await reblogStatusAs('admin', statusId)
await favoriteStatusAs('admin', statusId)
await favoriteStatusAs('quux', statusId)
await loginAsFoobar(t)
await t
.expect(getNthStatusContent(0).innerText).contains('this will get boosted')
.click(getNthStatus(0))
.expect(getReblogsCount()).eql(1)
.expect(getFavoritesCount()).eql(2)
.click(homeNavButton)
await favoriteStatusAs('baz', statusId)
await t
.click(getNthStatus(0))
.expect(getReblogsCount()).eql(1)
.expect(getFavoritesCount()).eql(3)
.click(homeNavButton)
await favoriteStatusAs('LockedAccount', statusId)
await t
.click(getNthStatus(0))
.expect(getReblogsCount()).eql(1)
.expect(getFavoritesCount()).eql(4)
})