Stream the page shell first so a loader shows while feeds fetch
Opening the page used to block on refreshStale() before a single byte went out, so the browser sat on a blank tab for the whole fetch. index.php now renders templates/shell.php (head, header, filters, skeleton loader) and flushes it, then refreshes and appends templates/content.php, which removes the loader as the feed HTML arrives. - templates/layout.php is split into shell.php + content.php - refresh chip moved to a right-aligned row above the feed: the toolbar paints before the refresh report exists - header story count shows the cached total, then corrects to the real one - skeleton styles match the card grid and keep the sources' chroma; a noscript style hides the loader for clients without JS - README: file map and page-load lifecycle updated
This commit is contained in:
@@ -6,13 +6,11 @@ declare(strict_types=1);
|
||||
$app = require __DIR__ . '/src/bootstrap.php';
|
||||
|
||||
$config = $app['config'];
|
||||
$repository = $app['repository'];
|
||||
$service = $app['service'];
|
||||
|
||||
$refresh = $service->refreshStale();
|
||||
|
||||
$sources = $service->sources();
|
||||
$activeSource = $_GET['source'] ?? null;
|
||||
if (!is_string($activeSource) || !in_array($activeSource, $sources, true)) {
|
||||
if (!is_string($activeSource) || $activeSource === '') {
|
||||
$activeSource = null;
|
||||
}
|
||||
|
||||
@@ -21,13 +19,41 @@ $activeRange = $_GET['range'] ?? '';
|
||||
if (!is_string($activeRange) || !array_key_exists($activeRange, $ranges)) {
|
||||
$activeRange = '';
|
||||
}
|
||||
|
||||
$since = $activeRange !== '' ? gmdate('c', time() - (int) $ranges[$activeRange]) : null;
|
||||
$pageSize = (int) $config['page_size'];
|
||||
|
||||
$page = $service->page($activeSource, 1, (int) $config['page_size'], $since);
|
||||
// Register the configured feeds before anything renders so the filter tabs are
|
||||
// complete on a fresh database; refreshStale() repeats the same sync cheaply.
|
||||
$repository->syncFeeds($app['feeds']);
|
||||
|
||||
echo App\View::render('layout', [
|
||||
$sources = $service->sources();
|
||||
if ($activeSource !== null && !in_array($activeSource, $sources, true)) {
|
||||
$activeSource = null;
|
||||
}
|
||||
|
||||
// Send the shell (header, filters and the feed loader) before refreshing, so
|
||||
// the loader is on screen while the feeds are being fetched. Nothing may hold
|
||||
// those bytes back.
|
||||
ini_set('zlib.output_compression', '0');
|
||||
while (ob_get_level() > 0 && ob_end_flush()) {
|
||||
// Drop any active output buffers so the shell reaches the browser now.
|
||||
}
|
||||
|
||||
echo App\View::render('shell', [
|
||||
'config' => $config,
|
||||
'sources' => $sources,
|
||||
'activeSource' => $activeSource,
|
||||
'activeRange' => $activeRange,
|
||||
'cachedTotal' => $repository->countItems($activeSource, $since),
|
||||
]);
|
||||
|
||||
flush();
|
||||
|
||||
$refresh = $service->refreshStale();
|
||||
$page = $service->page($activeSource, 1, $pageSize, $since);
|
||||
|
||||
echo App\View::render('content', [
|
||||
'activeSource' => $activeSource,
|
||||
'activeRange' => $activeRange,
|
||||
'page' => $page,
|
||||
|
||||
Reference in New Issue
Block a user