Merge pull request #1299 from PicPeak/fix/1297-inert-protection-props
fix(gallery): remove the inert image-protection prop surface from AuthenticatedImage
This commit is contained in:
@@ -11,25 +11,12 @@ import {
|
|||||||
interface AuthenticatedImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, 'onLoad'> {
|
interface AuthenticatedImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, 'onLoad'> {
|
||||||
src: string;
|
src: string;
|
||||||
fallbackSrc?: string;
|
fallbackSrc?: string;
|
||||||
useWatermark?: boolean;
|
|
||||||
isGallery?: boolean;
|
isGallery?: boolean;
|
||||||
protectFromDownload?: boolean;
|
|
||||||
slug?: string;
|
slug?: string;
|
||||||
photoId?: number;
|
|
||||||
requiresToken?: boolean;
|
|
||||||
secureUrlTemplate?: string;
|
|
||||||
downloadUrlTemplate?: string;
|
|
||||||
onProtectionViolation?: (violationType: string) => void;
|
|
||||||
watermarkText?: string;
|
|
||||||
overlayProtection?: boolean;
|
|
||||||
fragmentGrid?: boolean;
|
|
||||||
scrambleFragments?: boolean;
|
|
||||||
useCanvasRendering?: boolean;
|
useCanvasRendering?: boolean;
|
||||||
blockKeyboardShortcuts?: boolean;
|
/** Fired when the canvas branch blocks a context-menu attempt. The only
|
||||||
detectPrintScreen?: boolean;
|
* protection callback this component actually implements (#1297). */
|
||||||
detectDevTools?: boolean;
|
onProtectionViolation?: (violationType: string) => void;
|
||||||
protectionLevel?: 'basic' | 'standard' | 'enhanced' | 'maximum';
|
|
||||||
useEnhancedProtection?: boolean;
|
|
||||||
onLoad?: () => void;
|
onLoad?: () => void;
|
||||||
/**
|
/**
|
||||||
* Priority in the shared fetch queue (#1287). NOT the native `fetchPriority`
|
* Priority in the shared fetch queue (#1287). NOT the native `fetchPriority`
|
||||||
@@ -43,51 +30,44 @@ interface AuthenticatedImageProps extends Omit<React.ImgHTMLAttributes<HTMLImage
|
|||||||
queuePriority?: 'high' | 'prefetch' | 'normal';
|
queuePriority?: 'high' | 'prefetch' | 'normal';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches an image with the gallery's bearer token and renders it.
|
||||||
|
*
|
||||||
|
* IMAGE PROTECTION IS NOT IMPLEMENTED HERE (#1297). This component used to
|
||||||
|
* accept the whole protection prop surface — protectFromDownload,
|
||||||
|
* watermarkText, fragmentGrid, blockKeyboardShortcuts, detectPrintScreen,
|
||||||
|
* detectDevTools, protectionLevel and the rest — and discard every one of
|
||||||
|
* them in a `void unusedProps` block. Callers computed them from the event's
|
||||||
|
* protection level and passed them in good faith, so raising that level
|
||||||
|
* produced canvas rendering (via the layouts' own OR on
|
||||||
|
* `protectionLevel === 'maximum'`) and nothing else it implies.
|
||||||
|
*
|
||||||
|
* They are removed rather than implemented, so the interface states what the
|
||||||
|
* component actually does. The implementation those props describe already
|
||||||
|
* exists in `ProtectedImage` — which is exported and currently rendered
|
||||||
|
* nowhere. Wiring that in is a deliberate product decision about what
|
||||||
|
* protection level should mean, not a silent side effect of a cleanup.
|
||||||
|
*
|
||||||
|
* Two props survive because they are real:
|
||||||
|
* useCanvasRendering draws to a canvas instead of an <img>
|
||||||
|
* onProtectionViolation fires from the canvas context-menu handler below
|
||||||
|
*
|
||||||
|
* `useWatermark` was removed too. #1297 did not list it — it sat outside the
|
||||||
|
* `unusedProps` block — but it was equally inert: declared, defaulted, never
|
||||||
|
* read.
|
||||||
|
*/
|
||||||
export const AuthenticatedImage: React.FC<AuthenticatedImageProps> = ({
|
export const AuthenticatedImage: React.FC<AuthenticatedImageProps> = ({
|
||||||
src,
|
src,
|
||||||
fallbackSrc,
|
fallbackSrc,
|
||||||
alt,
|
alt,
|
||||||
useWatermark = false,
|
|
||||||
isGallery = false,
|
isGallery = false,
|
||||||
protectFromDownload,
|
|
||||||
slug,
|
slug,
|
||||||
photoId,
|
|
||||||
requiresToken,
|
|
||||||
secureUrlTemplate,
|
|
||||||
downloadUrlTemplate,
|
|
||||||
onProtectionViolation,
|
|
||||||
watermarkText,
|
|
||||||
overlayProtection,
|
|
||||||
fragmentGrid,
|
|
||||||
scrambleFragments,
|
|
||||||
useCanvasRendering,
|
useCanvasRendering,
|
||||||
blockKeyboardShortcuts,
|
onProtectionViolation,
|
||||||
detectPrintScreen,
|
|
||||||
detectDevTools,
|
|
||||||
protectionLevel,
|
|
||||||
useEnhancedProtection,
|
|
||||||
onLoad,
|
onLoad,
|
||||||
queuePriority = 'normal',
|
queuePriority = 'normal',
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const unusedProps = {
|
|
||||||
protectFromDownload,
|
|
||||||
photoId,
|
|
||||||
requiresToken,
|
|
||||||
secureUrlTemplate,
|
|
||||||
downloadUrlTemplate,
|
|
||||||
onProtectionViolation,
|
|
||||||
watermarkText,
|
|
||||||
overlayProtection,
|
|
||||||
fragmentGrid,
|
|
||||||
scrambleFragments,
|
|
||||||
blockKeyboardShortcuts,
|
|
||||||
detectPrintScreen,
|
|
||||||
detectDevTools,
|
|
||||||
protectionLevel,
|
|
||||||
useEnhancedProtection
|
|
||||||
};
|
|
||||||
void unusedProps;
|
|
||||||
|
|
||||||
const [imageSrc, setImageSrc] = useState<string>('');
|
const [imageSrc, setImageSrc] = useState<string>('');
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
|
|||||||
@@ -41,9 +41,7 @@ export const GalleryFolderTiles: React.FC<GalleryFolderTilesProps> = ({
|
|||||||
compact = false,
|
compact = false,
|
||||||
slug,
|
slug,
|
||||||
protectionLevel,
|
protectionLevel,
|
||||||
useEnhancedProtection,
|
|
||||||
useCanvasRendering,
|
useCanvasRendering,
|
||||||
allowDownloads = true,
|
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -96,12 +94,6 @@ export const GalleryFolderTiles: React.FC<GalleryFolderTilesProps> = ({
|
|||||||
className="w-full h-full object-cover group-hover:scale-[1.02] transition-transform"
|
className="w-full h-full object-cover group-hover:scale-[1.02] transition-transform"
|
||||||
isGallery
|
isGallery
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={coverPhoto.id}
|
|
||||||
requiresToken={coverPhoto.requires_token}
|
|
||||||
secureUrlTemplate={coverPhoto.secure_url_template}
|
|
||||||
protectFromDownload={!allowDownloads || useEnhancedProtection}
|
|
||||||
protectionLevel={protectionLevel}
|
|
||||||
useEnhancedProtection={useEnhancedProtection}
|
|
||||||
// Same rule as every other gallery image path: maximum
|
// Same rule as every other gallery image path: maximum
|
||||||
// protection implies canvas rendering even when the separate
|
// protection implies canvas rendering even when the separate
|
||||||
// toggle is off (its default), otherwise a cover silently
|
// toggle is off (its default), otherwise a cover silently
|
||||||
|
|||||||
@@ -43,9 +43,7 @@ export const HeroHeader: React.FC<HeroHeaderProps> = ({
|
|||||||
heroLogoSize = 'medium',
|
heroLogoSize = 'medium',
|
||||||
heroLogoPosition = 'top',
|
heroLogoPosition = 'top',
|
||||||
dividerStyle = 'wave',
|
dividerStyle = 'wave',
|
||||||
allowDownloads = true,
|
|
||||||
protectionLevel = 'standard',
|
protectionLevel = 'standard',
|
||||||
useEnhancedProtection = false,
|
|
||||||
useCanvasRendering = false,
|
useCanvasRendering = false,
|
||||||
onScrollToContent,
|
onScrollToContent,
|
||||||
heroImageAnchor = 'center'
|
heroImageAnchor = 'center'
|
||||||
@@ -144,10 +142,6 @@ export const HeroHeader: React.FC<HeroHeaderProps> = ({
|
|||||||
style={{ objectPosition: heroImageAnchor }}
|
style={{ objectPosition: heroImageAnchor }}
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={heroPhoto.id}
|
|
||||||
protectFromDownload={!allowDownloads || useEnhancedProtection}
|
|
||||||
protectionLevel={protectionLevel}
|
|
||||||
useEnhancedProtection={useEnhancedProtection}
|
|
||||||
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -144,9 +144,6 @@ export const PeopleSheet: React.FC<PeopleSheetProps> = ({
|
|||||||
alt=""
|
alt=""
|
||||||
isGallery
|
isGallery
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={photo.id}
|
|
||||||
requiresToken={photo.requires_token}
|
|
||||||
secureUrlTemplate={photo.secure_url_template}
|
|
||||||
// Crop to the face, exactly as the strip does. Without
|
// Crop to the face, exactly as the strip does. Without
|
||||||
// this a group photo shows whoever is centred — often
|
// this a group photo shows whoever is centred — often
|
||||||
// not the person being labelled, and identical for two
|
// not the person being labelled, and identical for two
|
||||||
|
|||||||
@@ -86,9 +86,6 @@ const PersonAvatar: React.FC<PersonAvatarProps> = ({
|
|||||||
alt=""
|
alt=""
|
||||||
isGallery
|
isGallery
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={photo.id}
|
|
||||||
requiresToken={photo.requires_token}
|
|
||||||
secureUrlTemplate={photo.secure_url_template}
|
|
||||||
style={cropStyle || { width: '100%', height: '100%', objectFit: 'cover' }}
|
style={cropStyle || { width: '100%', height: '100%', objectFit: 'cover' }}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -244,7 +244,6 @@ const PhotoThumbnail: React.FC<PhotoThumbnailProps> = ({
|
|||||||
onDownload,
|
onDownload,
|
||||||
allowDownloads = true,
|
allowDownloads = true,
|
||||||
protectionLevel = 'standard',
|
protectionLevel = 'standard',
|
||||||
useEnhancedProtection = false,
|
|
||||||
useCanvasRendering = false,
|
useCanvasRendering = false,
|
||||||
slug,
|
slug,
|
||||||
feedbackEnabled = false
|
feedbackEnabled = false
|
||||||
@@ -269,18 +268,7 @@ const PhotoThumbnail: React.FC<PhotoThumbnailProps> = ({
|
|||||||
loading="lazy"
|
loading="lazy"
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={photo.id}
|
|
||||||
requiresToken={photo.requires_token}
|
|
||||||
secureUrlTemplate={photo.secure_url_template}
|
|
||||||
protectFromDownload={!allowDownloads || useEnhancedProtection}
|
|
||||||
protectionLevel={protectionLevel}
|
|
||||||
useEnhancedProtection={useEnhancedProtection}
|
|
||||||
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
||||||
fragmentGrid={protectionLevel === 'enhanced' || protectionLevel === 'maximum'}
|
|
||||||
blockKeyboardShortcuts={useEnhancedProtection}
|
|
||||||
detectPrintScreen={useEnhancedProtection}
|
|
||||||
detectDevTools={protectionLevel === 'maximum'}
|
|
||||||
watermarkText={useEnhancedProtection ? 'Protected' : undefined}
|
|
||||||
onProtectionViolation={(violationType) => {
|
onProtectionViolation={(violationType) => {
|
||||||
// Track analytics
|
// Track analytics
|
||||||
if (typeof window !== 'undefined' && (window as any).umami) {
|
if (typeof window !== 'undefined' && (window as any).umami) {
|
||||||
|
|||||||
@@ -1159,9 +1159,6 @@ export const PhotoLightbox: React.FC<PhotoLightboxProps> = ({
|
|||||||
draggable={false}
|
draggable={false}
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={photo.id}
|
|
||||||
requiresToken={photo.requires_token}
|
|
||||||
secureUrlTemplate={photo.secure_url_template}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -1189,21 +1186,9 @@ export const PhotoLightbox: React.FC<PhotoLightboxProps> = ({
|
|||||||
transition: isDragging ? 'none' : 'transform 0.2s',
|
transition: isDragging ? 'none' : 'transform 0.2s',
|
||||||
}}
|
}}
|
||||||
draggable={false}
|
draggable={false}
|
||||||
useWatermark={useEnhancedProtection}
|
|
||||||
watermarkText={useEnhancedProtection ? `${photo.filename} - Protected` : undefined}
|
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={photo.id}
|
|
||||||
requiresToken={photo.requires_token}
|
|
||||||
secureUrlTemplate={photo.secure_url_template}
|
|
||||||
protectFromDownload={!allowDownloads || useEnhancedProtection}
|
|
||||||
protectionLevel={protectionLevel}
|
|
||||||
useEnhancedProtection={useEnhancedProtection}
|
|
||||||
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
||||||
fragmentGrid={protectionLevel === 'enhanced' || protectionLevel === 'maximum'}
|
|
||||||
blockKeyboardShortcuts={useEnhancedProtection}
|
|
||||||
detectPrintScreen={useEnhancedProtection}
|
|
||||||
detectDevTools={protectionLevel === 'enhanced' || protectionLevel === 'maximum'}
|
|
||||||
onProtectionViolation={(violationType) => {
|
onProtectionViolation={(violationType) => {
|
||||||
console.warn(`Protection violation in lightbox for photo ${photo.id}: ${violationType}`);
|
console.warn(`Protection violation in lightbox for photo ${photo.id}: ${violationType}`);
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ export const CarouselGalleryLayout: React.FC<BaseGalleryLayoutProps> = ({
|
|||||||
alt={currentPhoto.filename}
|
alt={currentPhoto.filename}
|
||||||
className="w-full h-full object-contain"
|
className="w-full h-full object-contain"
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
protectFromDownload={!allowDownloads}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Colour labels for the photo in view (#1189). Bottom-left because it
|
{/* Colour labels for the photo in view (#1189). Bottom-left because it
|
||||||
@@ -267,7 +266,6 @@ export const CarouselGalleryLayout: React.FC<BaseGalleryLayoutProps> = ({
|
|||||||
className="w-full h-full object-cover"
|
className="w-full h-full object-cover"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
protectFromDownload={!allowDownloads}
|
|
||||||
/>
|
/>
|
||||||
{/* The strip is the only place this layout shows more than one
|
{/* The strip is the only place this layout shows more than one
|
||||||
photo at a time, so it is the only place a label can
|
photo at a time, so it is the only place a label can
|
||||||
|
|||||||
@@ -68,9 +68,7 @@ const PhotoCard: React.FC<PhotoCardProps> = ({
|
|||||||
isSelectionMode,
|
isSelectionMode,
|
||||||
isLiked,
|
isLiked,
|
||||||
slug,
|
slug,
|
||||||
allowDownloads = true,
|
|
||||||
protectionLevel = 'standard',
|
protectionLevel = 'standard',
|
||||||
useEnhancedProtection = false,
|
|
||||||
useCanvasRendering = false,
|
useCanvasRendering = false,
|
||||||
feedbackEnabled = false,
|
feedbackEnabled = false,
|
||||||
allowLikes = false,
|
allowLikes = false,
|
||||||
@@ -124,12 +122,6 @@ const PhotoCard: React.FC<PhotoCardProps> = ({
|
|||||||
loading="lazy"
|
loading="lazy"
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={photo.id}
|
|
||||||
requiresToken={photo.requires_token}
|
|
||||||
secureUrlTemplate={photo.secure_url_template}
|
|
||||||
protectFromDownload={!allowDownloads || useEnhancedProtection}
|
|
||||||
protectionLevel={protectionLevel}
|
|
||||||
useEnhancedProtection={useEnhancedProtection}
|
|
||||||
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ const GridPhoto: React.FC<GridPhotoProps> = ({
|
|||||||
allowDownloads = true,
|
allowDownloads = true,
|
||||||
slug,
|
slug,
|
||||||
protectionLevel = 'standard',
|
protectionLevel = 'standard',
|
||||||
useEnhancedProtection = false,
|
|
||||||
useCanvasRendering = false,
|
useCanvasRendering = false,
|
||||||
feedbackEnabled = false,
|
feedbackEnabled = false,
|
||||||
feedbackOptions,
|
feedbackOptions,
|
||||||
@@ -93,18 +92,7 @@ const GridPhoto: React.FC<GridPhotoProps> = ({
|
|||||||
loading: 'lazy',
|
loading: 'lazy',
|
||||||
isGallery: true,
|
isGallery: true,
|
||||||
slug,
|
slug,
|
||||||
photoId: photo.id,
|
|
||||||
requiresToken: photo.requires_token,
|
|
||||||
secureUrlTemplate: photo.secure_url_template,
|
|
||||||
protectFromDownload: !allowDownloads || useEnhancedProtection,
|
|
||||||
protectionLevel,
|
|
||||||
useEnhancedProtection,
|
|
||||||
useCanvasRendering: useCanvasRendering || protectionLevel === 'maximum',
|
useCanvasRendering: useCanvasRendering || protectionLevel === 'maximum',
|
||||||
fragmentGrid: protectionLevel === 'enhanced' || protectionLevel === 'maximum',
|
|
||||||
blockKeyboardShortcuts: useEnhancedProtection,
|
|
||||||
detectPrintScreen: useEnhancedProtection,
|
|
||||||
detectDevTools: protectionLevel === 'maximum',
|
|
||||||
watermarkText: useEnhancedProtection ? 'Protected' : undefined,
|
|
||||||
onProtectionViolation: (violationType: string) => {
|
onProtectionViolation: (violationType: string) => {
|
||||||
console.warn(`Protection violation on grid photo ${photo.id}: ${violationType}`);
|
console.warn(`Protection violation on grid photo ${photo.id}: ${violationType}`);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ const JustifiedPhoto: React.FC<JustifiedPhotoProps> = ({
|
|||||||
allowDownloads = true,
|
allowDownloads = true,
|
||||||
slug,
|
slug,
|
||||||
protectionLevel = 'standard',
|
protectionLevel = 'standard',
|
||||||
useEnhancedProtection = false,
|
|
||||||
useCanvasRendering = false,
|
useCanvasRendering = false,
|
||||||
feedbackEnabled = false,
|
feedbackEnabled = false,
|
||||||
feedbackOptions,
|
feedbackOptions,
|
||||||
@@ -134,18 +133,7 @@ const JustifiedPhoto: React.FC<JustifiedPhotoProps> = ({
|
|||||||
loading: 'lazy',
|
loading: 'lazy',
|
||||||
isGallery: true,
|
isGallery: true,
|
||||||
slug,
|
slug,
|
||||||
photoId: photo.id,
|
|
||||||
requiresToken: photo.requires_token,
|
|
||||||
secureUrlTemplate: photo.secure_url_template,
|
|
||||||
protectFromDownload: !allowDownloads || useEnhancedProtection,
|
|
||||||
protectionLevel,
|
|
||||||
useEnhancedProtection,
|
|
||||||
useCanvasRendering: useCanvasRendering || protectionLevel === 'maximum',
|
useCanvasRendering: useCanvasRendering || protectionLevel === 'maximum',
|
||||||
fragmentGrid: protectionLevel === 'enhanced' || protectionLevel === 'maximum',
|
|
||||||
blockKeyboardShortcuts: useEnhancedProtection,
|
|
||||||
detectPrintScreen: useEnhancedProtection,
|
|
||||||
detectDevTools: protectionLevel === 'maximum',
|
|
||||||
watermarkText: useEnhancedProtection ? 'Protected' : undefined,
|
|
||||||
onProtectionViolation: (violationType: string) => {
|
onProtectionViolation: (violationType: string) => {
|
||||||
console.warn(`Protection violation on justified photo ${photo.id}: ${violationType}`);
|
console.warn(`Protection violation on justified photo ${photo.id}: ${violationType}`);
|
||||||
},
|
},
|
||||||
@@ -411,10 +399,6 @@ export const JustifiedGalleryLayout: React.FC<JustifiedGalleryLayoutProps> = ({
|
|||||||
className="w-full h-full object-cover"
|
className="w-full h-full object-cover"
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={heroPhoto.id}
|
|
||||||
protectFromDownload={!allowDownloads || useEnhancedProtection}
|
|
||||||
protectionLevel={protectionLevel}
|
|
||||||
useEnhancedProtection={useEnhancedProtection}
|
|
||||||
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ const MasonryPhoto: React.FC<MasonryPhotoProps> = ({
|
|||||||
className: 'w-full h-full object-cover rounded-lg',
|
className: 'w-full h-full object-cover rounded-lg',
|
||||||
loading: 'lazy',
|
loading: 'lazy',
|
||||||
isGallery: true,
|
isGallery: true,
|
||||||
protectFromDownload: !allowDownloads,
|
|
||||||
}}
|
}}
|
||||||
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 rounded-lg flex items-center justify-center gap-2"
|
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 rounded-lg flex items-center justify-center gap-2"
|
||||||
allowDownloads={allowDownloads}
|
allowDownloads={allowDownloads}
|
||||||
@@ -376,7 +375,6 @@ export const MasonryGalleryLayout: React.FC<BaseGalleryLayoutProps> = ({
|
|||||||
className: 'w-full h-full object-cover rounded-lg transition-transform duration-300 group-hover:scale-[1.02]',
|
className: 'w-full h-full object-cover rounded-lg transition-transform duration-300 group-hover:scale-[1.02]',
|
||||||
loading: 'lazy',
|
loading: 'lazy',
|
||||||
isGallery: true,
|
isGallery: true,
|
||||||
protectFromDownload: !allowDownloads,
|
|
||||||
}}
|
}}
|
||||||
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 rounded-lg flex items-center justify-center gap-2"
|
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 rounded-lg flex items-center justify-center gap-2"
|
||||||
actionVariant="dark"
|
actionVariant="dark"
|
||||||
@@ -434,7 +432,6 @@ export const MasonryGalleryLayout: React.FC<BaseGalleryLayoutProps> = ({
|
|||||||
className: 'w-full h-full object-cover rounded-lg transition-transform duration-300 group-hover:scale-[1.02]',
|
className: 'w-full h-full object-cover rounded-lg transition-transform duration-300 group-hover:scale-[1.02]',
|
||||||
loading: 'lazy',
|
loading: 'lazy',
|
||||||
isGallery: true,
|
isGallery: true,
|
||||||
protectFromDownload: !allowDownloads,
|
|
||||||
}}
|
}}
|
||||||
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 rounded-lg flex items-center justify-center gap-2"
|
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 rounded-lg flex items-center justify-center gap-2"
|
||||||
actionVariant="dark"
|
actionVariant="dark"
|
||||||
@@ -501,7 +498,6 @@ export const MasonryGalleryLayout: React.FC<BaseGalleryLayoutProps> = ({
|
|||||||
className: 'w-full h-full object-cover transition-transform duration-300 group-hover:scale-105',
|
className: 'w-full h-full object-cover transition-transform duration-300 group-hover:scale-105',
|
||||||
loading: 'lazy',
|
loading: 'lazy',
|
||||||
isGallery: true,
|
isGallery: true,
|
||||||
protectFromDownload: !allowDownloads,
|
|
||||||
}}
|
}}
|
||||||
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 flex items-center justify-center gap-2"
|
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 flex items-center justify-center gap-2"
|
||||||
actionVariant="dark"
|
actionVariant="dark"
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ const MosaicPhoto: React.FC<MosaicPhotoProps> = ({
|
|||||||
className: 'w-full h-full object-cover transition-transform duration-300 group-hover:scale-105',
|
className: 'w-full h-full object-cover transition-transform duration-300 group-hover:scale-105',
|
||||||
loading: 'lazy',
|
loading: 'lazy',
|
||||||
isGallery: true,
|
isGallery: true,
|
||||||
protectFromDownload: !allowDownloads,
|
|
||||||
}}
|
}}
|
||||||
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 flex items-center justify-center gap-2"
|
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 flex items-center justify-center gap-2"
|
||||||
allowDownloads={allowDownloads}
|
allowDownloads={allowDownloads}
|
||||||
|
|||||||
@@ -130,7 +130,6 @@ export const TimelineGalleryLayout: React.FC<BaseGalleryLayoutProps> = ({
|
|||||||
className: 'w-full h-full object-cover rounded-lg',
|
className: 'w-full h-full object-cover rounded-lg',
|
||||||
loading: 'lazy',
|
loading: 'lazy',
|
||||||
isGallery: true,
|
isGallery: true,
|
||||||
protectFromDownload: !allowDownloads,
|
|
||||||
}}
|
}}
|
||||||
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 rounded-lg flex items-center justify-center gap-2"
|
overlayBaseClassName="absolute inset-0 bg-black/40 transition-opacity duration-200 rounded-lg flex items-center justify-center gap-2"
|
||||||
allowDownloads={allowDownloads}
|
allowDownloads={allowDownloads}
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ export const StoryHero: React.FC<StoryHeroProps> = ({
|
|||||||
stats,
|
stats,
|
||||||
photo,
|
photo,
|
||||||
slug,
|
slug,
|
||||||
allowDownloads = true,
|
|
||||||
protectionLevel = 'standard',
|
protectionLevel = 'standard',
|
||||||
useEnhancedProtection = false,
|
|
||||||
useCanvasRendering = false
|
useCanvasRendering = false
|
||||||
}) => {
|
}) => {
|
||||||
const formattedDate = date
|
const formattedDate = date
|
||||||
@@ -51,12 +49,6 @@ export const StoryHero: React.FC<StoryHeroProps> = ({
|
|||||||
className="w-full h-full object-cover"
|
className="w-full h-full object-cover"
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={photo.id}
|
|
||||||
requiresToken={photo.requires_token}
|
|
||||||
secureUrlTemplate={photo.secure_url_template}
|
|
||||||
protectFromDownload={!allowDownloads || useEnhancedProtection}
|
|
||||||
protectionLevel={protectionLevel}
|
|
||||||
useEnhancedProtection={useEnhancedProtection}
|
|
||||||
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -28,9 +28,7 @@ export const StoryPhotoCard: React.FC<StoryPhotoCardProps> = ({
|
|||||||
onToggleFavorite,
|
onToggleFavorite,
|
||||||
onClick,
|
onClick,
|
||||||
slug,
|
slug,
|
||||||
allowDownloads = true,
|
|
||||||
protectionLevel = 'standard',
|
protectionLevel = 'standard',
|
||||||
useEnhancedProtection = false,
|
|
||||||
useCanvasRendering = false,
|
useCanvasRendering = false,
|
||||||
featured = false,
|
featured = false,
|
||||||
galleryId: _galleryId
|
galleryId: _galleryId
|
||||||
@@ -105,12 +103,6 @@ export const StoryPhotoCard: React.FC<StoryPhotoCardProps> = ({
|
|||||||
}`}
|
}`}
|
||||||
isGallery={true}
|
isGallery={true}
|
||||||
slug={slug}
|
slug={slug}
|
||||||
photoId={photo.id}
|
|
||||||
requiresToken={photo.requires_token}
|
|
||||||
secureUrlTemplate={photo.secure_url_template}
|
|
||||||
protectFromDownload={!allowDownloads || useEnhancedProtection}
|
|
||||||
protectionLevel={protectionLevel}
|
|
||||||
useEnhancedProtection={useEnhancedProtection}
|
|
||||||
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
useCanvasRendering={useCanvasRendering || protectionLevel === 'maximum'}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user