mirror of
https://git.shipoclu.com/moon/plspace.git
synced 2026-08-13 02:42:30 +00:00
146 lines
4.7 KiB
Svelte
146 lines
4.7 KiB
Svelte
<script lang="ts">
|
||
/**
|
||
* "Contacting Tom" — the two-column action list.
|
||
*
|
||
* Follow state comes from `/api/v1/accounts/relationships`, which is only
|
||
* available when signed in; logged out, the actions become sign-in prompts
|
||
* rather than disappearing, so the box keeps its shape.
|
||
*/
|
||
import type { Account, Relationship } from '$lib/api/types'
|
||
import { useAppServices } from '$lib/app-services'
|
||
import { displayNameOf } from '$lib/util/profile'
|
||
import Module from '../common/Module.svelte'
|
||
import EmojiText from '../common/EmojiText.svelte'
|
||
|
||
interface Props {
|
||
account: Account
|
||
relationship: Relationship | null
|
||
onrelationship?: (relationship: Relationship) => void
|
||
}
|
||
|
||
let { account, relationship, onrelationship }: Props = $props()
|
||
|
||
const { endpoints, session } = useAppServices()
|
||
let busy = $state(false)
|
||
let error = $state<string | null>(null)
|
||
|
||
const firstName = $derived(displayNameOf(account).split(/\s+/)[0])
|
||
const isSelf = $derived(session.me?.id === account.id)
|
||
const following = $derived(relationship?.following ?? false)
|
||
const requested = $derived(relationship?.requested ?? false)
|
||
const blocking = $derived(relationship?.blocking ?? false)
|
||
|
||
const followLabel = $derived(
|
||
blocking
|
||
? 'Unblock User'
|
||
: following
|
||
? 'Remove from Friends'
|
||
: requested
|
||
? 'Cancel Friend Request'
|
||
: account.locked
|
||
? 'Request to Add'
|
||
: 'Add to Friends',
|
||
)
|
||
|
||
async function run(action: () => Promise<Relationship>): Promise<void> {
|
||
if (busy) return
|
||
busy = true
|
||
error = null
|
||
try {
|
||
onrelationship?.(await action())
|
||
} catch (cause) {
|
||
error = cause instanceof Error ? cause.message : 'That didn’t work.'
|
||
} finally {
|
||
busy = false
|
||
}
|
||
}
|
||
|
||
function toggleFollow(): void {
|
||
if (blocking) {
|
||
void run(() => endpoints.unblockAccount(session.api, account.id))
|
||
} else if (following || requested) {
|
||
void run(() => endpoints.unfollowAccount(session.api, account.id))
|
||
} else {
|
||
void run(() => endpoints.followAccount(session.api, account.id))
|
||
}
|
||
}
|
||
|
||
function toggleBlock(): void {
|
||
void run(() =>
|
||
blocking
|
||
? endpoints.unblockAccount(session.api, account.id)
|
||
: endpoints.blockAccount(session.api, account.id),
|
||
)
|
||
}
|
||
</script>
|
||
|
||
<Module title={`Contacting ${firstName}`} titleEmojis={account.emojis}>
|
||
{#if error}
|
||
<p class="error-note" role="alert">{error}</p>
|
||
{/if}
|
||
|
||
<ul class="action-list">
|
||
<li class="action-list-item">
|
||
<span class="action-list-icon" aria-hidden="true">✉</span>
|
||
{#if session.signedIn}
|
||
<a class="action-list-label" href={`#/compose?to=${encodeURIComponent(account.acct)}`}>Send Message</a>
|
||
{:else}
|
||
<a class="action-list-label" href="#/login">Send Message</a>
|
||
{/if}
|
||
</li>
|
||
|
||
<li class="action-list-item">
|
||
<span class="action-list-icon" aria-hidden="true">👤</span>
|
||
{#if isSelf}
|
||
<span class="action-list-label muted">This is you</span>
|
||
{:else if session.signedIn}
|
||
<button
|
||
type="button"
|
||
class="link-button action-list-label"
|
||
disabled={busy}
|
||
aria-pressed={following ? 'true' : 'false'}
|
||
onclick={toggleFollow}
|
||
>
|
||
{followLabel}
|
||
</button>
|
||
{:else}
|
||
<a class="action-list-label" href="#/login">Add to Friends</a>
|
||
{/if}
|
||
</li>
|
||
|
||
<li class="action-list-item">
|
||
<span class="action-list-icon" aria-hidden="true">★</span>
|
||
<a class="action-list-label" href={account.url} target="_blank" rel="noopener noreferrer">
|
||
View on {account.acct.includes('@') ? account.acct.split('@')[1] : session.host}
|
||
</a>
|
||
</li>
|
||
|
||
<li class="action-list-item">
|
||
<span class="action-list-icon" aria-hidden="true">➦</span>
|
||
<a class="action-list-label" href={`#/@${account.acct}/friends`}>Forward to Friend</a>
|
||
</li>
|
||
|
||
<li class="action-list-item">
|
||
<span class="action-list-icon" aria-hidden="true">💬</span>
|
||
<a class="action-list-label" href={`#/@${account.acct}/blog`}>Instant Message</a>
|
||
</li>
|
||
|
||
<li class="action-list-item">
|
||
<span class="action-list-icon" aria-hidden="true">⛔</span>
|
||
{#if isSelf || !session.signedIn}
|
||
<span class="action-list-label muted">Block User</span>
|
||
{:else}
|
||
<button type="button" class="link-button action-list-label" disabled={busy} onclick={toggleBlock}>
|
||
{blocking ? 'Unblock User' : 'Block User'}
|
||
</button>
|
||
{/if}
|
||
</li>
|
||
</ul>
|
||
|
||
{#if relationship?.followed_by && !isSelf}
|
||
<p class="contact-note muted">
|
||
<EmojiText text={firstName} emojis={account.emojis} /> has you on their friends list.
|
||
</p>
|
||
{/if}
|
||
</Module>
|