3c2d90fb7e
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
62 lines
1.8 KiB
PHP
62 lines
1.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/** @var array<string, mixed> $app */
|
|
$app = require __DIR__ . '/src/bootstrap.php';
|
|
|
|
$config = $app['config'];
|
|
$repository = $app['repository'];
|
|
$service = $app['service'];
|
|
|
|
$activeSource = $_GET['source'] ?? null;
|
|
if (!is_string($activeSource) || $activeSource === '') {
|
|
$activeSource = null;
|
|
}
|
|
|
|
$ranges = $config['ranges'] ?? [];
|
|
$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'];
|
|
|
|
// 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']);
|
|
|
|
$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,
|
|
'refresh' => $refresh,
|
|
]);
|