Initial commit: RSS feed dashboard aggregating YouTube, Reddit and RT
- PHP 8 + PDO SQLite cache with on-demand TTL refresh and dedup by link hash - laminas-feed + Guzzle for RSS/Atom parsing and HTTP - Bootstrap 5 UI with source and time-range filters, AJAX load-more - User cron-free deployment under Apache/php-fpm; .htaccess hardening
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\View;
|
||||
|
||||
/** @var array<int, array<string, mixed>> $items */
|
||||
|
||||
foreach ($items as $item):
|
||||
$source = (string) $item['source'];
|
||||
$color = View::sourceColor($source);
|
||||
$link = View::e((string) $item['link']);
|
||||
$publishedAt = $item['published_at'] ?? null;
|
||||
?>
|
||||
<div class="col-12 col-md-6 col-xl-4">
|
||||
<article class="card h-100 feed-card" style="--src: <?= View::e($color) ?>">
|
||||
<?php if (!empty($item['thumbnail'])): ?>
|
||||
<a href="<?= $link ?>" target="_blank" rel="noopener noreferrer" class="feed-thumb-link">
|
||||
<img src="<?= View::e((string) $item['thumbnail']) ?>"
|
||||
class="card-img-top feed-thumb"
|
||||
alt="" loading="lazy" decoding="async" referrerpolicy="no-referrer">
|
||||
<span class="thumb-tag"><?= View::e(View::sourceLabel($source)) ?></span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<div class="d-flex align-items-center gap-2 mb-2">
|
||||
<?php if (empty($item['thumbnail'])): ?>
|
||||
<span class="source-chip"><?= View::e(View::sourceLabel($source)) ?></span>
|
||||
<?php endif; ?>
|
||||
<small class="feed-name text-truncate mono"><?= View::e((string) ($item['feed_label'] ?? '')) ?></small>
|
||||
</div>
|
||||
<h2 class="card-title mb-2">
|
||||
<a href="<?= $link ?>" target="_blank" rel="noopener noreferrer"><?= View::e((string) $item['title']) ?></a>
|
||||
</h2>
|
||||
<?php if (!empty($item['description'])): ?>
|
||||
<p class="card-text flex-grow-1 mb-2"><?= View::e((string) $item['description']) ?></p>
|
||||
<?php endif; ?>
|
||||
<div class="card-footer-meta mt-auto d-flex justify-content-between align-items-center pt-3">
|
||||
<span class="author text-truncate me-2"><?= View::e((string) ($item['author'] ?? '')) ?></span>
|
||||
<?php if ($publishedAt): ?>
|
||||
<time datetime="<?= View::e((string) $publishedAt) ?>"
|
||||
data-timestamp="<?= View::e((string) $publishedAt) ?>"
|
||||
class="timestamp mono flex-shrink-0"><?= View::e(View::timeAgo((string) $publishedAt)) ?></time>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
Reference in New Issue
Block a user