feat: enhance FollowButton

This commit is contained in:
codytseng
2025-03-02 22:48:50 +08:00
parent 186b23386a
commit 36240edc12
12 changed files with 92 additions and 26 deletions

View File

@@ -1,3 +1,14 @@
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger
} from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button'
import { useToast } from '@/hooks'
import { useFollowList } from '@/providers/FollowListProvider'
@@ -12,6 +23,7 @@ export default function FollowButton({ pubkey }: { pubkey: string }) {
const { pubkey: accountPubkey, checkLogin } = useNostr()
const { followings, follow, unfollow } = useFollowList()
const [updating, setUpdating] = useState(false)
const [hover, setHover] = useState(false)
const isFollowing = useMemo(() => followings.includes(pubkey), [followings, pubkey])
if (!accountPubkey || (pubkey && pubkey === accountPubkey)) return null
@@ -57,16 +69,41 @@ export default function FollowButton({ pubkey }: { pubkey: string }) {
}
return isFollowing ? (
<Button
className="w-20 min-w-20 rounded-full"
variant="secondary"
onClick={handleUnfollow}
disabled={updating}
>
{updating ? <Loader className="animate-spin" /> : t('Unfollow')}
</Button>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
className="rounded-full min-w-28"
variant={hover ? 'destructive' : 'secondary'}
disabled={updating}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
{updating ? (
<Loader className="animate-spin" />
) : hover ? (
t('Unfollow')
) : (
t('buttonFollowing')
)}
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{t('Unfollow')}?</AlertDialogTitle>
<AlertDialogDescription>
{t('Are you sure you want to unfollow this user?')}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>{t('Cancel')}</AlertDialogCancel>
<AlertDialogAction onClick={handleUnfollow} variant="destructive">
{t('Unfollow')}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
) : (
<Button className="w-20 min-w-20 rounded-full" onClick={handleFollow} disabled={updating}>
<Button className="rounded-full min-w-28" onClick={handleFollow} disabled={updating}>
{updating ? <Loader className="animate-spin" /> : t('Follow')}
</Button>
)

View File

@@ -201,6 +201,9 @@ export default {
'Your donation helps me maintain Jumble and make it better! 😊':
'تبرعك يساعد في صيانة Jumble وتحسينه! 😊',
'Earlier notifications': 'الإشعارات السابقة',
'Temporarily display this note': 'عرض هذه الملاحظة مؤقتاً'
'Temporarily display this note': 'عرض هذه الملاحظة مؤقتاً',
buttonFollowing: 'جارٍ المتابعة',
'Are you sure you want to unfollow this user?':
'هل أنت متأكد أنك تريد إلغاء متابعة هذا المستخدم؟'
}
}

View File

@@ -206,6 +206,9 @@ export default {
'Your donation helps me maintain Jumble and make it better! 😊':
'Deine Spende hilft mir, Jumble zu pflegen und zu verbessern! 😊',
'Earlier notifications': 'Frühere Benachrichtigungen',
'Temporarily display this note': 'Notiz vorübergehend anzeigen'
'Temporarily display this note': 'Notiz vorübergehend anzeigen',
buttonFollowing: 'Folge',
'Are you sure you want to unfollow this user?':
'Möchtest du diesem Benutzer wirklich nicht mehr folgen?'
}
}

View File

@@ -202,6 +202,8 @@ export default {
'Your donation helps me maintain Jumble and make it better! 😊':
'Your donation helps me maintain Jumble and make it better! 😊',
'Earlier notifications': 'Earlier notifications',
'Temporarily display this note': 'Temporarily display this note'
'Temporarily display this note': 'Temporarily display this note',
buttonFollowing: 'Following',
'Are you sure you want to unfollow this user?': 'Are you sure you want to unfollow this user?'
}
}

View File

@@ -206,6 +206,9 @@ export default {
'Your donation helps me maintain Jumble and make it better! 😊':
'¡Tu donación me ayuda a mantener y mejorar Jumble! 😊',
'Earlier notifications': 'Notificaciones anteriores',
'Temporarily display this note': 'Mostrar esta nota temporalmente'
'Temporarily display this note': 'Mostrar esta nota temporalmente',
buttonFollowing: 'Siguiendo',
'Are you sure you want to unfollow this user?':
'¿Estás seguro de que deseas dejar de seguir a este usuario?'
}
}

View File

