mirror of
https://git.shipoclu.com/moon/plspace.git
synced 2026-08-13 02:42:30 +00:00
87 lines
2.7 KiB
Svelte
87 lines
2.7 KiB
Svelte
<script lang="ts">
|
|
/**
|
|
* "Tom's Friend Space" — the grid of tiny avatars with names above them.
|
|
*
|
|
* Mastodon lets an account hide its follower/following lists, and remote
|
|
* accounts often return an empty list rather than an error, so the count and
|
|
* the grid are allowed to disagree; the count is authoritative.
|
|
*/
|
|
import type { Account, CustomEmoji } from '$lib/api/types'
|
|
import { displayNameOf, formatCount, profilePath } from '$lib/util/profile'
|
|
import Module from '../common/Module.svelte'
|
|
import Avatar from '../common/Avatar.svelte'
|
|
import EmojiText from '../common/EmojiText.svelte'
|
|
|
|
interface Props {
|
|
title: string
|
|
/** The subject, used in "Tom has 527 friends." */
|
|
ownerName: string
|
|
ownerEmojis?: CustomEmoji[]
|
|
friends: Account[]
|
|
total: number
|
|
viewAllHref: string
|
|
loading?: boolean
|
|
/** The list is withheld by the account's privacy settings. */
|
|
hidden?: boolean
|
|
/** The count is withheld too, so `total` is not meaningful. */
|
|
countHidden?: boolean
|
|
compact?: boolean
|
|
}
|
|
|
|
let {
|
|
title,
|
|
ownerName,
|
|
ownerEmojis,
|
|
friends,
|
|
total,
|
|
viewAllHref,
|
|
loading = false,
|
|
hidden = false,
|
|
countHidden = false,
|
|
compact = false,
|
|
}: Props = $props()
|
|
</script>
|
|
|
|
<Module {title} titleEmojis={ownerEmojis} variant="band">
|
|
{#snippet action()}
|
|
<a href={viewAllHref}>[view all]</a>
|
|
{/snippet}
|
|
|
|
<!-- Never render a withheld count as "0 friends" — that reports a privacy
|
|
setting as a fact about the person. -->
|
|
{#if countHidden}
|
|
<p class="friend-count">
|
|
<EmojiText text={ownerName} emojis={ownerEmojis} /> keeps their friend count private.
|
|
</p>
|
|
{:else}
|
|
<p class="friend-count">
|
|
<EmojiText text={ownerName} emojis={ownerEmojis} /> has
|
|
<span class="friend-count-value">{formatCount(total)}</span>
|
|
friend{total === 1 ? '' : 's'}.
|
|
</p>
|
|
{/if}
|
|
|
|
{#if hidden}
|
|
<p class="empty-note">This friends list is private.</p>
|
|
{:else if loading && friends.length === 0}
|
|
<p class="loading-note">Loading friends…</p>
|
|
{:else if friends.length === 0}
|
|
<p class="empty-note">No friends to show yet.</p>
|
|
{:else}
|
|
<ul class="friend-grid" class:friend-grid--compact={compact}>
|
|
{#each friends as friend (friend.id)}
|
|
<li class="friend-card" data-account={friend.acct}>
|
|
<a class="friend-card-link" href={profilePath(friend)}>
|
|
<EmojiText
|
|
class="friend-card-name"
|
|
text={displayNameOf(friend)}
|
|
emojis={friend.emojis}
|
|
/>
|
|
<Avatar account={friend} plain size="friend" class="friend-card-photo" />
|
|
</a>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
{/if}
|
|
</Module>
|