xLog/src/components/site/Platform.tsx

273 lines
6.6 KiB
TypeScript

"use client"
import { useDebounceEffect } from "ahooks"
import { useEffect, useState } from "react"
import { Tooltip } from "~/components/ui/Tooltip"
import { UniLink } from "~/components/ui/UniLink"
import { cn } from "~/lib/utils"
const iconCDN = "https://icons.ly"
// There is no need to set this icon if it is available by default `https://cdn.simpleicons.org/${platform}`
export const PlatformsSyncMap: {
[key: string]: {
name: string
icon?: string
url?: string
identityFormatTemplate?: string
portfolioDomain?: string
}
} = {
telegram: {
name: "Telegram",
url: "https://t.me/{username}",
},
tg_channel: {
name: "Telegram Channel",
icon: `${iconCDN}/telegram`,
url: "https://t.me/{username}",
},
twitter: {
name: "X",
icon: `${iconCDN}/x`,
url: "https://x.com/{username}",
portfolioDomain: `https://x.com/`,
},
twitter_id: {
name: "X",
icon: `${iconCDN}/x`,
url: "https://x.com/i/user/{username}",
},
x: {
name: "X",
icon: `${iconCDN}/x/_/fff`,
url: "https://x.com/{username}",
portfolioDomain: `https://x.com/`,
},
x_id: {
name: "X",
icon: `${iconCDN}/x/_/fff`,
url: "https://x.com/i/user/{username}",
},
pixiv: {
name: "Pixiv",
url: "https://www.pixiv.net/users/{username}",
portfolioDomain: `https://www.pixiv.net/`,
},
substack: {
name: "Substack",
url: "https://{username}.substack.com/",
},
medium: {
name: "Medium",
url: "https://medium.com/@{username}",
},
github: {
name: "GitHub",
icon: `${iconCDN}/github/_/fff`,
url: "https://github.com/{username}",
portfolioDomain: `https://github.com/`,
},
jike: {
name: "即刻",
icon: "/assets/social/jike.png",
url: "https://web.okjike.com/u/{username}",
},
bilibili: {
name: "bilibili",
icon: "/assets/social/bilibili.svg",
url: "https://space.bilibili.com/{username}",
portfolioDomain: `https://www.bilibili.com/`,
},
zhihu: {
name: "知乎",
url: "https://www.zhihu.com/people/{username}",
},
playstation: {
name: "PlayStation",
url: "https://psnprofiles.com/{username}",
},
"nintendo switch": {
name: "Nintendo Switch",
icon: `${iconCDN}/nintendoswitch`,
},
"discord server": {
name: "Discord Server",
icon: `${iconCDN}/discord`,
url: "https://discord.gg/{username}",
},
"discord user": {
name: "Discord User",
icon: `${iconCDN}/discord`,
url: "https://discord.com/users/{username}",
},
xiaoyuzhou: {
name: "小宇宙播客",
icon: "/assets/social/xiaoyuzhou2.png",
url: "https://www.xiaoyuzhoufm.com/podcast/{username}",
portfolioDomain: `https://www.xiaoyuzhoufm.com/`,
},
steam: {
name: "Steam",
url: "https://steamcommunity.com/id/{username}",
},
steam_profiles: {
name: "Steam",
icon: `${iconCDN}/steam`,
url: "https://steamcommunity.com/profiles/{username}",
},
gitlab: {
name: "Gitlab",
url: "https://gitlab.com/{username}",
},
keybase: {
name: "Keybase",
url: "https://keybase.io/{username}",
},
youtube: {
name: "Youtube",
url: "https://youtube.com/@{username}",
portfolioDomain: `https://youtube.com/`,
},
facebook: {
name: "Facebook",
url: "https://facebook.com/{username}",
},
whatsapp: {
name: "Whatsapp",
url: "https://wa.me/{username}",
},
mastodon: {
name: "Mastodon",
url: "https://{instance}/@{username}",
identityFormatTemplate: "username@instance.ltd",
},
misskey: {
name: "Misskey",
url: "https://{instance}/@{username}",
identityFormatTemplate: "username@instance.ltd",
},
pleroma: {
name: "Pleroma",
url: "https://{instance}/users/{username}",
identityFormatTemplate: "username@instance.ltd",
},
douban: {
name: "豆瓣",
icon: "/assets/social/douban.png",
url: "https://www.douban.com/people/{username}",
},
email: {
name: "Email",
icon: "/assets/social/email.png",
url: "mailto:{username}",
},
"500px": {
name: "500px",
url: "https://500px.com/p/{username}",
},
threads: {
name: "Threads",
icon: `${iconCDN}/threads`,
url: "https://www.threads.net/@{username}",
},
instagram: {
name: "Instagram",
icon: `${iconCDN}/instagram`,
url: "https://www.instagram.com/{username}",
},
phaver: {
name: "Phaver",
icon: "/assets/social/phaver.png",
url: "https://phaver.app.link/{username}",
},
warpcast: {
name: "Warpcast",
icon: `${iconCDN}/farcaster`,
url: "https://warpcast.com/{username}",
},
debank: {
name: "DeBank",
icon: "/assets/social/debank.png",
url: "https://debank.com/profile/{username}",
},
}
export const Platform = ({
platform,
username,
className,
}: {
platform: string
username: string
className?: string
}) => {
platform = platform.toLowerCase()
const [debouncePlatform, setDebouncePlatform] = useState(platform)
useDebounceEffect(
() => {
setDebouncePlatform(platform)
},
[platform],
{ wait: 500 },
)
let link = PlatformsSyncMap[debouncePlatform]?.url
switch (debouncePlatform) {
case "mastodon":
case "misskey":
case "pleroma":
const [uname, instance] = username?.split("@")
link = link?.replace("{instance}", instance).replace("{username}", uname)
break
default:
link = link?.replace("{username}", username)
break
}
const [showImg, setShowImg] = useState(true)
useEffect(() => {
setShowImg(true)
}, [debouncePlatform])
return (
<UniLink
className={cn(
"size-5 inline-flex hover:scale-110 ease align-middle mr-3 sm:mr-6 transition-transform",
className,
)}
key={debouncePlatform + username}
href={link}
>
<Tooltip
label={`${PlatformsSyncMap[debouncePlatform]?.name || debouncePlatform}: ${username}`}
className="text-sm"
>
<span className="inline-flex items-center">
{showImg ? (
// eslint-disable-next-line @next/next/no-img-element
<img
src={
PlatformsSyncMap[debouncePlatform]?.icon ||
`${iconCDN}/${debouncePlatform}`
}
alt={debouncePlatform}
width={20}
height={20}
onError={() => setShowImg(false)}
/>
) : (
<span className="rounded-md inline-flex text-white justify-center items-center bg-zinc-300">
<i className="i-mingcute-planet-line text-xl" />
</span>
)}
</span>
</Tooltip>
</UniLink>
)
}