/** * Renders the Follow buttons of a user's profile and of a playlist's page. * Both go through `FollowContext`, which follows at once and rolls back when * the request fails; the button then says so beside it. * * @module */ import { useState } from "react"; import { t } from "@lingui/core/macro"; import { Trans } from "@lingui/react/macro"; import { useAuth } from "../../hooks/auth/useAuth.ts"; import { useFollows } from "../../hooks/social/useFollows.ts"; /** Passed to {@link FollowUserButton} by the `UserPublicProfile` page. */ export interface FollowUserButtonProps { targetUserId: string; /** Names the user in the button's accessible label. */ targetUsername: string; } /** Passed to {@link FollowPlaylistButton} by `PlaylistHeader`. */ export interface FollowPlaylistButtonProps { targetPlaylistId: string; /** Hides the button, since only a public playlist can be followed. */ isPublic: boolean; } /** * Renders the button that follows or unfollows a user. It renders nothing for * a visitor or on the user's own profile, and is disabled until the follows * have loaded. */ export function FollowUserButton( { targetUserId, targetUsername }: FollowUserButtonProps, ): React.JSX.Element | null { const { user } = useAuth(); const { followedUserIds, followUser, unfollowUser, isLoaded } = useFollows(); const [failed, setFailed] = useState(false); if (!user || user.id === targetUserId) return null; const isFollowing = followedUserIds.has(targetUserId); return ( <> {failed && } ); } /** * Renders the button that follows or unfollows a playlist. It renders nothing * for a visitor or a private playlist, and is disabled until the follows have * loaded. Unlike {@link FollowUserButton}, it shows on the user's own * playlists too. */ export function FollowPlaylistButton( { targetPlaylistId, isPublic }: FollowPlaylistButtonProps, ): React.JSX.Element | null { const { user } = useAuth(); const { followedPlaylistIds, followPlaylist, unfollowPlaylist, isLoaded } = useFollows(); const [failed, setFailed] = useState(false); if (!user || !isPublic) return null; const isFollowing = followedPlaylistIds.has(targetPlaylistId); return ( <> {failed && } ); } function FollowError(): React.JSX.Element { return ( Couldn't update. Try again. ); }