tok-to-insta-follower-bridge/src/lib/components/DetectedUserListItem.tsx
2024-12-01 17:27:29 +09:00

120 lines
3.5 KiB
TypeScript

import type { ProfileView } from "@atproto/api/dist/client/types/app/bsky/actor/defs";
import React from "react";
import { match } from "ts-pattern";
import type { BskyUser } from "~types";
import { ACTION_MODE } from "../constants";
import DetectedUserSource from "./DetectedUserSource";
import UserCard from "./UserCard";
export type Props = {
user: BskyUser;
actionMode: (typeof ACTION_MODE)[keyof typeof ACTION_MODE];
clickAction: (user: BskyUser) => Promise<void>;
reSearch: (user: {
sourceDid: string;
accountName: string;
displayName: string;
}) => Promise<void>;
};
const DetectedUserListItem = ({
user,
actionMode,
clickAction,
reSearch,
}: Props) => {
const [isBtnHovered, setIsBtnHovered] = React.useState(false);
const [isJustClicked, setIsJustClicked] = React.useState(false);
const actionBtnLabelAndClass = React.useMemo(
() =>
match(actionMode)
.with(ACTION_MODE.FOLLOW, ACTION_MODE.IMPORT_LIST, () => {
const follow = {
label: "Follow on Bluesky",
class: "btn-primary",
};
const following = {
label: "Following on Bluesky",
class:
"btn-outline hover:bg-transparent hover:border hover:bg-transparent hover:text-base-content",
};
const unfollow = {
label: "Unfollow on Bluesky",
class:
"text-red-500 hover:bg-transparent hover:border hover:border-red-500",
};
if (!isBtnHovered) {
return user.isFollowing ? following : follow;
}
if (user.isFollowing) {
return isJustClicked ? following : unfollow;
}
return follow;
})
.with(ACTION_MODE.BLOCK, () => {
const block = {
label: "Block on Bluesky",
class: "btn-primary",
};
const blocking = {
label: "Blocking on Bluesky",
class:
"btn-outline hover:bg-transparent hover:border hover:bg-transparent hover:text-base-content",
};
const unblock = {
label: "Unblock on Bluesky",
class:
"text-red-500 hover:bg-transparent hover:border hover:border-red-500",
};
if (!isBtnHovered) {
return user.isBlocking ? blocking : block;
}
if (user.isBlocking) {
return isJustClicked ? blocking : unblock;
}
return block;
})
.run(),
[
user.isFollowing,
user.isBlocking,
actionMode,
isBtnHovered,
isJustClicked,
],
);
const [loading, setLoading] = React.useState(false);
const handleActionButtonClick = async () => {
setLoading(true);
await clickAction(user);
setLoading(false);
setIsJustClicked(true);
};
const handleReSearchClick = () => {
reSearch({
sourceDid: user.did,
accountName: user.originalHandle,
displayName: user.originalDisplayName,
});
};
return (
<div className="bg-base-100 w-full relative grid grid-cols-[22%_1fr] gap-5">
<DetectedUserSource user={user} />
<UserCard
user={user}
loading={loading}
actionBtnLabelAndClass={actionBtnLabelAndClass}
handleActionButtonClick={handleActionButtonClick}
setIsBtnHovered={setIsBtnHovered}
setIsJustClicked={setIsJustClicked}
handleReSearchClick={handleReSearchClick}
/>
</div>
);
};
export default DetectedUserListItem;