fix: empty timelines no longer show infinite loading spinner (#1854)
Instead, they now show "Nothing to show." I only fixed this for VirtualList because List should never be non-empty (threads). Fixes #1763
This commit is contained in:
parent
55b9c8d3b8
commit
430ab4db4c
|
@ -104,9 +104,9 @@ async function addPagedTimelineItems (instanceName, timelineName, items) {
|
|||
}
|
||||
|
||||
export async function addPagedTimelineItemSummaries (instanceName, timelineName, newSummaries) {
|
||||
const oldSummaries = store.getForTimeline(instanceName, timelineName, 'timelineItemSummaries') || []
|
||||
const oldSummaries = store.getForTimeline(instanceName, timelineName, 'timelineItemSummaries')
|
||||
|
||||
const mergedSummaries = uniqBy(concat(oldSummaries, newSummaries), byId)
|
||||
const mergedSummaries = uniqBy(concat(oldSummaries || [], newSummaries), byId)
|
||||
|
||||
if (!isEqual(oldSummaries, mergedSummaries)) {
|
||||
store.setForTimeline(instanceName, timelineName, { timelineItemSummaries: mergedSummaries })
|
||||
|
@ -160,10 +160,10 @@ async function addTimelineItems (instanceName, timelineName, items, stale) {
|
|||
}
|
||||
|
||||
export async function addTimelineItemSummaries (instanceName, timelineName, newSummaries, newStale) {
|
||||
const oldSummaries = store.getForTimeline(instanceName, timelineName, 'timelineItemSummaries') || []
|
||||
const oldSummaries = store.getForTimeline(instanceName, timelineName, 'timelineItemSummaries')
|
||||
const oldStale = store.getForTimeline(instanceName, timelineName, 'timelineItemSummariesAreStale')
|
||||
|
||||
const mergedSummaries = uniqBy(mergeArrays(oldSummaries, newSummaries, compareTimelineItemSummaries), byId)
|
||||
const mergedSummaries = uniqBy(mergeArrays(oldSummaries || [], newSummaries, compareTimelineItemSummaries), byId)
|
||||
|
||||
if (!isEqual(oldSummaries, mergedSummaries)) {
|
||||
store.setForTimeline(instanceName, timelineName, { timelineItemSummaries: mergedSummaries })
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
index={visibleItem.index}
|
||||
/>
|
||||
{/each}
|
||||
{#if !$visibleItems.length}
|
||||
<div class="nothing-to-show">
|
||||
Nothing to show.
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if $showFooter}
|
||||
<VirtualListFooter component={footerComponent} />
|
||||
|
@ -23,6 +28,12 @@
|
|||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.nothing-to-show {
|
||||
font-size: 1.1em;
|
||||
width: 100%;
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import VirtualListContainer from './VirtualListContainer.html'
|
||||
|
|
|
@ -37,6 +37,12 @@ export async function postWithSpoilerAndPrivacyAs (username, text, spoiler, priv
|
|||
null, null, true, spoiler, privacy)
|
||||
}
|
||||
|
||||
export async function postStatusWithMediaAs (username, status, filename, alt, sensitive) {
|
||||
const mediaResponse = await submitMedia(users[username].accessToken, filename, alt)
|
||||
return postStatus(instanceName, users[username].accessToken, status,
|
||||
null, [mediaResponse.id], !!sensitive, null, 'public')
|
||||
}
|
||||
|
||||
export async function postEmptyStatusWithMediaAs (username, filename, alt, sensitive) {
|
||||
const mediaResponse = await submitMedia(users[username].accessToken, filename, alt)
|
||||
return postStatus(instanceName, users[username].accessToken, '',
|
||||
|
|
28
tests/spec/039-empty-list.js
Normal file
28
tests/spec/039-empty-list.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import {
|
||||
communityNavButton,
|
||||
getUrl, timeline
|
||||
} from '../utils'
|
||||
import { loginAsFoobar } from '../roles'
|
||||
import { Selector as $ } from 'testcafe'
|
||||
|
||||
fixture`039-empty-list.js`
|
||||
.page`http://localhost:4002`
|
||||
|
||||
test('Can show an empty list of bookmarks', async t => {
|
||||
await loginAsFoobar(t)
|
||||
await t
|
||||
.click(communityNavButton)
|
||||
.click($('a').withText('Bookmarks'))
|
||||
.expect(getUrl()).contains('bookmarks')
|
||||
.expect(timeline.innerText).contains('Nothing to show.')
|
||||
})
|
||||
|
||||
test('Can show an empty list of media', async t => {
|
||||
await loginAsFoobar(t)
|
||||
await t
|
||||
.click($('a').withText('quux'))
|
||||
.expect(getUrl()).contains('accounts/3')
|
||||
.click($('a').withText('Media'))
|
||||
.expect(getUrl()).contains('accounts/3/media')
|
||||
.expect(timeline.innerText).contains('Nothing to show.')
|
||||
})
|
22
tests/spec/136-empty-list.js
Normal file
22
tests/spec/136-empty-list.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
import {
|
||||
getNthStatus, sleep,
|
||||
timeline
|
||||
} from '../utils'
|
||||
import { loginAsFoobar } from '../roles'
|
||||
import { postStatusWithMediaAs } from '../serverActions'
|
||||
|
||||
fixture`136-empty-list.js`
|
||||
.page`http://localhost:4002`
|
||||
|
||||
test('An empty list can become non-empty as results stream in', async t => {
|
||||
await loginAsFoobar(t)
|
||||
await t
|
||||
.expect(getNthStatus(1).exists).ok()
|
||||
.navigateTo('/tags/sweetkitty')
|
||||
.expect(timeline.innerText).contains('Nothing to show.')
|
||||
|
||||
await sleep(500)
|
||||
await postStatusWithMediaAs('quux', 'look at this sweet kitty #sweetkitty', 'kitten2.jpg', 'hello kitty')
|
||||
await t
|
||||
.expect(getNthStatus(1).innerText).contains('look at this sweet kitty', { timeout: 20000 })
|
||||
})
|
|
@ -2,6 +2,7 @@ import { ClientFunction as exec, Selector as $ } from 'testcafe'
|
|||
import * as images from './images'
|
||||
import * as blobUtils from './blobUtils'
|
||||
|
||||
export const timeline = $('[role=feed]')
|
||||
export const settingsButton = $('nav a[aria-label=Settings]')
|
||||
export const instanceInput = $('#instanceInput')
|
||||
export const modalDialog = $('.modal-dialog')
|
||||
|
|
Loading…
Reference in a new issue