appview-less bluesky client
24
fork

Configure Feed

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

at main 79 lines 2.6 kB view raw
1<script lang="ts"> 2 import { parseToRichText } from '$lib/richtext'; 3 import { settings } from '$lib/settings'; 4 import { router } from '$lib/state.svelte'; 5 import type { BakedRichtext } from '@atcute/bluesky-richtext-builder'; 6 import { segmentize, type Facet, type RichtextSegment } from '@atcute/bluesky-richtext-segmenter'; 7 8 interface Props { 9 text: string; 10 facets?: Facet[]; 11 } 12 13 const { text, facets }: Props = $props(); 14 15 const richtext: Promise<BakedRichtext> = $derived( 16 facets ? Promise.resolve({ text, facets }) : parseToRichText(text) 17 ); 18 19 const handleProfileClick = (e: MouseEvent, did: string) => { 20 e.preventDefault(); 21 router.navigate(`/profile/${did}`); 22 }; 23</script> 24 25{#snippet plainText(text: string)} 26 {#each text.split(/(\s)/) as line, idx (idx)} 27 {#if line === '\n'} 28 <br /> 29 {:else} 30 {line} 31 {/if} 32 {/each} 33{/snippet} 34 35{#snippet segments(segments: RichtextSegment[])} 36 {#each segments as segment, idx (idx)} 37 {@const { text, features: _features } = segment} 38 {@const features = _features ?? []} 39 {#if features.length > 0} 40 <!-- eslint-disable svelte/no-navigation-without-resolve --> 41 {#each features as feature, idx (idx)} 42 {#if feature.$type === 'app.bsky.richtext.facet#mention'} 43 <a 44 class="text-(--nucleus-accent2) hover:cursor-pointer hover:underline" 45 href={`/profile/${feature.did}`} 46 onclick={(e) => handleProfileClick(e, feature.did)}>{@render plainText(text)}</a 47 > 48 {:else if feature.$type === 'app.bsky.richtext.facet#link'} 49 {@const uri = new URL(feature.uri)} 50 {@const text = `${!uri.protocol.startsWith('http') ? `${uri.protocol}//` : ''}${uri.host}${uri.hash.length === 0 && uri.search.length === 0 && uri.pathname === '/' ? '' : uri.pathname}${uri.search}${uri.hash}`} 51 <a 52 class="text-(--nucleus-accent2)" 53 href={uri.href} 54 target="_blank" 55 rel="noopener noreferrer" 56 >{@render plainText(`${text.substring(0, 40)}${text.length > 40 ? '...' : ''}`)}</a 57 > 58 {:else if feature.$type === 'app.bsky.richtext.facet#tag'} 59 <a 60 class="text-(--nucleus-accent2)" 61 href={`${$settings.socialAppUrl}/search?q=${encodeURIComponent('#' + feature.tag)}`} 62 target="_blank" 63 rel="noopener noreferrer">{@render plainText(text)}</a 64 > 65 {:else} 66 <span>{@render plainText(text)}</span> 67 {/if} 68 {/each} 69 {:else} 70 <span>{@render plainText(text)}</span> 71 {/if} 72 {/each} 73{/snippet} 74 75{#await richtext} 76 {@render plainText(text)} 77{:then richtext} 78 {@render segments(segmentize(richtext.text, richtext.facets))} 79{/await}