add infinite scrolling to local and federated timelines

pull/283/head
Dario Piotrowicz 2023-02-14 11:49:14 +00:00
rodzic d2a5ff122a
commit 91d6bb0503
4 zmienionych plików z 61 dodań i 26 usunięć

Wyświetl plik

@ -24,10 +24,10 @@ export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string },
)
export default component$(() => {
const statuses = statusesLoader.use()
const statuses = statusesLoader.use().value
return (
<StatusesPanel
initialStatuses={statuses.value}
initialStatuses={statuses}
fetchMoreStatuses={$(async (numOfCurrentStatuses: number) => {
let statuses: MastodonStatus[] = []
try {

Wyświetl plik

@ -1,11 +1,11 @@
import { component$ } from '@builder.io/qwik'
import { $, component$ } from '@builder.io/qwik'
import { MastodonStatus } from '~/types'
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
import Status from '~/components/Status'
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
import StickyHeader from '~/components/StickyHeader/StickyHeader'
import { getDocumentHead } from '~/utils/getDocumentHead'
import { RequestContext } from '@builder.io/qwik-city/middleware/request-handler'
import { StatusesPanel } from '~/components/StatusesPanel/StatusesPanel'
export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string }, Promise<MastodonStatus[]>>(
async ({ platform, html }) => {
@ -22,7 +22,7 @@ export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string },
)
export default component$(() => {
const statuses = statusesLoader.use()
const statuses = statusesLoader.use().value
return (
<>
@ -32,13 +32,22 @@ export default component$(() => {
<span>Federated timeline</span>
</div>
</StickyHeader>
{statuses.value.length > 0 ? (
statuses.value.map((status) => <Status status={status} />)
) : (
<div class="flex-1 grid place-items-center bg-wildebeest-600 text-center">
<p>Nothing to see right now. Check back later!</p>
</div>
)}
<StatusesPanel
initialStatuses={statuses}
fetchMoreStatuses={$(async (numOfCurrentStatuses: number) => {
let statuses: MastodonStatus[] = []
try {
const response = await fetch(`/api/v1/timelines/public?offset=${numOfCurrentStatuses}`)
if (response.ok) {
const results = await response.text()
statuses = JSON.parse(results)
}
} catch {
/* empty */
}
return statuses
})}
/>
</>
)
})

Wyświetl plik

@ -1,11 +1,11 @@
import { component$ } from '@builder.io/qwik'
import { $, component$ } from '@builder.io/qwik'
import { MastodonStatus } from '~/types'
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
import Status from '~/components/Status'
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
import StickyHeader from '~/components/StickyHeader/StickyHeader'
import { getDocumentHead } from '~/utils/getDocumentHead'
import { RequestContext } from '@builder.io/qwik-city/middleware/request-handler'
import { StatusesPanel } from '~/components/StatusesPanel/StatusesPanel'
export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string }, Promise<MastodonStatus[]>>(
async ({ platform, html }) => {
@ -22,7 +22,7 @@ export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string },
)
export default component$(() => {
const statuses = statusesLoader.use()
const statuses = statusesLoader.use().value
return (
<>
<StickyHeader>
@ -31,13 +31,22 @@ export default component$(() => {
<span>Local timeline</span>
</div>
</StickyHeader>
{statuses.value.length > 0 ? (
statuses.value.map((status) => <Status status={status} />)
) : (
<div class="flex-1 grid place-items-center bg-wildebeest-600 text-center">
<p>Nothing to see right now. Check back later!</p>
</div>
)}
<StatusesPanel
initialStatuses={statuses}
fetchMoreStatuses={$(async (numOfCurrentStatuses: number) => {
let statuses: MastodonStatus[] = []
try {
const response = await fetch(`/api/v1/timelines/public?local=true&offset=${numOfCurrentStatuses}`)
if (response.ok) {
const results = await response.text()
statuses = JSON.parse(results)
}
} catch {
/* empty */
}
return statuses
})}
/>
</>
)
})

Wyświetl plik

@ -1,4 +1,4 @@
import { test, expect, Page } from '@playwright/test'
import { test, expect, Page, Request } from '@playwright/test'
import type { Account, MastodonStatus } from 'wildebeest/frontend/src/types'
test.describe('Infinite (statuses) scrolling', () => {
@ -8,6 +8,20 @@ test.describe('Infinite (statuses) scrolling', () => {
goToPageFn: async (page: Page) => await page.goto('http://127.0.0.1:8788/explore'),
fetchUrl: 'http://127.0.0.1:8788/api/v1/timelines/public?*',
},
{
description: 'in local page',
goToPageFn: async (page: Page) => await page.goto('http://127.0.0.1:8788/public/local'),
fetchUrl: 'http://127.0.0.1:8788/api/v1/timelines/public?*',
isRequestValid: (request: Request) => {
const searchParams = new URL(request.url()).searchParams
return searchParams.get('local') === 'true'
},
},
{
description: 'in federated page',
goToPageFn: async (page: Page) => await page.goto('http://127.0.0.1:8788/public'),
fetchUrl: 'http://127.0.0.1:8788/api/v1/timelines/public?*',
},
{
description: 'in account page',
goToPageFn: async (page: Page) => {
@ -21,7 +35,7 @@ test.describe('Infinite (statuses) scrolling', () => {
},
]
tests.forEach(({ description, fetchUrl, goToPageFn }) =>
tests.forEach(({ description, fetchUrl, goToPageFn, isRequestValid }) =>
test(description, async ({ page, browserName }) => {
test.skip(browserName !== 'chromium', 'Only chromium tests infinite scrolling well')
@ -29,8 +43,11 @@ test.describe('Infinite (statuses) scrolling', () => {
await page.waitForLoadState('networkidle')
const generateFakeStatus = getMockStatusFn()
await page.route(fetchUrl, async (route) => {
const newStatuses = new Array(5).fill(null).map(generateFakeStatus)
await page.route(fetchUrl, async (route, request) => {
let newStatuses: MastodonStatus[] = []
if (!isRequestValid || isRequestValid(request)) {
newStatuses = new Array(5).fill(null).map(generateFakeStatus)
}
await route.fulfill({ body: JSON.stringify(newStatuses) })
})