/ src / lib / components / FollowButton.svelte
FollowButton.svelte
 1  <script lang="ts">
 2  	import type { MastodonAccount } from '$lib/mastodon';
 3  	import { followAccount, unfollowAccount } from '$lib/mastodon';
 4  	import { friendkit } from '$lib/store.svelte';
 5  	import { Button, Loader } from 'svelte-akui';
 6  	import PermissionModal from './PermissionModal.svelte';
 7  
 8  	let { account }: { account: MastodonAccount } = $props();
 9  
10  	let isProcessing = $state(false);
11  	let showPermissionModal = $state(false);
12  
13  	const isFollowingUser = $derived.by(() => friendkit.following.some((a) => a.id === account.id));
14  
15  	async function handleToggleFollow() {
16  		if (isProcessing) return;
17  		if (!friendkit.accessToken) return;
18  
19  		if (!friendkit.hasWriteAccess) {
20  			showPermissionModal = true;
21  			return;
22  		}
23  
24  		const accountId = account.id;
25  		const accountData = { ...account }; // Capture a snapshot
26  
27  		isProcessing = true;
28  		try {
29  			if (isFollowingUser) {
30  				await unfollowAccount(accountId);
31  				friendkit.following = friendkit.following.filter((a) => a.id !== accountId);
32  			} else {
33  				await followAccount(accountId);
34  				friendkit.following = [...friendkit.following, accountData];
35  			}
36  		} catch (e: unknown) {
37  			alert(e instanceof Error ? e.message : String(e));
38  		} finally {
39  			isProcessing = false;
40  		}
41  	}
42  </script>
43  
44  <div class="fk-follow-button-wrapper">
45  	<Button
46  		variant="regular"
47  		size="small"
48  		onclick={handleToggleFollow}
49  		disabled={isProcessing}
50  		class="fk-follow-button"
51  	>
52  		{#if isProcessing}
53  			<Loader size="small" />
54  		{:else}
55  			{isFollowingUser ? 'Unfollow' : 'Follow'}
56  		{/if}
57  	</Button>
58  </div>
59  
60  {#if showPermissionModal}
61  	<PermissionModal
62  		{account}
63  		actionName={isFollowingUser ? 'unfollowing accounts' : 'following accounts'}
64  		onClose={() => (showPermissionModal = false)}
65  	/>
66  {/if}
67  
68  <style>
69  	.fk-follow-button-wrapper :global(.fk-follow-button) {
70  		width: 6em;
71  		justify-content: center;
72  	}
73  </style>