1<script lang="ts">
2 import type { AtpClient } from '$lib/at/client';
3 import { ok, err, type Result } from '$lib/result';
4 import type { ComAtprotoRepoCreateRecord } from '@atcute/atproto';
5 import type { AppBskyFeedPost } from '@atcute/bluesky';
6 import type { InferOutput } from '@atcute/lexicons';
7 import { theme } from '$lib/theme.svelte';
8
9 interface Props {
10 client: AtpClient;
11 }
12
13 const { client }: Props = $props();
14
15 const post = async (
16 text: string
17 ): Promise<
18 Result<InferOutput<(typeof ComAtprotoRepoCreateRecord.mainSchema)['output']['schema']>, string>
19 > => {
20 const record: AppBskyFeedPost.Main = {
21 $type: 'app.bsky.feed.post',
22 text,
23 createdAt: new Date().toISOString()
24 };
25
26 const res = await client.atcute?.post('com.atproto.repo.createRecord', {
27 input: {
28 collection: 'app.bsky.feed.post',
29 repo: client.didDoc!.did,
30 record
31 }
32 });
33
34 if (!res) {
35 return err('failed to post: not logged in');
36 }
37
38 if (!res.ok) {
39 return err(`failed to post: ${res.data.error}: ${res.data.message ?? 'no details'}`);
40 }
41
42 return ok(res.data);
43 };
44
45 let postText = $state('');
46 let info = $state('');
47</script>
48
49<div
50 class="flex min-h-16 max-w-full items-center rounded-xl border-2 px-1 shadow-lg backdrop-blur-sm"
51 style="background: {theme.accent}18; border-color: {theme.accent}66;"
52>
53 <div class="w-full p-1">
54 {#if info.length > 0}
55 <div
56 class="rounded-lg px-3 py-1.5 text-center font-medium text-nowrap overflow-ellipsis"
57 style="background: {theme.accent}22; color: {theme.accent};"
58 >
59 {info}
60 </div>
61 {:else}
62 <div class="flex gap-2">
63 <input
64 bind:value={postText}
65 type="text"
66 placeholder="what's on your mind?"
67 class="placeholder-opacity-50 flex-1 rounded-lg border-2 px-3 py-2 text-sm font-medium transition-all focus:scale-[1.01] focus:shadow-lg focus:outline-none"
68 style="background: {theme.bg}66; border-color: {theme.accent}44; color: {theme.fg};"
69 />
70 <button
71 onclick={() => {
72 post(postText).then((res) => {
73 if (res.ok) {
74 postText = '';
75 info = 'posted! aaaaaaaaaasdf asdlfkasl;df kjasdfjalsdkfjaskd fajksdhf';
76 setTimeout(() => (info = ''), 1000 * 3);
77 } else {
78 info = res.error;
79 }
80 });
81 }}
82 class="rounded-lg border-none px-5 py-2 text-sm font-bold transition-all hover:scale-105 hover:shadow-xl"
83 style="background: linear-gradient(120deg, {theme.accent}c0, {theme.accent2}c0); color: {theme.fg}f0;"
84 >
85 post
86 </button>
87 </div>
88 {/if}
89 </div>
90</div>