mirror of
https://git.shipoclu.com/moon/plspace.git
synced 2026-08-13 02:42:30 +00:00
initial commit
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
<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 { session } from '$lib/stores/session.svelte'
|
||||
import { blockAccount, followAccount, unblockAccount, unfollowAccount } from '$lib/api/endpoints'
|
||||
import { displayNameOf } from '$lib/util/profile'
|
||||
import Module from '../common/Module.svelte'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
relationship: Relationship | null
|
||||
onrelationship?: (relationship: Relationship) => void
|
||||
}
|
||||
|
||||
let { account, relationship, onrelationship }: Props = $props()
|
||||
|
||||
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(() => unblockAccount(session.api, account.id))
|
||||
} else if (following || requested) {
|
||||
void run(() => unfollowAccount(session.api, account.id))
|
||||
} else {
|
||||
void run(() => followAccount(session.api, account.id))
|
||||
}
|
||||
}
|
||||
|
||||
function toggleBlock(): void {
|
||||
void run(() =>
|
||||
blocking ? unblockAccount(session.api, account.id) : blockAccount(session.api, account.id),
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<Module title={`Contacting ${firstName}`}>
|
||||
{#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">{firstName} has you on their friends list.</p>
|
||||
{/if}
|
||||
</Module>
|
||||
Reference in New Issue
Block a user