Browse Source

bug-fixes

imwald
Silberengel 5 days ago
parent
commit
3dd6085a91
  1. 2
      assets/styles/app.css
  2. 44
      assets/styles/layout.css
  3. 55
      src/Service/FeaturedAuthorListedRows.php
  4. 2
      src/Twig/SidebarFeaturedAuthorsExtension.php
  5. 3
      templates/components/Organisms/FeaturedList.html.twig
  6. 9
      templates/components/UserMenu.html.twig

2
assets/styles/app.css

@ -201,7 +201,7 @@ svg.icon {
padding: 1rem 1.125rem 1.2rem; padding: 1rem 1.125rem 1.2rem;
} }
/* Lead card only: 16:9 cover frame (Molecules/FeaturedList — side cards have no .card-header). */ /* 16:9 cover frame (lead + stacked side cards in FeaturedList). */
.featured-list .card > a > .card-header { .featured-list .card > a > .card-header {
margin: 0; margin: 0;
width: 100%; width: 100%;

44
assets/styles/layout.css

@ -422,8 +422,48 @@ main {
margin-top: 152px; margin-top: 152px;
} }
.user-menu { /* In-flow left column: <nav> clears the fixed #site-header. */
top: 162px; .layout > nav {
margin-top: 152px;
}
/*
* Left column account block: keep it in document flow (not position:fixed) so order is
* badge logout / search featured authors. Fixed positioning removed the menu from the flow
* so the featured block sat under the header or overlapped.
*/
.layout > nav .user-menu:not(.user-menu--inline) {
position: static;
width: 100%;
min-width: 0;
max-width: 100%;
top: auto;
left: auto;
}
.layout > nav .user-menu .notice {
margin-top: 0;
margin-bottom: 0.3rem;
}
/* Tight stack: badge, then logout, then search */
.layout > nav .user-menu .user-menu__account-nav {
margin: 0.4rem 0 0.35rem;
padding: 0;
}
.layout > nav .user-menu .user-menu__account-nav li {
margin: 0.2rem 0 0;
}
.layout > nav .user-menu .user-menu__account-nav li:first-child {
margin-top: 0;
}
/* More separation before the featured block (sibling in <nav>, after this menu). */
.layout > nav .sidebar-featured-authors {
margin-top: 1.35rem;
padding-top: 1.15rem;
} }
} }

55
src/Service/FeaturedAuthorListedRows.php

@ -9,15 +9,45 @@ use swentel\nostr\Key\Key;
/** /**
* NIP-05 / listed featured author rows (same shape as {@see \App\Controller\FeaturedAuthorsController}). * NIP-05 / listed featured author rows (same shape as {@see \App\Controller\FeaturedAuthorsController}).
* Sidebar: falls back to magazine index pubkeys when the `featured_author` list is still empty
* (e.g. prewarm has not yet synced the table).
*/ */
final class FeaturedAuthorListedRows final class FeaturedAuthorListedRows
{ {
public function __construct( public function __construct(
private readonly FeaturedAuthorRepository $featuredAuthorRepository, private readonly FeaturedAuthorRepository $featuredAuthorRepository,
private readonly CacheService $cacheService, private readonly CacheService $cacheService,
private readonly MagazineContentService $magazineContent,
) { ) {
} }
/**
* Rows for the left nav: NIP-05–listed authors first, otherwise authors from the magazine index store.
*
* @return list<array{npub: string, pubkey: string, display_name: string, picture: string, local_part: string}>
*/
public function buildSidebarRows(int $limit = 12): array
{
$fromDb = $this->buildListedByLocalPartPage($limit, 0);
if ($fromDb !== []) {
return $fromDb;
}
$keys = new Key();
$authors = [];
$hexes = $this->magazineContent->getAllDistinctCategoryAuthorPubkeyHexes();
foreach (\array_slice($hexes, 0, $limit) as $hex) {
try {
$npub = $keys->convertPublicKeyToBech32($hex);
} catch (\Throwable) {
continue;
}
$authors[] = $this->rowFromNpub($npub, $hex, '');
}
return $authors;
}
/** /**
* @return list<array{npub: string, pubkey: string, display_name: string, picture: string, local_part: string}> * @return list<array{npub: string, pubkey: string, display_name: string, picture: string, local_part: string}>
*/ */
@ -26,20 +56,33 @@ final class FeaturedAuthorListedRows
$keys = new Key(); $keys = new Key();
$authors = []; $authors = [];
foreach ($this->featuredAuthorRepository->findListedOrderByLocalPartPaginated($limit, $offset) as $fa) { foreach ($this->featuredAuthorRepository->findListedOrderByLocalPartPaginated($limit, $offset) as $fa) {
try {
$npub = $keys->convertPublicKeyToBech32($fa->getPubkeyHex()); $npub = $keys->convertPublicKeyToBech32($fa->getPubkeyHex());
} catch (\Throwable) {
continue;
}
$authors[] = $this->rowFromNpub($npub, $fa->getPubkeyHex(), $fa->getLocalPart());
}
return $authors;
}
/**
* @return array{npub: string, pubkey: string, display_name: string, picture: string, local_part: string}
*/
private function rowFromNpub(string $npub, string $pubkeyHex, string $localPart): array
{
$bundle = $this->cacheService->getMetadataBundle($npub); $bundle = $this->cacheService->getMetadataBundle($npub);
$author = $bundle['content']; $author = $bundle['content'];
$displayName = trim((string) ($author->display_name ?? $author->name ?? '')); $displayName = trim((string) ($author->display_name ?? $author->name ?? ''));
$picture = trim((string) ($author->picture ?? '')); $picture = trim((string) ($author->picture ?? ''));
$authors[] = [
return [
'npub' => $npub, 'npub' => $npub,
'pubkey' => strtolower($fa->getPubkeyHex()), 'pubkey' => strtolower($pubkeyHex),
'display_name' => $displayName, 'display_name' => $displayName,
'picture' => $picture, 'picture' => $picture,
'local_part' => $fa->getLocalPart(), 'local_part' => $localPart,
]; ];
} }
return $authors;
}
} }

