Improve social media sharing functionality and image handling

Update social sharing buttons to use popup windows for a more reliable user experience. Adjust Facebook sharer URL format and ensure optimal OG image delivery by defaulting to JPG format and setting cache headers. Update image URLs in gallery data.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 1f7e7e89-a520-4970-9645-37daadc466dc
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 4a846f8c-2e0e-44e4-bcf6-7ac503fb3b19
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/1f7e7e89-a520-4970-9645-37daadc466dc/ZApZ5Qi
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
sebastjanartic 2026-03-05 14:39:35 +00:00
parent 9a81e63740
commit 7c72650f90
4 changed files with 1155 additions and 283 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -19,24 +19,43 @@ function canonicalUrl(url: string): string {
} }
} }
const SHARE_TARGETS = [ function openPopup(shareUrl: string) {
const w = 600;
const h = 500;
const left = window.screenX + (window.outerWidth - w) / 2;
const top = window.screenY + (window.outerHeight - h) / 2;
window.open(shareUrl, "share", `width=${w},height=${h},left=${left},top=${top},toolbar=no,menubar=no,scrollbars=yes`);
}
interface ShareTarget {
name: string;
icon: typeof SiFacebook;
color: string;
getUrl: (url: string, title: string, image?: string) => string;
popup?: boolean;
}
const SHARE_TARGETS: ShareTarget[] = [
{ {
name: "Facebook", name: "Facebook",
icon: SiFacebook, icon: SiFacebook,
color: "hover:bg-[#1877F2] hover:text-white", color: "hover:bg-[#1877F2] hover:text-white",
getUrl: (url: string) => `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`, getUrl: (url: string) => `https://www.facebook.com/sharer.php?u=${encodeURIComponent(url)}`,
popup: true,
}, },
{ {
name: "X", name: "X",
icon: SiX, icon: SiX,
color: "hover:bg-[#000] hover:text-white", color: "hover:bg-[#000] hover:text-white",
getUrl: (url: string, title: string) => `https://x.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(title)}`, getUrl: (url: string, title: string) => `https://x.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(title)}`,
popup: true,
}, },
{ {
name: "LinkedIn", name: "LinkedIn",
icon: SiLinkedin, icon: SiLinkedin,
color: "hover:bg-[#0A66C2] hover:text-white", color: "hover:bg-[#0A66C2] hover:text-white",
getUrl: (url: string) => `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`, getUrl: (url: string) => `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`,
popup: true,
}, },
{ {
name: "WhatsApp", name: "WhatsApp",
@ -55,6 +74,7 @@ const SHARE_TARGETS = [
icon: SiPinterest, icon: SiPinterest,
color: "hover:bg-[#BD081C] hover:text-white", color: "hover:bg-[#BD081C] hover:text-white",
getUrl: (url: string, title: string, image?: string) => `https://pinterest.com/pin/create/button/?url=${encodeURIComponent(url)}&description=${encodeURIComponent(title)}${image ? "&media=" + encodeURIComponent(image) : ""}`, getUrl: (url: string, title: string, image?: string) => `https://pinterest.com/pin/create/button/?url=${encodeURIComponent(url)}&description=${encodeURIComponent(title)}${image ? "&media=" + encodeURIComponent(image) : ""}`,
popup: true,
}, },
{ {
name: "E-Mail", name: "E-Mail",
@ -84,6 +104,14 @@ export default function ShareButtons({ url, title, image }: ShareButtonsProps) {
} }
}; };
const handleShare = (target: ShareTarget, e: React.MouseEvent) => {
const shareUrl = target.getUrl(canonicalUrl(url), title, image ? canonicalUrl(image) : undefined);
if (target.popup) {
e.preventDefault();
openPopup(shareUrl);
}
};
return ( return (
<div className="flex flex-wrap items-center gap-2" data-testid="share-buttons"> <div className="flex flex-wrap items-center gap-2" data-testid="share-buttons">
<span className="text-sm text-muted-foreground mr-1">Teilen:</span> <span className="text-sm text-muted-foreground mr-1">Teilen:</span>
@ -93,6 +121,7 @@ export default function ShareButtons({ url, title, image }: ShareButtonsProps) {
href={target.getUrl(canonicalUrl(url), title, image ? canonicalUrl(image) : undefined)} href={target.getUrl(canonicalUrl(url), title, image ? canonicalUrl(image) : undefined)}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
onClick={(e) => handleShare(target, e)}
className={`inline-flex items-center justify-center w-9 h-9 rounded-full border border-border text-muted-foreground transition-all duration-200 ${target.color}`} className={`inline-flex items-center justify-center w-9 h-9 rounded-full border border-border text-muted-foreground transition-all duration-200 ${target.color}`}
aria-label={`Auf ${target.name} teilen`} aria-label={`Auf ${target.name} teilen`}
data-testid={`button-share-${target.name.toLowerCase()}`} data-testid={`button-share-${target.name.toLowerCase()}`}

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,13 @@ export function serveStatic(app: Express) {
); );
} }
app.use(express.static(distPath)); app.use(express.static(distPath, {
setHeaders(res, filePath) {
if (filePath.endsWith("og-image.jpg") || filePath.includes("/uploads/")) {
res.setHeader("Cache-Control", "public, max-age=86400");
}
},
}));
app.use("/{*path}", async (req, res) => { app.use("/{*path}", async (req, res) => {
const url = req.originalUrl; const url = req.originalUrl;