Files
folx-tv/client/src/components/share-buttons.tsx
T
sebastjanartic a55d69614f Update website links to use the correct domain for image sharing
Replace all instances of "www.folx.tv" with "folx.tv" in the client and server configurations to resolve SSL issues preventing image sharing on social media platforms.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 1f7e7e89-a520-4970-9645-37daadc466dc
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 20f43e40-d815-42d5-9bb6-37729939c10e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/1f7e7e89-a520-4970-9645-37daadc466dc/mwtHL8H
Replit-Helium-Checkpoint-Created: true
2026-03-05 15:43:13 +00:00

143 lines
4.9 KiB
TypeScript

import { SiFacebook, SiLinkedin, SiX, SiWhatsapp, SiTelegram, SiPinterest } from "react-icons/si";
import { Mail, Link2, Check } from "lucide-react";
import { useState } from "react";
interface ShareButtonsProps {
url: string;
title: string;
image?: string;
}
const CANONICAL_DOMAIN = "https://folx.tv";
function canonicalUrl(url: string): string {
try {
const parsed = new URL(url);
return `${CANONICAL_DOMAIN}${parsed.pathname}${parsed.search}${parsed.hash}`;
} catch {
return url;
}
}
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",
icon: SiFacebook,
color: "hover:bg-[#1877F2] hover:text-white",
getUrl: (url: string) => `https://www.facebook.com/sharer.php?u=${encodeURIComponent(url)}`,
popup: true,
},
{
name: "X",
icon: SiX,
color: "hover:bg-[#000] hover:text-white",
getUrl: (url: string, title: string) => `https://x.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(title)}`,
popup: true,
},
{
name: "LinkedIn",
icon: SiLinkedin,
color: "hover:bg-[#0A66C2] hover:text-white",
getUrl: (url: string) => `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`,
popup: true,
},
{
name: "WhatsApp",
icon: SiWhatsapp,
color: "hover:bg-[#25D366] hover:text-white",
getUrl: (url: string, title: string) => `https://wa.me/?text=${encodeURIComponent(title + " " + url)}`,
},
{
name: "Telegram",
icon: SiTelegram,
color: "hover:bg-[#26A5E4] hover:text-white",
getUrl: (url: string, title: string) => `https://t.me/share/url?url=${encodeURIComponent(url)}&text=${encodeURIComponent(title)}`,
},
{
name: "Pinterest",
icon: SiPinterest,
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) : ""}`,
popup: true,
},
{
name: "E-Mail",
icon: Mail,
color: "hover:bg-muted-foreground hover:text-white",
getUrl: (url: string, title: string) => `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(title + "\n\n" + url)}`,
},
];
export default function ShareButtons({ url, title, image }: ShareButtonsProps) {
const [copied, setCopied] = useState(false);
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(canonicalUrl(url));
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch {
const input = document.createElement("input");
input.value = canonicalUrl(url);
document.body.appendChild(input);
input.select();
document.execCommand("copy");
document.body.removeChild(input);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
};
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 (
<div className="flex flex-wrap items-center gap-2" data-testid="share-buttons">
<span className="text-sm text-muted-foreground mr-1">Teilen:</span>
{SHARE_TARGETS.map((target) => (
<a
key={target.name}
href={target.getUrl(canonicalUrl(url), title, image ? canonicalUrl(image) : undefined)}
target="_blank"
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}`}
aria-label={`Auf ${target.name} teilen`}
data-testid={`button-share-${target.name.toLowerCase()}`}
>
<target.icon className="w-4 h-4" />
</a>
))}
<button
onClick={handleCopy}
className={`inline-flex items-center justify-center w-9 h-9 rounded-full border border-border transition-all duration-200 ${copied ? "bg-green-600 text-white border-green-600" : "text-muted-foreground hover:bg-muted-foreground hover:text-white"}`}
aria-label="Link kopieren"
data-testid="button-share-copy"
>
{copied ? <Check className="w-4 h-4" /> : <Link2 className="w-4 h-4" />}
</button>
</div>
);
}