2
src/Twig/SidebarFeaturedAuthorsExtension.php

@ -20,7 +20,7 @@ final class SidebarFeaturedAuthorsExtension extends AbstractExtension
{ {
return [ return [
new TwigFunction('sidebar_featured_author_rows', function (int $limit = 12): array { new TwigFunction('sidebar_featured_author_rows', function (int $limit = 12): array {
return $this->featuredAuthorListedRows->buildListedByLocalPartPage($limit, 0); return $this->featuredAuthorListedRows->buildSidebarRows($limit);
}), }),
]; ];
} }

3
templates/components/Organisms/FeaturedList.html.twig

@ -30,6 +30,9 @@
{% if item != feature %} {% if item != feature %}
<div class="card"> <div class="card">
<a href="{{ (item.pubkey and npub_from_hex(item.pubkey) != '') ? path('article', { npub: npub_from_hex(item.pubkey), slug: item.slug }) : path('article-legacy-redirect', { slug: item.slug }) }}"> <a href="{{ (item.pubkey and npub_from_hex(item.pubkey) != '') ? path('article', { npub: npub_from_hex(item.pubkey), slug: item.slug }) : path('article-legacy-redirect', { slug: item.slug }) }}">
<div class="card-header">
<img src="{{ article_card_cover(item.image, item.pubkey) }}" alt="{{ ('Illustration for ' ~ item.title)|e('html_attr') }}" width="1200" height="675" loading="lazy" decoding="async">
</div>
<div class="card-body"> <div class="card-body">
<h2 class="card-title">{{ item.title }}</h2> <h2 class="card-title">{{ item.title }}</h2>
{% if item.displayAt %} {% if item.displayAt %}

9
templates/components/UserMenu.html.twig

@ -11,18 +11,15 @@
{# </li>#} {# </li>#}
{# </ul>#} {# </ul>#}
{% endif %} {% endif %}
<ul class="user-nav"> <ul class="user-nav user-menu__account-nav" role="list">
{# <li>#} {# <li>#}
{# <a href="{{ path('editor-create') }}">Write an article</a>#} {# <a href="{{ path('editor-create') }}">Write an article</a>#}
{# </li>#} {# </li>#}
<li> <li>
<a href="{{ path('search') }}">{{ 'heading.search'|trans }}</a> <a href="/logout" data-action="live#$render">{{ 'heading.logout'|trans }}</a>
</li> </li>
{# <li>#}
{# <a href="{{ path('app_index_index') }}">{{ 'heading.index'|trans }}</a>#}
{# </li>#}
<li> <li>
<a href="/logout" data-action="live#$render">{{ 'heading.logout'|trans }}</a> <a href="{{ path('search') }}">{{ 'heading.search'|trans }}</a>
</li> </li>
</ul> </ul>
{% else %} {% else %}

Loading…
Cancel
Save