your personal website on atproto - mirror
blento.app
1<script lang="ts">
2 import { Alert, Button, Input, Subheading } from '@foxui/core';
3 import Modal from '$lib/components/modal/Modal.svelte';
4 import type { CreationModalComponentProps } from '../../types';
5 import { parseBlueskyPostUrl } from './utils';
6
7 let { item = $bindable(), oncreate, oncancel }: CreationModalComponentProps = $props();
8
9 let isValidating = $state(false);
10 let errorMessage = $state('');
11 let postUrl = $state('');
12
13 async function validateAndCreate() {
14 errorMessage = '';
15 isValidating = true;
16
17 try {
18 const parsed = parseBlueskyPostUrl(postUrl.trim());
19
20 if (!parsed) {
21 throw new Error('Invalid URL format');
22 }
23
24 // Construct AT URI using handle (will be resolved to DID when loading)
25 item.cardData.uri = `at://${parsed.handle}/app.bsky.feed.post/${parsed.rkey}`;
26 item.cardData.href = postUrl.trim();
27
28 return true;
29 } catch (err) {
30 errorMessage =
31 err instanceof Error && err.message === 'Post not found'
32 ? "Couldn't find that post. Please check the URL and try again."
33 : err instanceof Error && err.message === 'Could not resolve handle'
34 ? "Couldn't find that user. Please check the URL and try again."
35 : 'Invalid URL. Please enter a valid Bluesky post URL (e.g., https://bsky.app/profile/handle/post/rkey).';
36 return false;
37 } finally {
38 isValidating = false;
39 }
40 }
41</script>
42
43<Modal open={true} closeButton={false}>
44 <form
45 onsubmit={async () => {
46 if (await validateAndCreate()) oncreate();
47 }}
48 class="flex flex-col gap-2"
49 >
50 <Subheading>Enter a Bluesky post URL</Subheading>
51 <Input
52 bind:value={postUrl}
53 placeholder="https://bsky.app/profile/handle/post/..."
54 class="mt-4"
55 />
56
57 {#if errorMessage}
58 <Alert type="error" title="Failed to create post card"><span>{errorMessage}</span></Alert>
59 {/if}
60
61 <p class="text-base-500 dark:text-base-400 mt-2 text-xs">
62 Paste a URL from <a
63 href="https://bsky.app"
64 class="text-accent-800 dark:text-accent-300"
65 target="_blank">bsky.app</a
66 > to embed a Bluesky post.
67 </p>
68
69 <div class="mt-4 flex justify-end gap-2">
70 <Button onclick={oncancel} variant="ghost">Cancel</Button>
71 <Button type="submit" disabled={isValidating || !postUrl.trim()}
72 >{isValidating ? 'Creating...' : 'Create'}</Button
73 >
74 </div>
75 </form>
76</Modal>