@@ -204,6 +204,9 @@ export default {
'Your donation helps me maintain Jumble and make it better! 😊':
"Votre don m'aide à maintenir Jumble et à l'améliorer ! 😊",
'Earlier notifications': 'Notifications antérieures',
'Temporarily display this note': 'Afficher temporairement cette note'
'Temporarily display this note': 'Afficher temporairement cette note',
buttonFollowing: 'Suivi',
'Are you sure you want to unfollow this user?':
'Êtes-vous sûr de vouloir arrêter de suivre cet utilisateur ?'
}
}

View File

@@ -203,6 +203,8 @@ export default {
'Your donation helps me maintain Jumble and make it better! 😊':
'あなたの寄付はJumbleの維持と改善に役立ちます 😊',
'Earlier notifications': '以前の通知',
'Temporarily display this note': 'このノートを一時的に表示'
'Temporarily display this note': 'このノートを一時的に表示',
buttonFollowing: 'フォロー中',
'Are you sure you want to unfollow this user?': 'このユーザーのフォローを解除しますか?'
}
}

View File

@@ -204,6 +204,9 @@ export default {
'Earlier notifications': 'Wcześniejsze powiadomienia',
// NOTE: The translations below were generated by ChatGPT and have not yet been verified.
'Temporarily display this note': 'Tymczas wyświetl ten wpis'
'Temporarily display this note': 'Tymczas wyświetl ten wpis',
buttonFollowing: 'Obserwujesz',
'Are you sure you want to unfollow this user?':
'Czy na pewno chcesz przestać obserwować tego użytkownika?'
}
}

View File

@@ -204,6 +204,9 @@ export default {
'Your donation helps me maintain Jumble and make it better! 😊':
'Sua doação me ajuda a manter o Jumble e torná-lo melhor! 😊',
'Earlier notifications': 'Notificações anteriores',
'Temporarily display this note': 'Exibir esta nota temporariamente'
'Temporarily display this note': 'Exibir esta nota temporariamente',
buttonFollowing: 'Seguindo',
'Are you sure you want to unfollow this user?':
'Tem certeza de que deseja deixar de seguir este usuário?'
}
}

View File

@@ -206,6 +206,9 @@ export default {
'Your donation helps me maintain Jumble and make it better! 😊':
'Ваше пожертвование помогает поддерживать и улучшать Jumble! 😊',
'Earlier notifications': 'Ранние уведомления',
'Temporarily display this note': 'Временно отобразить эту заметку'
'Temporarily display this note': 'Временно отобразить эту заметку',
buttonFollowing: 'Подписан',
'Are you sure you want to unfollow this user?':
'Вы уверены, что хотите отписаться от этого пользователя?'
}
}

View File

@@ -203,6 +203,8 @@ export default {
'Your donation helps me maintain Jumble and make it better! 😊':
'您的捐赠帮助我维护 Jumble 并使其更好!😊',
'Earlier notifications': '更早的通知',
'Temporarily display this note': '临时显示此笔记'
'Temporarily display this note': '临时显示此笔记',
buttonFollowing: '已关注',
'Are you sure you want to unfollow this user?': '确定要取消关注此用户吗?'
}
}

View File

@@ -90,12 +90,7 @@ const ProfilePage = forwardRef(({ id, index }: { id?: string; index?: number },
</div>
</div>
<div className="px-4">
<div className="flex justify-end h-8 gap-2 items-center">
{isFollowingYou && (
<div className="text-muted-foreground rounded-full bg-muted text-xs h-fit px-2">
{t('Follows you')}
</div>
)}
<div className="flex justify-end h-8 gap-2 items-center max-sm:translate-x-2">
<ProfileOptions pubkey={pubkey} />
{isSelf ? (
<Button
@@ -113,7 +108,14 @@ const ProfilePage = forwardRef(({ id, index }: { id?: string; index?: number },
)}
</div>
<div className="pt-2">
<div className="text-xl font-semibold">{username}</div>
<div className="flex gap-2 items-center">
<div className="text-xl font-semibold truncate">{username}</div>
{isFollowingYou && (
<div className="text-muted-foreground rounded-full bg-muted text-xs h-fit px-2 shrink-0">
{t('Follows you')}
</div>
)}
</div>
<Nip05 pubkey={pubkey} />
{lightningAddress && (
<div className="text-sm text-yellow-400 flex gap-1 items-center">