kopia lustrzana https://github.com/cloudflare/wildebeest
add infinite scrolling to local and federated timelines
rodzic
d2a5ff122a
commit
91d6bb0503
|
|
@ -24,10 +24,10 @@ export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string },
|
||||||
)
|
)
|
||||||
|
|
||||||
export default component$(() => {
|
export default component$(() => {
|
||||||
const statuses = statusesLoader.use()
|
const statuses = statusesLoader.use().value
|
||||||
return (
|
return (
|
||||||
<StatusesPanel
|
<StatusesPanel
|
||||||
initialStatuses={statuses.value}
|
initialStatuses={statuses}
|
||||||
fetchMoreStatuses={$(async (numOfCurrentStatuses: number) => {
|
fetchMoreStatuses={$(async (numOfCurrentStatuses: number) => {
|
||||||
let statuses: MastodonStatus[] = []
|
let statuses: MastodonStatus[] = []
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { component$ } from '@builder.io/qwik'
|
import { $, component$ } from '@builder.io/qwik'
|
||||||
import { MastodonStatus } from '~/types'
|
import { MastodonStatus } from '~/types'
|
||||||
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
||||||
import Status from '~/components/Status'
|
|
||||||
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
||||||
import StickyHeader from '~/components/StickyHeader/StickyHeader'
|
import StickyHeader from '~/components/StickyHeader/StickyHeader'
|
||||||
import { getDocumentHead } from '~/utils/getDocumentHead'
|
import { getDocumentHead } from '~/utils/getDocumentHead'
|
||||||
import { RequestContext } from '@builder.io/qwik-city/middleware/request-handler'
|
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[]>>(
|
export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string }, Promise<MastodonStatus[]>>(
|
||||||
async ({ platform, html }) => {
|
async ({ platform, html }) => {
|
||||||
|
|
@ -22,7 +22,7 @@ export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string },
|
||||||
)
|
)
|
||||||
|
|
||||||
export default component$(() => {
|
export default component$(() => {
|
||||||
const statuses = statusesLoader.use()
|
const statuses = statusesLoader.use().value
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -32,13 +32,22 @@ export default component$(() => {
|
||||||
<span>Federated timeline</span>
|
<span>Federated timeline</span>
|
||||||
</div>
|
</div>
|
||||||
</StickyHeader>
|
</StickyHeader>
|
||||||
{statuses.value.length > 0 ? (
|
<StatusesPanel
|
||||||
statuses.value.map((status) => <Status status={status} />)
|
initialStatuses={statuses}
|
||||||
) : (
|
fetchMoreStatuses={$(async (numOfCurrentStatuses: number) => {
|
||||||
<div class="flex-1 grid place-items-center bg-wildebeest-600 text-center">
|
let statuses: MastodonStatus[] = []
|
||||||
<p>Nothing to see right now. Check back later!</p>
|
try {
|
||||||
</div>
|
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
|
||||||
|
})}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { component$ } from '@builder.io/qwik'
|
import { $, component$ } from '@builder.io/qwik'
|
||||||
import { MastodonStatus } from '~/types'
|
import { MastodonStatus } from '~/types'
|
||||||
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
||||||
import Status from '~/components/Status'
|
|
||||||
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
||||||
import StickyHeader from '~/components/StickyHeader/StickyHeader'
|
import StickyHeader from '~/components/StickyHeader/StickyHeader'
|
||||||
import { getDocumentHead } from '~/utils/getDocumentHead'
|
import { getDocumentHead } from '~/utils/getDocumentHead'
|
||||||
import { RequestContext } from '@builder.io/qwik-city/middleware/request-handler'
|
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[]>>(
|
export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string }, Promise<MastodonStatus[]>>(
|
||||||
async ({ platform, html }) => {
|
async ({ platform, html }) => {
|
||||||
|
|
@ -22,7 +22,7 @@ export const statusesLoader = loader$<{ DATABASE: D1Database; domain: string },
|
||||||
)
|
)
|
||||||
|
|
||||||
export default component$(() => {
|
export default component$(() => {
|
||||||
const statuses = statusesLoader.use()
|
const statuses = statusesLoader.use().value
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StickyHeader>
|
<StickyHeader>
|
||||||
|
|
@ -31,13 +31,22 @@ export default component$(() => {
|
||||||
<span>Local timeline</span>
|
<span>Local timeline</span>
|
||||||
</div>
|
</div>
|
||||||
</StickyHeader>
|
</StickyHeader>
|
||||||
{statuses.value.length > 0 ? (
|
<StatusesPanel
|
||||||
statuses.value.map((status) => <Status status={status} />)
|
initialStatuses={statuses}
|
||||||
) : (
|
fetchMoreStatuses={$(async (numOfCurrentStatuses: number) => {
|
||||||
<div class="flex-1 grid place-items-center bg-wildebeest-600 text-center">
|
let statuses: MastodonStatus[] = []
|
||||||
<p>Nothing to see right now. Check back later!</p>
|
try {
|
||||||
</div>
|
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
|
||||||
|
})}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -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'
|
import type { Account, MastodonStatus } from 'wildebeest/frontend/src/types'
|
||||||
|
|
||||||
test.describe('Infinite (statuses) scrolling', () => {
|
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'),
|
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?*',
|
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',
|
description: 'in account page',
|
||||||
goToPageFn: async (page: 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(description, async ({ page, browserName }) => {
|
||||||
test.skip(browserName !== 'chromium', 'Only chromium tests infinite scrolling well')
|
test.skip(browserName !== 'chromium', 'Only chromium tests infinite scrolling well')
|
||||||
|
|
||||||
|
|
@ -29,8 +43,11 @@ test.describe('Infinite (statuses) scrolling', () => {
|
||||||
await page.waitForLoadState('networkidle')
|
await page.waitForLoadState('networkidle')
|
||||||
|
|
||||||
const generateFakeStatus = getMockStatusFn()
|
const generateFakeStatus = getMockStatusFn()
|
||||||
await page.route(fetchUrl, async (route) => {
|
await page.route(fetchUrl, async (route, request) => {
|
||||||
const newStatuses = new Array(5).fill(null).map(generateFakeStatus)
|
let newStatuses: MastodonStatus[] = []
|
||||||
|
if (!isRequestValid || isRequestValid(request)) {
|
||||||
|
newStatuses = new Array(5).fill(null).map(generateFakeStatus)
|
||||||
|
}
|
||||||
await route.fulfill({ body: JSON.stringify(newStatuses) })
|
await route.fulfill({ body: JSON.stringify(newStatuses) })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
Ładowanie…
Reference in New Issue