Compare commits

..

8 Commits

Author SHA1 Message Date
Paul Nothaft 9b50f3d6b7 Merge pull request #109 from the-luap/release-please--branches--main
Build and Push Docker Images / build-backend (push) Failing after 3m36s
Build and Push Docker Images / build-frontend (push) Failing after 3m21s
Build and Push Docker Images / summary (push) Successful in 3s
chore(main): release 2.3.3
2026-01-15 09:24:12 -05:00
github-actions[bot] e945bc9413 chore(main): release 2.3.3 2026-01-15 14:23:34 +00:00
Paul Nothaft 3b720ed56e fix: lightbox watermark loading, white label translations, and dynamic footer year (#108)
fix: lightbox watermark loading, white label translations, and dynamic footer year
2026-01-15 09:23:10 -05:00
Paul Nothaft ce8587b24d fix: lightbox watermark loading, white label translations, and dynamic footer year
- Fix watermarked images not opening in lightbox (add /api prefix to photo URLs)
- Add i18n translations for 'White Label' and 'Hide Powered by' branding settings
- Add complete logo customization translations (EN and DE)
- Replace hardcoded © 2024 with dynamic current year in footer
- Use company name from settings in default footer text
2026-01-15 14:16:00 +01:00
Paul Nothaft fe772b52d6 Merge pull request #106 from the-luap/release-please--branches--main
Build and Push Docker Images / build-backend (push) Failing after 4m6s
Build and Push Docker Images / build-frontend (push) Failing after 3m56s
Build and Push Docker Images / summary (push) Successful in 3s
chore(main): release 2.3.2
2026-01-15 08:03:07 -05:00
github-actions[bot] f29b77998b chore(main): release 2.3.2 2026-01-15 13:02:43 +00:00
Paul Nothaft f843e4c25c Merge pull request #105 from the-luap/fix/codeql-v4-upgrade
fix: watermark thumbnails, custom logo display, and German translations
2026-01-15 08:02:28 -05:00
Paul Nothaft ea20446a79 fix: watermark thumbnails, custom logo display, and German translations
- Fix thumbnail display when watermarks enabled globally on existing galleries
  - Backend: Apply watermarks to thumbnails at the thumbnail endpoint
  - Frontend: Remove hack that redirected thumbnails to photo endpoint
- Fix custom logo display in gallery hero sections
  - Only apply brightness/invert filter to default PicPeak logo
  - Custom logos now display as-is with drop-shadow only
- Add German translations for Event Creation and Image Protection settings
  - settings.events: Pflichtfelder, Kundenname/E-Mail erforderlich, etc.
  - settings.imageSecurity: Bildschutz, Ratenbegrenzung, Sicherheitsüberwachung
  - Protection level options in both EN and DE locales
2026-01-15 13:57:22 +01:00
13 changed files with 151 additions and 21 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
{
".": "2.3.1"
".": "2.3.3"
}
+17
View File
@@ -5,6 +5,23 @@ All notable changes to PicPeak will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.3.3](https://github.com/the-luap/picpeak/compare/v2.3.2...v2.3.3) (2026-01-15)
### Bug Fixes
* lightbox watermark loading, white label translations, and dynamic footer year ([3b720ed](https://github.com/the-luap/picpeak/commit/3b720ed56ecd2ded6aec57309f8c408c63a617ef))
* lightbox watermark loading, white label translations, and dynamic footer year ([ce8587b](https://github.com/the-luap/picpeak/commit/ce8587b24df3f53a11a74348eff8b5c5b96c5488))
* lightbox watermark loading, white label translations, and dynamic footer year ([#108](https://github.com/the-luap/picpeak/issues/108)) ([3b720ed](https://github.com/the-luap/picpeak/commit/3b720ed56ecd2ded6aec57309f8c408c63a617ef))
## [2.3.2](https://github.com/the-luap/picpeak/compare/v2.3.1...v2.3.2) (2026-01-15)
### Bug Fixes
* watermark thumbnails, custom logo display, and German translations ([f843e4c](https://github.com/the-luap/picpeak/commit/f843e4c25cef02eef354fd3ee25824e20e4f8fc8))
* watermark thumbnails, custom logo display, and German translations ([ea20446](https://github.com/the-luap/picpeak/commit/ea20446a797a00cf45dbe7bf6f06574a79c4d8a6))
## [2.3.1](https://github.com/the-luap/picpeak/compare/v2.3.0...v2.3.1) (2026-01-15)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "picpeak-backend",
"version": "2.3.1",
"version": "2.3.3",
"description": "Backend for PicPeak event photo sharing platform",
"main": "server.js",
"scripts": {
+11 -2
View File
@@ -829,8 +829,17 @@ router.get('/:slug/thumbnail/:photoId',
'X-Protected-Thumbnail': 'true'
});
// Send file
res.sendFile(path.resolve(thumbPath));
// Check if watermarks are enabled and apply to thumbnail
const watermarkSettings = await watermarkService.getWatermarkSettings();
if (watermarkSettings && watermarkSettings.enabled) {
// Apply watermark to thumbnail
const watermarkedBuffer = await watermarkService.applyWatermark(thumbPath, watermarkSettings);
res.send(watermarkedBuffer);
} else {
// Send file without watermark
res.sendFile(path.resolve(thumbPath));
}
} catch (error) {
logger.error('Error serving thumbnail:', {
error: error.message,
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "picpeak-frontend",
"private": true,
"version": "2.3.1",
"version": "2.3.3",
"type": "module",
"scripts": {
"dev": "vite",
@@ -366,7 +366,10 @@ export const GalleryLayout: React.FC<GalleryLayoutProps> = ({
className={`${heroLogoSize.className} w-auto object-contain mx-auto`}
style={{
...(heroLogoSize.style || {}),
filter: 'brightness(0) invert(1) drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3))'
// Only apply brightness/invert filter to default logo; custom logos display as-is
filter: brandingSettings?.logo_url
? 'drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3))'
: 'brightness(0) invert(1) drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3))'
}}
/>
{shouldShowCompanyName() && brandingSettings?.company_name && (
@@ -441,7 +444,7 @@ export const GalleryLayout: React.FC<GalleryLayoutProps> = ({
</p>
)}
<p className="text-xs sm:text-sm text-neutral-500">
{brandingSettings?.footer_text || '© 2024 Your Company. All rights reserved.'}
{brandingSettings?.footer_text || `© ${new Date().getFullYear()}${brandingSettings?.company_name ? ` ${brandingSettings.company_name}` : ''}. All rights reserved.`}
{!brandingSettings?.hide_powered_by && (
<> | Powered by <span className="font-semibold">PicPeak</span></>
)}
@@ -203,7 +203,7 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
company_name: settingsData.branding_company_name || '',
company_tagline: settingsData.branding_company_tagline || '',
support_email: settingsData.branding_support_email || '',
footer_text: settingsData.branding_footer_text || '© 2024 Your Company. All rights reserved.',
footer_text: settingsData.branding_footer_text || '',
watermark_enabled: settingsData.branding_watermark_enabled || false,
logo_url: settingsData.branding_logo_url || null,
logo_size: settingsData.branding_logo_size || 'medium',
@@ -380,12 +380,12 @@ export const GalleryView: React.FC<GalleryViewProps> = ({ slug, event }) => {
}
});
// Transform URLs for watermarks if enabled
// Transform full-size URLs for watermarks if enabled
// Note: Thumbnails are watermarked server-side at the thumbnail endpoint
if (watermarkEnabled) {
photos = photos.map(photo => ({
...photo,
url: `/gallery/${slug}/photo/${photo.id}`,
thumbnail_url: `/gallery/${slug}/photo/${photo.id}` // Use watermarked version for thumbnails too
url: `/api/gallery/${slug}/photo/${photo.id}`
}));
}
@@ -142,8 +142,11 @@ export const HeroGalleryLayout: React.FC<HeroGalleryLayoutProps> = ({
}
alt="Event logo"
className="h-20 sm:h-24 lg:h-32 mx-auto"
style={{
filter: 'brightness(0) invert(1) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5))'
style={{
// Only apply brightness/invert filter to default logo; custom logos display as-is
filter: eventLogo
? 'drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5))'
: 'brightness(0) invert(1) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5))'
}}
/>
</div>
+71 -1
View File
@@ -778,6 +778,10 @@
"enableDevtoolsProtection": "Entwicklertools erkennen",
"useCanvasRendering": "Canvas-Rendering (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",
"protectionLevelEnhanced": "Erweitert - Bildschirmfoto-Erkennung",
"protectionLevelMaximum": "Maximum - DevTools-Erkennung & Canvas-Rendering",
"heroPhoto": "Hero-Foto",
"heroPhotoHelp": "Wählen Sie ein hervorgehobenes Foto für das Hero-Galerie-Layout",
"selectHeroPhoto": "Hero-Foto auswählen",
@@ -1032,6 +1036,48 @@
"saveSettings": "Sicherheitseinstellungen speichern",
"saveSecuritySettings": "Sicherheitseinstellungen speichern"
},
"events": {
"title": "Veranstaltungserstellung",
"requiredFields": "Pflichtfelder",
"requiredFieldsDescription": "Konfigurieren Sie, welche Kontaktfelder beim Erstellen neuer Veranstaltungen erforderlich sind.",
"requireCustomerName": "Kundenname erforderlich",
"requireCustomerNameHelp": "Kundenname muss für neue Veranstaltungen angegeben werden",
"requireCustomerEmail": "Kunden-E-Mail erforderlich",
"requireCustomerEmailHelp": "Kunden-E-Mail muss für neue Veranstaltungen angegeben werden",
"customerEmailWarning": "Erforderlich für das Versenden von Galerie-Einladungen",
"requireAdminEmail": "Admin-E-Mail erforderlich",
"requireAdminEmailHelp": "Admin-E-Mail muss für neue Veranstaltungen angegeben werden",
"adminEmailWarning": "Erforderlich für den Erhalt von Veranstaltungsbenachrichtigungen",
"saveSettings": "Veranstaltungseinstellungen speichern",
"noteTitle": "Hinweis",
"noteText": "Diese Einstellungen betreffen nur die Erstellung neuer Veranstaltungen. Bestehende Veranstaltungen sind nicht betroffen. Standardmäßig sind alle Felder erforderlich."
},
"imageSecurity": {
"title": "Bildschutz",
"saveSuccess": "Bildschutz-Einstellungen gespeichert",
"saveError": "Fehler beim Speichern der Einstellungen",
"loadError": "Fehler beim Laden der Bildschutz-Einstellungen",
"defaultProtection": "Standard-Schutzeinstellungen",
"defaultProtectionHelp": "Diese Einstellungen gelten für alle neuen Veranstaltungen. Einzelne Veranstaltungen können diese Standardwerte überschreiben.",
"protectionLevel": "Standard-Schutzstufe",
"imageQuality": "Standard-Bildqualität",
"fragmentationLevel": "Fragmentierungsstufe",
"enableDevtools": "DevTools-Erkennung standardmäßig aktivieren",
"enableCanvas": "Canvas-Rendering 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",
"requestsPer5Minutes": "Anfragen pro 5 Min.",
"requestsPerHour": "Anfragen pro Stunde",
"securityMonitoring": "Sicherheitsüberwachung",
"suspiciousThreshold": "Schwellenwert für verdächtige Aktivitäten",
"autoBlockThreshold": "Automatische Sperrschwelle",
"enableMonitoring": "Sicherheitsüberwachung aktivieren",
"blockSuspiciousIps": "Verdächtige IPs automatisch blockieren",
"logEvents": "Sicherheitsereignisse in Datenbank protokollieren",
"infoTitle": "Über Bildschutz",
"infoText": "Diese Schutzfunktionen helfen, gelegentliches Herunterladen und Kopieren zu verhindern, können aber nicht alle Methoden blockieren. Entschlossene Benutzer finden möglicherweise trotzdem Wege, Bilder zu erfassen. Erwägen Sie die Verwendung von Wasserzeichen und rechtlichen Vereinbarungen für umfassenden Schutz."
},
"categories": {
"title": "Kategorien",
"about": "Über Fotokategorien",
@@ -1209,7 +1255,31 @@
"customizeTheme": "Design anpassen",
"saveTheme": "Design speichern",
"previewLayout": "Vorschau-Layout",
"livePreview": "Live-Vorschau"
"livePreview": "Live-Vorschau",
"whiteLabel": "White Label",
"hidePoweredBy": "\"Powered by PicPeak\" Branding ausblenden",
"hidePoweredByHelp": "Entfernen Sie die PicPeak-Kennzeichnung aus Galerie-Fußzeilen für ein vollständig personalisiertes Erscheinungsbild",
"logoCustomization": "Logo-Anpassung",
"changeLogo": "Logo ändern",
"logoSizeSmall": "Klein (32px)",
"logoSizeMedium": "Mittel (48px)",
"logoSizeLarge": "Groß (64px)",
"logoSizeXLarge": "Extra Groß (96px)",
"logoSizeCustom": "Benutzerdefiniert",
"logoMaxHeight": "Maximale Höhe (Pixel)",
"logoMaxHeightHelp": "Legen Sie eine benutzerdefinierte maximale Höhe für das Logo fest (20-200 Pixel)",
"logoPosition": "Logo-Position im Header",
"positionLeft": "Links",
"positionCenter": "Mitte",
"positionRight": "Rechts",
"logoDisplayMode": "Anzeigemodus",
"logoOnly": "Nur Logo",
"textOnly": "Nur Firmenname",
"logoAndText": "Logo und Firmenname",
"showLogoInHeader": "Logo im Galerie-Header anzeigen",
"showLogoInHeaderHelp": "Logo in der Hauptkopfzeile anzeigen",
"showLogoInHero": "Logo im Hero-Bereich anzeigen",
"showLogoInHeroHelp": "Logo in Hero-Bereichen anzeigen (für Nicht-Raster-Layouts)"
},
"admin": {
"title": "Admin-Panel",
+29 -1
View File
@@ -452,6 +452,10 @@
"enableDevtoolsProtection": "Detect developer tools",
"useCanvasRendering": "Canvas rendering (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",
"protectionLevelEnhanced": "Enhanced - Print screen detection",
"protectionLevelMaximum": "Maximum - DevTools detection & canvas rendering",
"heroPhoto": "Hero Photo",
"heroPhotoHelp": "Select a featured photo for the hero gallery layout",
"selectHeroPhoto": "Select Hero Photo",
@@ -1014,7 +1018,31 @@
"customizeTheme": "Customize Theme",
"saveTheme": "Save Theme",
"previewLayout": "Preview Layout",
"livePreview": "Live Preview"
"livePreview": "Live Preview",
"whiteLabel": "White Label",
"hidePoweredBy": "Hide \"Powered by PicPeak\" branding",
"hidePoweredByHelp": "Remove the PicPeak attribution from gallery footers for a fully white-labeled experience",
"logoCustomization": "Logo Customization",
"changeLogo": "Change Logo",
"logoSizeSmall": "Small (32px)",
"logoSizeMedium": "Medium (48px)",
"logoSizeLarge": "Large (64px)",
"logoSizeXLarge": "Extra Large (96px)",
"logoSizeCustom": "Custom",
"logoMaxHeight": "Maximum Height (pixels)",
"logoMaxHeightHelp": "Set a custom maximum height for the logo (20-200 pixels)",
"logoPosition": "Logo Position in Header",
"positionLeft": "Left",
"positionCenter": "Center",
"positionRight": "Right",
"logoDisplayMode": "Display Mode",
"logoOnly": "Logo Only",
"textOnly": "Company Name Only",
"logoAndText": "Logo and Company Name",
"showLogoInHeader": "Show logo in gallery header",
"showLogoInHeaderHelp": "Display the logo in the main header bar",
"showLogoInHero": "Show logo in hero section",
"showLogoInHeroHelp": "Display the logo in hero sections (for non-grid layouts)"
},
"admin": {
"title": "Admin Panel",
+2 -2
View File
@@ -15,7 +15,7 @@ export const BrandingPage: React.FC = () => {
const [brandingSettings, setBrandingSettings] = useState<BrandingSettings>({
company_name: '',
company_tagline: '',
footer_text: '© 2024 Your Company. All rights reserved.',
footer_text: '',
support_email: '',
watermark_enabled: false,
watermark_position: 'bottom-right',
@@ -307,7 +307,7 @@ export const BrandingPage: React.FC = () => {
onChange={(e) => handleBrandingChange('footer_text', e.target.value)}
className="w-full px-3 py-2 border border-neutral-300 rounded-lg focus:ring-2 focus:ring-primary-500"
rows={2}
placeholder="© 2024 Your Company. All rights reserved."
placeholder={`© ${new Date().getFullYear()} Your Company. All rights reserved.`}
/>
</div>
</div>
+1 -1
View File
@@ -144,7 +144,7 @@ export const LegalPage: React.FC = () => {
</Link>
</div>
<p className="text-sm text-neutral-500 mt-4">
© 2024 PicPeak. All rights reserved.
© {new Date().getFullYear()} PicPeak. All rights reserved.
</p>
</div>
</footer>
+3 -3
View File
@@ -12,10 +12,10 @@ interface PhotoUrlOptions {
*/
export function getPhotoUrl({ slug, photo, watermarkEnabled = false, token }: PhotoUrlOptions): string {
if (watermarkEnabled && token) {
// Use the watermarked photo endpoint
return `/gallery/${slug}/photo/${photo.id}`;
// Use the watermarked photo endpoint (needs /api prefix)
return `/api/gallery/${slug}/photo/${photo.id}`;
}
// Use the static photo URL
return photo.url;
}