fix: address beta feedback - gallery layout fixes, Russian locale, email logo (#249)
- Add Russian (Русский) to admin settings language dropdown - Fix Premium layout hero using thumbnail instead of hero_url - Hide "Uncategorized" section header in Story layout for uncategorized photos - Add PhotoLightbox to Story layout so photo clicks open full-screen view - Use full-res images in StoryPhotoCard instead of thumbnails - Defer public gallery auto-login text until settings/locale are loaded - Add validation and debug logging for email logo URL construction Co-authored-by: Paul Nothaft <[email protected]>
This commit is contained in:
co-authored by
Paul Nothaft
parent
2c5ae6fbb9
commit
486239aeb9
@@ -343,7 +343,7 @@ export const GalleryPremiumLayout: React.FC<GalleryPremiumLayoutProps> = ({
|
||||
<div
|
||||
className="gallery-premium-hero-bg"
|
||||
style={{
|
||||
backgroundImage: heroPhoto ? `url(${heroPhoto.thumbnail_url || heroPhoto.url})` : undefined
|
||||
backgroundImage: heroPhoto ? `url(${heroPhoto.hero_url || heroPhoto.url})` : undefined
|
||||
}}
|
||||
/>
|
||||
<div className="gallery-premium-hero-overlay" />
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
StoryFeedbackSheet,
|
||||
StoryScrollToTop
|
||||
} from './story';
|
||||
import { PhotoLightbox } from '../PhotoLightbox';
|
||||
|
||||
import './GalleryStoryLayout.css';
|
||||
|
||||
@@ -71,6 +72,7 @@ export const GalleryStoryLayout: React.FC<GalleryStoryLayoutProps> = ({
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [favorites, setFavorites] = useState<Set<number>>(new Set());
|
||||
const [selectedPhotoForFeedback, setSelectedPhotoForFeedback] = useState<Photo | null>(null);
|
||||
const [lightboxIndex, setLightboxIndex] = useState<number | null>(null);
|
||||
const [comments, setComments] = useState<Record<number, Array<{ id: string; author: string; text: string; date: string }>>>({});
|
||||
const [ratings, setRatings] = useState<Record<number, number>>({});
|
||||
const [savedIdentity, setSavedIdentity] = useState<{ name: string; email: string } | null>(null);
|
||||
@@ -112,7 +114,7 @@ export const GalleryStoryLayout: React.FC<GalleryStoryLayoutProps> = ({
|
||||
|
||||
// Group by category
|
||||
filteredPhotos.forEach(photo => {
|
||||
const categoryName = photo.category_name || t('gallery.uncategorized', 'Gallery');
|
||||
const categoryName = photo.category_name || '';
|
||||
if (!photosByCategory[categoryName]) {
|
||||
photosByCategory[categoryName] = [];
|
||||
}
|
||||
@@ -163,6 +165,11 @@ export const GalleryStoryLayout: React.FC<GalleryStoryLayoutProps> = ({
|
||||
setSelectedPhotoForFeedback(photo);
|
||||
}, []);
|
||||
|
||||
const handleOpenLightbox = useCallback((photo: Photo) => {
|
||||
const index = photos.findIndex(p => p.id === photo.id);
|
||||
setLightboxIndex(index >= 0 ? index : 0);
|
||||
}, [photos]);
|
||||
|
||||
const handleCloseFeedback = useCallback(() => {
|
||||
setSelectedPhotoForFeedback(null);
|
||||
}, []);
|
||||
@@ -312,7 +319,7 @@ export const GalleryStoryLayout: React.FC<GalleryStoryLayoutProps> = ({
|
||||
photos={scene.photos}
|
||||
favorites={favorites}
|
||||
onToggleFavorite={handleToggleFavorite}
|
||||
onPhotoClick={handleOpenFeedback}
|
||||
onPhotoClick={handleOpenLightbox}
|
||||
slug={slug}
|
||||
allowDownloads={allowDownloads}
|
||||
protectionLevel={protectionLevel}
|
||||
@@ -328,7 +335,7 @@ export const GalleryStoryLayout: React.FC<GalleryStoryLayoutProps> = ({
|
||||
index={index}
|
||||
isFavorite={favorites.has(photo.id)}
|
||||
onToggleFavorite={handleToggleFavorite}
|
||||
onClick={() => handleOpenFeedback(photo)}
|
||||
onClick={() => handleOpenLightbox(photo)}
|
||||
slug={slug}
|
||||
galleryId={`gallery-${scene.id}`}
|
||||
allowDownloads={allowDownloads}
|
||||
@@ -359,6 +366,22 @@ export const GalleryStoryLayout: React.FC<GalleryStoryLayoutProps> = ({
|
||||
)}
|
||||
</footer>
|
||||
|
||||
{/* Lightbox */}
|
||||
{lightboxIndex !== null && (
|
||||
<PhotoLightbox
|
||||
photos={photos}
|
||||
initialIndex={lightboxIndex}
|
||||
onClose={() => setLightboxIndex(null)}
|
||||
slug={slug}
|
||||
feedbackEnabled={feedbackEnabled}
|
||||
allowDownloads={allowDownloads}
|
||||
protectionLevel={protectionLevel}
|
||||
useEnhancedProtection={useEnhancedProtection}
|
||||
useCanvasRendering={useCanvasRendering}
|
||||
onFeedbackChange={onFeedbackChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Feedback Sheet */}
|
||||
{feedbackEnabled && (
|
||||
<StoryFeedbackSheet
|
||||
|
||||
@@ -60,7 +60,7 @@ export const StoryPhotoCard: React.FC<StoryPhotoCardProps> = ({
|
||||
className="block w-full h-full"
|
||||
>
|
||||
<AuthenticatedImage
|
||||
src={photo.thumbnail_url || photo.url}
|
||||
src={photo.url}
|
||||
alt={photo.filename}
|
||||
onLoad={() => setIsLoaded(true)}
|
||||
className={`w-full h-full object-cover transition-all duration-700 ease-out will-change-transform ${
|
||||
|
||||
@@ -18,27 +18,29 @@ export const StoryScene: React.FC<StorySceneProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<section className={`story-scene ${fullWidth ? 'full-width' : ''} ${className}`}>
|
||||
<div className="story-scene-header">
|
||||
<motion.h2
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="story-scene-title"
|
||||
>
|
||||
{title}
|
||||
</motion.h2>
|
||||
{subtitle && (
|
||||
<motion.p
|
||||
{title && (
|
||||
<div className="story-scene-header">
|
||||
<motion.h2
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.1 }}
|
||||
className="story-scene-subtitle"
|
||||
className="story-scene-title"
|
||||
>
|
||||
{subtitle}
|
||||
</motion.p>
|
||||
)}
|
||||
</div>
|
||||
{title}
|
||||
</motion.h2>
|
||||
{subtitle && (
|
||||
<motion.p
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.1 }}
|
||||
className="story-scene-subtitle"
|
||||
>
|
||||
{subtitle}
|
||||
</motion.p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user