atmo.rsvp
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 160 lines 3.9 kB view raw
1<script lang="ts"> 2 import { Modal, Button, Avatar } from '@foxui/core'; 3 import { LinkCard } from '@foxui/social'; 4 import PostToBlueskyModal from '$lib/components/PostToBlueskyModal.svelte'; 5 import type { EditorAdapter, EditorViewer } from '$lib/components/editor/adapter'; 6 7 let { 8 open = $bindable(false), 9 url, 10 title = 'Event created!', 11 shareText, 12 eventName, 13 ogImageUrl, 14 canSetEventComments = false, 15 eventDid, 16 eventRkey, 17 eventDescription, 18 adapter, 19 viewer, 20 onPosted 21 }: { 22 open: boolean; 23 url: string; 24 title?: string; 25 shareText?: string; 26 eventName?: string; 27 ogImageUrl?: string; 28 canSetEventComments?: boolean; 29 eventDid?: string; 30 eventRkey?: string; 31 eventDescription?: string; 32 adapter: EditorAdapter; 33 viewer: EditorViewer; 34 onPosted?: (ref: { uri: string; cid: string; showComments: boolean }) => void; 35 } = $props(); 36 37 let copiedUrl = $state(false); 38 let copiedText = $state(false); 39 let showPostModal = $state(false); 40 41 let textBeforeUrl = $derived(shareText ? shareText.replace(url, '').trim() : undefined); 42 43 async function copyUrl() { 44 try { 45 await navigator.clipboard.writeText(url); 46 copiedUrl = true; 47 setTimeout(() => (copiedUrl = false), 2000); 48 } catch {} 49 } 50 51 async function copyText() { 52 if (!shareText) return; 53 try { 54 await navigator.clipboard.writeText(shareText); 55 copiedText = true; 56 setTimeout(() => (copiedText = false), 2000); 57 } catch {} 58 } 59 60 let blueskyButton: HTMLElement | null = $state(null); 61 62 let canPostDirectly = $derived( 63 !!eventDid && !!eventRkey && !!eventName && viewer.isLoggedIn 64 ); 65 66 let blueskyIntentUrl = $derived( 67 `https://bsky.app/intent/compose?text=${encodeURIComponent(shareText || url)}` 68 ); 69 70 function handleBlueskyClick() { 71 showPostModal = true; 72 } 73 74 function handlePostedFromInner(ref: { uri: string; cid: string; showComments: boolean }) { 75 onPosted?.(ref); 76 open = false; 77 } 78</script> 79 80<Modal 81 bind:open 82 onOpenAutoFocus={(e) => { 83 e.preventDefault(); 84 blueskyButton?.focus(); 85 }} 86> 87 <div> 88 <h2 class="text-base-900 dark:text-base-50 mb-2 text-xl font-bold">{title}</h2> 89 <p class="text-base-500 dark:text-base-400 mb-4 text-sm">Share it with others!</p> 90 91 <div 92 class="bg-base-200 dark:bg-base-950/30 border-base-400/40 dark:border-base-700 mb-6 overflow-hidden rounded-xl border px-4 py-3 text-left" 93 > 94 {#if viewer.isLoggedIn} 95 <div class="flex items-center gap-2 pb-4"> 96 <Avatar src={viewer.avatar} alt="" class="size-6" /> 97 <span class="text-base-700 dark:text-base-200 text-sm font-medium" 98 >{viewer.handle ?? viewer.did}</span 99 > 100 </div> 101 {/if} 102 {#if textBeforeUrl} 103 <p class="text-base-700 dark:text-base-200 text-md font-semibold">{textBeforeUrl}</p> 104 {/if} 105 {#if eventName} 106 <LinkCard 107 href={url} 108 meta={{ 109 title: eventName, 110 image: ogImageUrl 111 }} 112 class="mb-1" 113 /> 114 {/if} 115 </div> 116 117 <div class="flex flex-col gap-2 sm:flex-row"> 118 <Button class="flex-1" variant="secondary" onclick={copyUrl}> 119 {copiedUrl ? 'Copied!' : 'Copy link'} 120 </Button> 121 {#if shareText} 122 <Button class="flex-1" variant="secondary" onclick={copyText}> 123 {copiedText ? 'Copied!' : 'Copy text'} 124 </Button> 125 {/if} 126 {#if canPostDirectly} 127 <Button bind:ref={blueskyButton} class="flex-1" onclick={handleBlueskyClick}> 128 Share to Bluesky 129 </Button> 130 {:else} 131 <Button 132 bind:ref={blueskyButton} 133 class="flex-1" 134 href={blueskyIntentUrl} 135 target="_blank" 136 rel="noopener" 137 > 138 Share to Bluesky 139 </Button> 140 {/if} 141 </div> 142 </div> 143</Modal> 144 145{#if canPostDirectly && eventDid && eventRkey && eventName} 146 <PostToBlueskyModal 147 bind:open={showPostModal} 148 {canSetEventComments} 149 {eventDid} 150 {eventRkey} 151 {eventName} 152 eventUrl={url} 153 {eventDescription} 154 {ogImageUrl} 155 initialText={textBeforeUrl ?? eventName} 156 {adapter} 157 {viewer} 158 onPosted={handlePostedFromInner} 159 /> 160{/if}