2026-06-18 10:52:04 +00:00
|
|
|
<script lang="ts">
|
2026-07-28 16:16:26 +00:00
|
|
|
import {readable} from "svelte/store"
|
2026-06-18 10:52:04 +00:00
|
|
|
import {clamp} from "@welshman/lib"
|
|
|
|
|
import Shield from "@assets/icons/shield-minimalistic.svg?dataurl"
|
|
|
|
|
import Icon from "@lib/components/Icon.svelte"
|
|
|
|
|
import ProfileCircles from "@app/components/ProfileCircles.svelte"
|
2026-07-28 16:16:26 +00:00
|
|
|
import {followLists, profiles, user, wot} from "@app/core"
|
2026-06-18 10:52:04 +00:00
|
|
|
|
|
|
|
|
type Props = {
|
|
|
|
|
pubkey: string
|
|
|
|
|
isSelf?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const {pubkey: target, isSelf = false}: Props = $props()
|
|
|
|
|
|
2026-07-28 16:16:26 +00:00
|
|
|
const profileDisplay = $profiles.display(target).$
|
|
|
|
|
const followers = $wot.followers(target).$
|
2026-06-18 10:52:04 +00:00
|
|
|
|
2026-07-28 16:16:26 +00:00
|
|
|
const score = $derived($wot.wotScore($user.pubkey, target).$)
|
2026-06-18 10:52:04 +00:00
|
|
|
|
2026-07-28 16:16:26 +00:00
|
|
|
const followsWhoFollow = $derived(
|
|
|
|
|
!isSelf && $user.pubkey
|
|
|
|
|
? $wot.followsWhoFollow($user.pubkey, target).$
|
|
|
|
|
: readable<string[]>([]),
|
|
|
|
|
)
|
2026-06-18 10:52:04 +00:00
|
|
|
|
2026-07-28 16:16:26 +00:00
|
|
|
const followerCount = $derived($followers.length)
|
2026-06-18 10:52:04 +00:00
|
|
|
|
2026-07-28 16:16:26 +00:00
|
|
|
const networkFollowCount = $derived(isSelf ? followerCount : $followsWhoFollow.length)
|
2026-06-18 10:52:04 +00:00
|
|
|
|
|
|
|
|
const displayScore = $derived(isSelf ? followerCount : Math.round(clamp([0, 100], $score)))
|
|
|
|
|
const progress = $derived(isSelf ? undefined : displayScore)
|
|
|
|
|
|
|
|
|
|
const trustMessage = $derived.by(() => {
|
|
|
|
|
if (isSelf) {
|
|
|
|
|
if (followerCount === 0) return "No followers in your network yet."
|
|
|
|
|
|
|
|
|
|
return `Followed by ${followerCount}+ people in your network.`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (networkFollowCount > 0) {
|
|
|
|
|
return `Followed by ${networkFollowCount}+ people in your network.`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (displayScore >= 50) return "This user is highly trusted in your network."
|
|
|
|
|
if (displayScore >= 10) return "This user has some trust in your network."
|
|
|
|
|
|
|
|
|
|
return "This user is not well known in your network."
|
|
|
|
|
})
|
2026-07-28 16:16:26 +00:00
|
|
|
|
|
|
|
|
$effect(() => {
|
|
|
|
|
if (!isSelf) {
|
|
|
|
|
$followLists.load(target)
|
|
|
|
|
$followLists.load($user.pubkey)
|
|
|
|
|
}
|
|
|
|
|
})
|
2026-06-18 10:52:04 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<div class="card card-sm flex flex-col gap-3 sm:gap-4">
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
<Icon icon={Shield} size={5} />
|
|
|
|
|
<strong>Reputation</strong>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="flex flex-col gap-2 border-t border-line pt-4">
|
|
|
|
|
<div class="flex items-end justify-between gap-2">
|
|
|
|
|
<span class="text-sm opacity-75">{isSelf ? "Followers" : "Trust score"}</span>
|
|
|
|
|
<span class="text-lg font-semibold">
|
|
|
|
|
{#if isSelf}
|
|
|
|
|
{displayScore}
|
|
|
|
|
{:else}
|
|
|
|
|
{displayScore} / 100
|
|
|
|
|
{/if}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
{#if !isSelf}
|
|
|
|
|
<progress class="progress w-full" value={progress} max="100"></progress>
|
|
|
|
|
{/if}
|
|
|
|
|
<p class="text-sm opacity-75">{trustMessage}</p>
|
|
|
|
|
</div>
|
2026-07-28 16:16:26 +00:00
|
|
|
{#if $followsWhoFollow.length > 0}
|
2026-06-18 10:52:04 +00:00
|
|
|
<div class="flex flex-col gap-2 border-t border-line pt-4">
|
|
|
|
|
<p class="text-sm font-medium">People who follow {$profileDisplay}</p>
|
2026-07-28 16:16:26 +00:00
|
|
|
<ProfileCircles pubkeys={$followsWhoFollow} limit={5} />
|
2026-06-18 10:52:04 +00:00
|
|
|
<p class="text-sm opacity-75">
|
2026-07-28 16:16:26 +00:00
|
|
|
{$followsWhoFollow.length}
|
|
|
|
|
{$followsWhoFollow.length === 1 ? "person" : "people"} you follow also follow
|
2026-06-18 10:52:04 +00:00
|
|
|
{$profileDisplay}.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|