Profile: store covers in object storage (WebP); add covers config; remember artworks categories content-type preference

This commit is contained in:
2026-03-29 09:22:36 +02:00
parent cab4fbd83e
commit 1da7d3bf88
27 changed files with 703 additions and 448 deletions

View File

@@ -7,14 +7,28 @@
@php
$active = $section ?? 'artworks';
$includeTags = (bool) ($includeTags ?? false);
$contentTypes = collect($contentTypes ?? $mainCategories ?? []);
$iconMap = [
'photography' => 'fa-camera',
'wallpapers' => 'fa-desktop',
'skins' => 'fa-layer-group',
'digital-art' => 'fa-palette',
'other' => 'fa-folder-open',
];
$sections = collect([
'artworks' => ['label' => 'All Artworks', 'icon' => 'fa-border-all', 'href' => '/browse'],
'photography' => ['label' => 'Photography', 'icon' => 'fa-camera', 'href' => '/photography'],
'wallpapers' => ['label' => 'Wallpapers', 'icon' => 'fa-desktop', 'href' => '/wallpapers'],
'skins' => ['label' => 'Skins', 'icon' => 'fa-layer-group', 'href' => '/skins'],
'other' => ['label' => 'Other', 'icon' => 'fa-folder-open', 'href' => '/other'],
]);
])->merge(
$contentTypes->mapWithKeys(function ($type) use ($iconMap) {
$slug = strtolower((string) ($type->slug ?? ''));
return [$slug => [
'label' => $type->name,
'icon' => $iconMap[$slug] ?? 'fa-folder-open',
'href' => $type->url ?? ('/' . $slug),
]];
})
);
if ($includeTags) {
$sections->put('tags', ['label' => 'Tags', 'icon' => 'fa-tags', 'href' => '/tags']);

View File

@@ -113,6 +113,7 @@
'photography' => 'fa-camera',
'wallpapers' => 'fa-desktop',
'skins' => 'fa-layer-group',
'digital-art' => 'fa-palette',
'other' => 'fa-folder-open',
'tags' => 'fa-tags',
];
@@ -130,20 +131,14 @@
$headerBreadcrumbs = collect();
if (($gallery_type ?? null) === 'browse') {
$headerBreadcrumbs = collect([
(object) ['name' => 'Browse', 'url' => '/browse'],
]);
} elseif (isset($contentType) && $contentType) {
$headerBreadcrumbs = collect([
(object) ['name' => 'Browse', 'url' => '/browse'],
(object) ['name' => $contentType->name, 'url' => '/' . strtolower($contentType->slug)],
]);
if (($gallery_type ?? null) === 'category' && isset($breadcrumbs) && $breadcrumbs->isNotEmpty()) {
$headerBreadcrumbs = $breadcrumbs;
}
$headerBreadcrumbs = $breadcrumbs ?? collect();
} elseif (isset($breadcrumbs) && $breadcrumbs->isNotEmpty()) {
$headerBreadcrumbs = $breadcrumbs;
} elseif (isset($contentType) && $contentType) {
$headerBreadcrumbs = collect([
(object) ['name' => 'Explore', 'url' => '/browse'],
(object) ['name' => $contentType->name, 'url' => '/' . strtolower($contentType->slug)],
]);
}
@endphp
@@ -426,95 +421,6 @@
</div>
@endsection
@push('head')
<style>
/* ── Hero ─────────────────────────────────────────────────────── */
.nb-hero-fade {
background: linear-gradient(180deg, rgba(17,24,39,0) 0%, rgba(7,10,15,0.9) 60%, rgba(7,10,15,1) 100%);
}
.nb-hero-gradient {
background: linear-gradient(135deg, rgba(224,122,33,0.08) 0%, rgba(15,23,36,0) 50%, rgba(21,36,58,0.4) 100%);
animation: nb-hero-shimmer 8s ease-in-out infinite alternate;
}
@keyframes nb-hero-shimmer {
0% { opacity: 0.6; }
100% { opacity: 1; }
}
/* ── Ranking Tabs ─────────────────────────────────────────────── */
.gallery-rank-tab {
-webkit-tap-highlight-color: transparent;
}
.gallery-rank-tab .nb-tab-indicator {
transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1), background-color 200ms ease;
}
/* Legacy: keep nb-scrollbar-none working elsewhere in the page */
.nb-scrollbar-none {
-ms-overflow-style: none;
scrollbar-width: none;
}
.nb-scrollbar-none::-webkit-scrollbar { display: none; }
/* ── Gallery grid fade-in on page load / tab change ─────────── */
@keyframes nb-gallery-fade-in {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0); }
}
[data-react-masonry-gallery] {
animation: nb-gallery-fade-in 300ms ease-out both;
}
/* ── Filter panel choice pills ───────────────────────────────── */
.nb-filter-choice { display: inline-flex; cursor: pointer; }
.nb-filter-choice--block { display: flex; width: 100%; }
.nb-filter-choice-label {
display: inline-flex;
align-items: center;
padding: 0.375rem 0.875rem;
border-radius: 9999px;
border: 1px solid rgba(255,255,255,0.1);
background: rgba(255,255,255,0.05);
color: rgba(214,224,238,0.8);
font-size: 0.8125rem;
font-weight: 500;
transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
white-space: nowrap;
}
.nb-filter-choice--block .nb-filter-choice-label {
border-radius: 0.6rem;
width: 100%;
}
.nb-filter-choice input:checked ~ .nb-filter-choice-label {
background: #E07A21;
border-color: #E07A21;
color: #fff;
box-shadow: 0 1px 8px rgba(224,122,33,0.35);
}
.nb-filter-choice input:focus-visible ~ .nb-filter-choice-label {
outline: 2px solid rgba(224,122,33,0.6);
outline-offset: 2px;
}
/* Filter date/text inputs */
.nb-filter-input {
appearance: none;
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 0.5rem;
color: rgba(255,255,255,0.85);
font-size: 0.8125rem;
padding: 0.425rem 0.75rem;
transition: border-color 150ms ease;
color-scheme: dark;
}
.nb-filter-input:focus {
outline: none;
border-color: rgba(224,122,33,0.6);
box-shadow: 0 0 0 3px rgba(224,122,33,0.15);
}
</style>
@endpush
@push('scripts')
@vite('resources/js/entry-masonry-gallery.jsx')
@vite('resources/js/entry-pill-carousel.jsx')