feat: add donation link card

This commit is contained in:
kawamataryo 2024-12-08 20:43:56 +09:00
parent 6dafcdbb8e
commit 9af8f9b957
4 changed files with 106 additions and 13 deletions

@ -0,0 +1,101 @@
import { Storage } from "@plasmohq/storage";
import { useStorage } from "@plasmohq/storage/hook";
import { AnimatePresence, motion } from "framer-motion";
import React from "react";
import { STORAGE_KEYS } from "~lib/constants";
import { getMessageWithLink } from "~lib/utils";
const DonationCard = () => {
const [userClosed, setUserClosed] = useStorage<boolean>(
{
key: STORAGE_KEYS.DONATION_CARD_USER_CLOSED,
instance: new Storage({
area: "local",
}),
},
false,
);
const handleClose = () => {
setUserClosed(true);
setIsVisible(false);
};
const handleDonationLinkClick = () => {
handleClose();
window.open("https://ko-fi.com/kawamataryo", "_blank");
};
const [isVisible, setIsVisible] = React.useState(false);
React.useEffect(() => {
const showDonationCard = () => {
if (userClosed) return;
setIsVisible(true);
};
const timeoutId = setTimeout(showDonationCard, 2000);
return () => clearTimeout(timeoutId);
}, [userClosed]);
return (
<>
<AnimatePresence>
{isVisible && (
<motion.div
className="card bg-neutral text-neutral-content shadow-lg w-96 relative"
initial={{ y: "100%", opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: "100%", opacity: 0 }}
transition={{ type: "spring", stiffness: 50, damping: 10 }}
>
<div className="card-body p-4">
<div className="flex gap-2 items-center">
<p
className="text-xs"
// biome-ignore lint/security/noDangerouslySetInnerHtml: <explanation>
dangerouslySetInnerHTML={{
__html: getMessageWithLink("donate_message"),
}}
/>
<button
type="button"
onClick={handleDonationLinkClick}
style={{ display: "inline-block" }}
className="w-full"
>
<img
src="https://storage.ko-fi.com/cdn/kofi1.png?v=6"
alt="Buy Me a Coffee at ko-fi.com"
className="w-[120px] h-auto m-auto"
/>
</button>
</div>
</div>
<div className="absolute top-[-10px] right-[-10px]">
<button
className="btn btn-circle btn-sm bg-neutral text-neutral-content"
type="button"
onClick={handleClose}
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
</motion.div>
)}
</AnimatePresence>
</>
);
};
export default React.memo(DonationCard);

@ -184,19 +184,6 @@ const Sidebar = ({
__html: getMessageWithLink("donate_message"),
}}
/>
<a
href="https://ko-fi.com/kawamataryo"
target="_blank"
rel="noreferrer"
style={{ display: "inline-block" }}
className="w-full"
>
<img
src="https://storage.ko-fi.com/cdn/kofi1.png?v=6"
alt="Buy Me a Coffee at ko-fi.com"
className="w-[120px] h-auto m-auto"
/>
</a>
<div className="divider" />
<SocialLinks />
</div>

@ -44,6 +44,7 @@ export const STORAGE_KEYS = {
DETECTED_BSKY_USERS: `${STORAGE_PREFIX}_detected_bsky_users`,
LIST_NAME: `${STORAGE_PREFIX}_list_name`,
RENDER_KEY: `${STORAGE_PREFIX}_render_key`,
DONATION_CARD_USER_CLOSED: `${STORAGE_PREFIX}_donation_card_user_closed`,
} as const;
export const TARGET_URLS_REGEX = {

@ -8,6 +8,7 @@ import type { ProfileView } from "@atproto/api/dist/client/types/app/bsky/actor/
import React from "react";
import ReSearchModal from "~components/ReSearchModal";
import DetectedUserListItem from "~lib/components/DetectedUserListItem";
import DonationCard from "~lib/components/DonationCard";
const Option = () => {
const {
@ -185,6 +186,9 @@ const Option = () => {
))}
</div>
</div>
<div className="fixed bottom-5 right-5">
<DonationCard />
</div>
<ReSearchModal
open={showReSearchModal}
onClose={handleCloseReSearchModal}