diff --git a/frontend/src/components/gallery/GalleryFolderTiles.tsx b/frontend/src/components/gallery/GalleryFolderTiles.tsx index 3ac15763..8906d6c3 100644 --- a/frontend/src/components/gallery/GalleryFolderTiles.tsx +++ b/frontend/src/components/gallery/GalleryFolderTiles.tsx @@ -22,9 +22,7 @@ interface GalleryFolderTilesProps { * so a gallery configured for canvas rendering or maximum protection must not * get an ordinary blob-backed here just because it is a cover. */ - protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; - useCanvasRendering?: boolean; allowDownloads?: boolean; /** * Compact chip row instead of cover cards. Used by the full-bleed layouts @@ -40,8 +38,6 @@ export const GalleryFolderTiles: React.FC = ({ onOpen, compact = false, slug, - protectionLevel, - useCanvasRendering, }) => { const { t } = useTranslation(); @@ -95,10 +91,6 @@ export const GalleryFolderTiles: React.FC = ({ isGallery slug={slug} // Same rule as every other gallery image path: maximum - // protection implies canvas rendering even when the separate - // toggle is off (its default), otherwise a cover silently - // falls back to a blob-backed . - useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'} /> ) : (
diff --git a/frontend/src/components/gallery/GalleryView.tsx b/frontend/src/components/gallery/GalleryView.tsx index 56b0c6a8..b5273206 100644 --- a/frontend/src/components/gallery/GalleryView.tsx +++ b/frontend/src/components/gallery/GalleryView.tsx @@ -1311,9 +1311,7 @@ export const GalleryView: React.FC = ({ slug, event, requiresP onOpen={openFolderBySlug} compact={compact} slug={slug} - protectionLevel={protectionLevel} useEnhancedProtection={protectionLevel !== 'basic'} - useCanvasRendering={useCanvasRendering} allowDownloads={allowDownloads} /> ); diff --git a/frontend/src/components/gallery/HeroHeader.tsx b/frontend/src/components/gallery/HeroHeader.tsx index 6f183799..ec187f81 100644 --- a/frontend/src/components/gallery/HeroHeader.tsx +++ b/frontend/src/components/gallery/HeroHeader.tsx @@ -23,9 +23,7 @@ interface HeroHeaderProps { heroLogoPosition?: 'top' | 'center' | 'bottom'; dividerStyle?: HeroDividerStyle; allowDownloads?: boolean; - protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; - useCanvasRendering?: boolean; onScrollToContent?: () => void; // Hero image anchor position (#162) – keyword or "X% Y%" focal point heroImageAnchor?: string; @@ -43,8 +41,6 @@ export const HeroHeader: React.FC = ({ heroLogoSize = 'medium', heroLogoPosition = 'top', dividerStyle = 'wave', - protectionLevel = 'standard', - useCanvasRendering = false, onScrollToContent, heroImageAnchor = 'center' }) => { @@ -142,7 +138,6 @@ export const HeroHeader: React.FC = ({ style={{ objectPosition: heroImageAnchor }} isGallery={true} slug={slug} - useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'} /> {/* Overlay */} diff --git a/frontend/src/components/gallery/PhotoGrid.tsx b/frontend/src/components/gallery/PhotoGrid.tsx index 154e8858..e41021db 100644 --- a/frontend/src/components/gallery/PhotoGrid.tsx +++ b/frontend/src/components/gallery/PhotoGrid.tsx @@ -196,7 +196,6 @@ export const PhotoGrid: React.FC = ({ allowDownloads={allowDownloads} protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} - useCanvasRendering={useCanvasRendering} slug={slug} feedbackEnabled={feedbackEnabled} /> @@ -214,6 +213,7 @@ export const PhotoGrid: React.FC = ({ allowDownloads={allowDownloads} protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} + useCanvasRendering={useCanvasRendering} disableRightClick={disableRightClick} enableDevtoolsProtection={enableDevtoolsProtection} /> @@ -231,7 +231,6 @@ interface PhotoThumbnailProps { allowDownloads?: boolean; protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; - useCanvasRendering?: boolean; slug: string; // Add slug as required prop feedbackEnabled?: boolean; } @@ -244,7 +243,6 @@ const PhotoThumbnail: React.FC = ({ onDownload, allowDownloads = true, protectionLevel = 'standard', - useCanvasRendering = false, slug, feedbackEnabled = false }) => { @@ -268,7 +266,6 @@ const PhotoThumbnail: React.FC = ({ loading="lazy" isGallery={true} slug={slug} - useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'} onProtectionViolation={(violationType) => { // Track analytics if (typeof window !== 'undefined' && (window as any).umami) { diff --git a/frontend/src/components/gallery/PhotoGridWithLayouts.tsx b/frontend/src/components/gallery/PhotoGridWithLayouts.tsx index 62a95481..b0ea6459 100644 --- a/frontend/src/components/gallery/PhotoGridWithLayouts.tsx +++ b/frontend/src/components/gallery/PhotoGridWithLayouts.tsx @@ -361,9 +361,7 @@ export const PhotoGridWithLayouts: React.FC = ({ heroLogoPosition={heroLogoPosition} dividerStyle={heroDividerStyle} allowDownloads={allowDownloads} - protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} - useCanvasRendering={useCanvasRendering} heroImageAnchor={heroImageAnchor} /> )} diff --git a/frontend/src/components/gallery/__tests__/canvasLightboxOnly.test.ts b/frontend/src/components/gallery/__tests__/canvasLightboxOnly.test.ts new file mode 100644 index 00000000..d8a8c45e --- /dev/null +++ b/frontend/src/components/gallery/__tests__/canvasLightboxOnly.test.ts @@ -0,0 +1,56 @@ +/** + * Canvas rendering is a lightbox concern, not a tile concern. + * + * A canvas pins a backing store of naturalWidth × naturalHeight × 4 bytes + * that the browser is not allowed to evict, and iOS Safari has a hard + * budget for canvas memory that fails silently when exceeded — blank + * tiles, no error. A gallery is hundreds of tiles and one lightbox image, + * so the tiles render whatever the protection level says, and the + * lightbox keeps the per-event toggle and the `maximum` implication. + * + * Source-level pin: nothing under components/gallery except PhotoLightbox + * may hand `useCanvasRendering` to AuthenticatedImage. + */ +import fs from 'fs'; +import path from 'path'; +import { describe, it, expect } from 'vitest'; + +const root = path.resolve(__dirname, '..'); +function walk(dir: string): string[] { + return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => { + const file = path.join(dir, entry.name); + if (entry.isDirectory()) return entry.name === '__tests__' ? [] : walk(file); + return file.endsWith('.tsx') ? [file] : []; + }); +} + +describe('canvas rendering stays in the lightbox', () => { + const files = walk(root); + const lightbox = path.join(root, 'PhotoLightbox.tsx'); + + /** The JSX props of every in a file, plus every + * `imageProps={{ ... }}` object a layout hands to PhotoCard to spread in. */ + const imageProps = (source: string) => [ + ...source.split(' chunk.split('/>')[0]), + ...source.split('imageProps={{').slice(1).map((chunk) => chunk.split('}}')[0]), + ]; + + it('only PhotoLightbox passes useCanvasRendering to AuthenticatedImage', () => { + const offenders = files.filter((file) => file !== lightbox + && imageProps(fs.readFileSync(file, 'utf8')).some((props) => props.includes('useCanvasRendering'))); + expect(offenders.map((f) => path.relative(root, f))).toEqual([]); + // The pin has teeth: the lightbox itself is caught by the same probe. + expect(imageProps(fs.readFileSync(lightbox, 'utf8')).some((props) => props.includes('useCanvasRendering'))).toBe(true); + }); + + it('only PhotoLightbox turns canvas on for protection level maximum', () => { + const offenders = files.filter((file) => file !== lightbox + && /useCanvasRendering[^\n]*protectionLevel === 'maximum'/.test(fs.readFileSync(file, 'utf8'))); + expect(offenders.map((f) => path.relative(root, f))).toEqual([]); + }); + + it('the lightbox still does both', () => { + const source = fs.readFileSync(lightbox, 'utf8'); + expect(source).toMatch(/useCanvasRendering=\{useCanvasRendering \|\| protectionLevel === 'maximum'\}/); + }); +}); diff --git a/frontend/src/components/gallery/layouts/BaseGalleryLayout.tsx b/frontend/src/components/gallery/layouts/BaseGalleryLayout.tsx index e818d7b8..926ce009 100644 --- a/frontend/src/components/gallery/layouts/BaseGalleryLayout.tsx +++ b/frontend/src/components/gallery/layouts/BaseGalleryLayout.tsx @@ -47,6 +47,7 @@ export interface BaseGalleryLayoutProps { onPickResolution?: (photoIds: number[]) => void; protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; + /** Canvas rendering applies to the lightbox only; tiles always render . */ useCanvasRendering?: boolean; feedbackEnabled?: boolean; feedbackOptions?: { diff --git a/frontend/src/components/gallery/layouts/GalleryPremiumLayout.tsx b/frontend/src/components/gallery/layouts/GalleryPremiumLayout.tsx index e6c99b34..0a2dd95a 100644 --- a/frontend/src/components/gallery/layouts/GalleryPremiumLayout.tsx +++ b/frontend/src/components/gallery/layouts/GalleryPremiumLayout.tsx @@ -46,9 +46,7 @@ interface PhotoCardProps { isLiked: boolean; slug: string; allowDownloads?: boolean; - protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; - useCanvasRendering?: boolean; feedbackEnabled?: boolean; // #506: track the per-event "allow likes" toggle so the per-photo // Like button respects it. `feedbackEnabled` alone isn't enough — @@ -68,8 +66,6 @@ const PhotoCard: React.FC = ({ isSelectionMode, isLiked, slug, - protectionLevel = 'standard', - useCanvasRendering = false, feedbackEnabled = false, allowLikes = false, index @@ -122,7 +118,6 @@ const PhotoCard: React.FC = ({ loading="lazy" isGallery={true} slug={slug} - useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'} /> {/* Colour label (#1044) — same badge every layout uses. */} @@ -208,9 +203,7 @@ export const GalleryPremiumLayout: React.FC = ({ allowDownloads = true, downloadChoices, onPickResolution, - protectionLevel = 'standard', useEnhancedProtection = false, - useCanvasRendering = false, feedbackEnabled = false, feedbackOptions, heroPhotoOverride, @@ -629,9 +622,7 @@ export const GalleryPremiumLayout: React.FC = ({ isLiked={likedPhotoIds.has(originalPhoto.id)} slug={slug} allowDownloads={allowDownloads} - protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} - useCanvasRendering={useCanvasRendering} feedbackEnabled={feedbackEnabled} allowLikes={!!feedbackOptions?.allowLikes} index={photoIndex} diff --git a/frontend/src/components/gallery/layouts/GalleryStoryLayout.tsx b/frontend/src/components/gallery/layouts/GalleryStoryLayout.tsx index 6f91e82e..bc5f6511 100644 --- a/frontend/src/components/gallery/layouts/GalleryStoryLayout.tsx +++ b/frontend/src/components/gallery/layouts/GalleryStoryLayout.tsx @@ -255,9 +255,7 @@ export const GalleryStoryLayout: React.FC = ({ photo={heroPhoto} slug={slug} allowDownloads={allowDownloads} - protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} - useCanvasRendering={useCanvasRendering} /> {/* Main Content - Scenes */} @@ -281,9 +279,7 @@ export const GalleryStoryLayout: React.FC = ({ onPhotoClick={handleOpenLightbox} slug={slug} allowDownloads={allowDownloads} - protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} - useCanvasRendering={useCanvasRendering} /> ) : (
@@ -298,9 +294,7 @@ export const GalleryStoryLayout: React.FC = ({ slug={slug} galleryId={`gallery-${scene.id}`} allowDownloads={allowDownloads} - protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} - useCanvasRendering={useCanvasRendering} // Mark first photo in each grid as featured featured={index === 0 && scene.photos.length > 4} /> diff --git a/frontend/src/components/gallery/layouts/GridGalleryLayout.tsx b/frontend/src/components/gallery/layouts/GridGalleryLayout.tsx index e10f5c6e..61f1d5d6 100644 --- a/frontend/src/components/gallery/layouts/GridGalleryLayout.tsx +++ b/frontend/src/components/gallery/layouts/GridGalleryLayout.tsx @@ -18,9 +18,7 @@ interface GridPhotoProps { animationType?: string; allowDownloads?: boolean; slug?: string; - protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; - useCanvasRendering?: boolean; feedbackEnabled?: boolean; feedbackOptions?: { allowLikes?: boolean; @@ -47,8 +45,6 @@ const GridPhoto: React.FC = ({ animationType = 'fade', allowDownloads = true, slug, - protectionLevel = 'standard', - useCanvasRendering = false, feedbackEnabled = false, feedbackOptions, savedIdentity, @@ -130,7 +126,6 @@ const GridPhoto: React.FC = ({ loading: 'lazy', isGallery: true, slug, - useCanvasRendering: useCanvasRendering || protectionLevel === 'maximum', onProtectionViolation: (violationType: string) => { console.warn(`Protection violation on grid photo ${photo.id}: ${violationType}`); }, @@ -200,9 +195,7 @@ export const GridGalleryLayout: React.FC = ({ isSelectionMode = false, onPhotoSelect, allowDownloads = true, - protectionLevel = 'standard', useEnhancedProtection = false, - useCanvasRendering = false, feedbackEnabled = false, feedbackOptions, isClient = false, @@ -255,9 +248,7 @@ export const GridGalleryLayout: React.FC = ({ animationType={animation} allowDownloads={allowDownloads} slug={slug} - protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} - useCanvasRendering={useCanvasRendering} feedbackEnabled={feedbackEnabled} feedbackOptions={feedbackOptions} savedIdentity={savedIdentity} diff --git a/frontend/src/components/gallery/layouts/JustifiedGalleryLayout.tsx b/frontend/src/components/gallery/layouts/JustifiedGalleryLayout.tsx index 8e0d5113..b4f3295d 100644 --- a/frontend/src/components/gallery/layouts/JustifiedGalleryLayout.tsx +++ b/frontend/src/components/gallery/layouts/JustifiedGalleryLayout.tsx @@ -40,9 +40,7 @@ interface JustifiedPhotoProps { animationType?: string; allowDownloads?: boolean; slug?: string; - protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; - useCanvasRendering?: boolean; feedbackEnabled?: boolean; feedbackOptions?: { allowLikes?: boolean; @@ -69,8 +67,6 @@ const JustifiedPhoto: React.FC = ({ animationType = 'fade', allowDownloads = true, slug, - protectionLevel = 'standard', - useCanvasRendering = false, feedbackEnabled = false, feedbackOptions, savedIdentity, @@ -133,7 +129,6 @@ const JustifiedPhoto: React.FC = ({ loading: 'lazy', isGallery: true, slug, - useCanvasRendering: useCanvasRendering || protectionLevel === 'maximum', onProtectionViolation: (violationType: string) => { console.warn(`Protection violation on justified photo ${photo.id}: ${violationType}`); }, @@ -214,9 +209,7 @@ export const JustifiedGalleryLayout: React.FC = ({ isSelectionMode = false, onPhotoSelect, allowDownloads = true, - protectionLevel = 'standard', useEnhancedProtection = false, - useCanvasRendering = false, feedbackEnabled = false, feedbackOptions, // Hero props @@ -399,7 +392,6 @@ export const JustifiedGalleryLayout: React.FC = ({ className="w-full h-full object-cover" isGallery={true} slug={slug} - useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'} /> {/* Overlay */} @@ -523,9 +515,7 @@ export const JustifiedGalleryLayout: React.FC = ({ animationType={animation} allowDownloads={allowDownloads} slug={slug} - protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} - useCanvasRendering={useCanvasRendering} feedbackEnabled={feedbackEnabled} feedbackOptions={feedbackOptions} savedIdentity={savedIdentity} diff --git a/frontend/src/components/gallery/layouts/story/StoryCarousel.tsx b/frontend/src/components/gallery/layouts/story/StoryCarousel.tsx index d88212f8..c001e771 100644 --- a/frontend/src/components/gallery/layouts/story/StoryCarousel.tsx +++ b/frontend/src/components/gallery/layouts/story/StoryCarousel.tsx @@ -14,9 +14,7 @@ interface StoryCarouselProps { slug: string; id: string; allowDownloads?: boolean; - protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; - useCanvasRendering?: boolean; } export const StoryCarousel: React.FC = ({ @@ -27,9 +25,7 @@ export const StoryCarousel: React.FC = ({ slug, id, allowDownloads = true, - protectionLevel = 'standard', useEnhancedProtection = false, - useCanvasRendering = false }) => { return (
@@ -53,9 +49,7 @@ export const StoryCarousel: React.FC = ({ slug={slug} galleryId={id} allowDownloads={allowDownloads} - protectionLevel={protectionLevel} useEnhancedProtection={useEnhancedProtection} - useCanvasRendering={useCanvasRendering} />
diff --git a/frontend/src/components/gallery/layouts/story/StoryHero.tsx b/frontend/src/components/gallery/layouts/story/StoryHero.tsx index 66293623..6c56b841 100644 --- a/frontend/src/components/gallery/layouts/story/StoryHero.tsx +++ b/frontend/src/components/gallery/layouts/story/StoryHero.tsx @@ -11,9 +11,7 @@ interface StoryHeroProps { photo?: Photo | null; slug: string; allowDownloads?: boolean; - protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; - useCanvasRendering?: boolean; } export const StoryHero: React.FC = ({ @@ -22,8 +20,6 @@ export const StoryHero: React.FC = ({ stats, photo, slug, - protectionLevel = 'standard', - useCanvasRendering = false }) => { const formattedDate = date ? new Date(date).toLocaleDateString('en-US', { @@ -49,7 +45,6 @@ export const StoryHero: React.FC = ({ className="w-full h-full object-cover" isGallery={true} slug={slug} - useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'} /> ) : (
diff --git a/frontend/src/components/gallery/layouts/story/StoryPhotoCard.tsx b/frontend/src/components/gallery/layouts/story/StoryPhotoCard.tsx index a5eb5643..2cfeee02 100644 --- a/frontend/src/components/gallery/layouts/story/StoryPhotoCard.tsx +++ b/frontend/src/components/gallery/layouts/story/StoryPhotoCard.tsx @@ -14,9 +14,7 @@ interface StoryPhotoCardProps { onClick?: () => void; slug: string; allowDownloads?: boolean; - protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum'; useEnhancedProtection?: boolean; - useCanvasRendering?: boolean; featured?: boolean; galleryId: string; } @@ -28,8 +26,6 @@ export const StoryPhotoCard: React.FC = ({ onToggleFavorite, onClick, slug, - protectionLevel = 'standard', - useCanvasRendering = false, featured = false, galleryId: _galleryId }) => { @@ -103,7 +99,6 @@ export const StoryPhotoCard: React.FC = ({ }`} isGallery={true} slug={slug} - useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'} /> )} diff --git a/frontend/src/features/settings/tabs/ImageSecurityTab.tsx b/frontend/src/features/settings/tabs/ImageSecurityTab.tsx index 7c2a3354..86ccd266 100644 --- a/frontend/src/features/settings/tabs/ImageSecurityTab.tsx +++ b/frontend/src/features/settings/tabs/ImageSecurityTab.tsx @@ -184,7 +184,7 @@ export const ImageSecurityTab: React.FC = () => { /> - {t('settings.imageSecurity.enableCanvas', 'Enable canvas rendering by default (advanced protection)')} + {t('settings.imageSecurity.enableCanvas', 'Enable canvas rendering in the lightbox by default (advanced protection)')}
diff --git a/frontend/src/i18n/locales/de.json b/frontend/src/i18n/locales/de.json index 0f3567c4..3eef43b2 100644 --- a/frontend/src/i18n/locales/de.json +++ b/frontend/src/i18n/locales/de.json @@ -1934,7 +1934,7 @@ "disableRightClick": "Rechtsklick-Menü blockieren", "watermarkDownloads": "Wasserzeichen bei Downloads hinzufügen", "enableDevtoolsProtection": "Entwicklertools erkennen", - "useCanvasRendering": "Canvas-Rendering (erweiterter Schutz)", + "useCanvasRendering": "Canvas-Rendering in der Lightbox (erweiterter Schutz)", "protectionInfo": "Schutzfunktionen helfen, unerlaubte Downloads zu verhindern, können jedoch nicht alle Methoden blockieren.", "protectionLevelBasic": "Einfach - Nur Rechtsklick-Sperre", "protectionLevelStandard": "Standard - Tastenkombinationen blockiert", @@ -2374,7 +2374,7 @@ "protectionLevel": "Standard-Schutzstufe", "imageQuality": "Standard-Bildqualität", "enableDevtools": "DevTools-Erkennung standardmäßig aktivieren", - "enableCanvas": "Canvas-Rendering standardmäßig aktivieren (erweiterter Schutz)", + "enableCanvas": "Canvas-Rendering in der Lightbox standardmäßig aktivieren (erweiterter Schutz)", "rateLimiting": "Ratenbegrenzung", "rateLimitingHelp": "Begrenzen Sie, wie viele Bilder angefordert werden können, um Scraping zu verhindern.", "requestsPerMinute": "Anfragen pro Minute", diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 4b300b5c..61df73c0 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -1430,7 +1430,7 @@ "disableRightClick": "Block right-click menu", "watermarkDownloads": "Add watermark to downloads", "enableDevtoolsProtection": "Detect developer tools", - "useCanvasRendering": "Canvas rendering (advanced protection)", + "useCanvasRendering": "Canvas rendering in the lightbox (advanced protection)", "protectionInfo": "Protection features help prevent unauthorized downloads but cannot block all methods.", "protectionLevelBasic": "Basic - Right-click blocking only", "protectionLevelStandard": "Standard - Keyboard shortcuts blocked", @@ -1937,7 +1937,7 @@ "protectionLevel": "Default Protection Level", "imageQuality": "Default Image Quality", "enableDevtools": "Enable DevTools detection by default", - "enableCanvas": "Enable canvas rendering by default (advanced protection)", + "enableCanvas": "Enable canvas rendering in the lightbox by default (advanced protection)", "rateLimiting": "Rate Limiting", "rateLimitingHelp": "Limit how many images can be requested to prevent scraping.", "requestsPerMinute": "Requests per minute", diff --git a/frontend/src/i18n/locales/fr.json b/frontend/src/i18n/locales/fr.json index f18625db..03c7b368 100644 --- a/frontend/src/i18n/locales/fr.json +++ b/frontend/src/i18n/locales/fr.json @@ -498,7 +498,7 @@ "disableRightClick": "Bloquer le clic droit", "watermarkDownloads": "Ajouter un filigrane aux téléchargements", "enableDevtoolsProtection": "Détecter les outils de développement", - "useCanvasRendering": "Rendu canvas (protection avancée)", + "useCanvasRendering": "Rendu canvas dans la visionneuse (protection avancée)", "protectionInfo": "Les fonctionnalités de protection aident à prévenir les téléchargements non autorisés mais ne peuvent pas bloquer toutes les méthodes.", "protectionLevelBasic": "Basique - Blocage du clic droit uniquement", "protectionLevelStandard": "Standard - Blocage des raccourcis clavier", @@ -912,7 +912,7 @@ "protectionLevel": "Niveau de protection par défaut", "imageQuality": "Qualité d'image par défaut", "enableDevtools": "Activer la détection des outils DevTools par défaut", - "enableCanvas": "Activer le rendu canvas par défaut (protection avancée)", + "enableCanvas": "Activer le rendu canvas dans la visionneuse par défaut (protection avancée)", "rateLimiting": "Limitation de débit", "rateLimitingHelp": "Limitez le nombre d'images qui peuvent être demandées pour éviter le scraping.", "requestsPerMinute": "Requêtes par minute", diff --git a/frontend/src/i18n/locales/sl.json b/frontend/src/i18n/locales/sl.json index a02444bc..c13ca419 100644 --- a/frontend/src/i18n/locales/sl.json +++ b/frontend/src/i18n/locales/sl.json @@ -498,7 +498,7 @@ "disableRightClick": "Blokiraj meni desnega klika", "watermarkDownloads": "Dodaj vodni žig prenosom", "enableDevtoolsProtection": "Zaznaj orodja za razvijalce", - "useCanvasRendering": "Izris prek canvas (napredna zaščita)", + "useCanvasRendering": "Izris prek canvas v pregledovalniku (napredna zaščita)", "protectionInfo": "Zaščitne funkcije pomagajo preprečiti nepooblaščene prenose, vendar ne morejo blokirati vseh metod.", "protectionLevelBasic": "Osnovno - samo blokada desnega klika", "protectionLevelStandard": "Standardno - blokirane bližnjice na tipkovnici", @@ -912,7 +912,7 @@ "protectionLevel": "Privzeta raven zaščite", "imageQuality": "Privzeta kakovost slike", "enableDevtools": "Privzeto omogoči zaznavanje DevTools", - "enableCanvas": "Privzeto omogoči izris prek canvas (napredna zaščita)", + "enableCanvas": "Privzeto omogoči izris prek canvas v pregledovalniku (napredna zaščita)", "rateLimiting": "Omejevanje hitrosti", "rateLimitingHelp": "Omejite, koliko slik je mogoče zahtevati, da preprečite množično pobiranje.", "requestsPerMinute": "Zahtev na minuto", diff --git a/frontend/src/pages/admin/event-details/EventInformationCard.tsx b/frontend/src/pages/admin/event-details/EventInformationCard.tsx index 38aa686e..6311b2be 100644 --- a/frontend/src/pages/admin/event-details/EventInformationCard.tsx +++ b/frontend/src/pages/admin/event-details/EventInformationCard.tsx @@ -669,7 +669,7 @@ export const EventInformationCard: React.FC = ({ className="w-4 h-4 text-accent border-neutral-300 dark:border-neutral-600 rounded focus:ring-primary-500" /> - {t('events.useCanvasRendering', 'Canvas rendering (advanced protection)')} + {t('events.useCanvasRendering', 'Canvas rendering in the lightbox (advanced protection)')}