Thread viewer for Bluesky
at master 87 lines 1.8 kB view raw
1<script lang="ts"> 2 import { getBaseLocation, linkToHashtagPage, linkToPostById, parseBlueskyPostURL } from '../router.js'; 3 4 let query = $state(''); 5 let searchField: HTMLInputElement; 6 7 $effect(() => { 8 searchField.focus(); 9 }); 10 11 function onsubmit(e: Event) { 12 e.preventDefault(); 13 14 let q = query.trim(); 15 16 if (!q) { 17 return; 18 } 19 20 if (q.startsWith('at://')) { 21 let target = new URL(getBaseLocation()); 22 target.searchParams.set('q', q); 23 location.assign(target.toString()); 24 25 } else if (q.match(/^#?((\p{Letter}|\p{Number})+)$/u)) { 26 let hashtag = q.replace(/^#/, ''); 27 location.assign(linkToHashtagPage(hashtag)); 28 29 } else { 30 try { 31 let { user, post } = parseBlueskyPostURL(q); 32 location.assign(linkToPostById(user, post)); 33 } catch (error) { 34 console.log(error); 35 alert(error.message || "This is not a valid URL or hashtag"); 36 } 37 } 38 } 39</script> 40 41<div id="search"> 42 <form method="get" {onsubmit}> 43 🌤 <input type="text" placeholder="Paste a thread link or type a #hashtag" bind:value={query} bind:this={searchField}> 44 </form> 45</div> 46 47<style> 48 #search { 49 position: fixed; 50 top: 0; 51 bottom: 0; 52 left: 0; 53 right: 0; 54 display: flex; 55 align-items: center; 56 justify-content: center; 57 padding-bottom: 5%; 58 } 59 60 form { 61 border: 2px solid hsl(210, 100%, 80%); 62 border-radius: 10px; 63 padding: 15px 20px; 64 margin-left: 50px; 65 } 66 67 input { 68 font-size: 16pt; 69 width: 600px; 70 border: 0; 71 margin-left: 8px; 72 } 73 74 input:focus { 75 outline: none; 76 } 77 78 @media (prefers-color-scheme: dark) { 79 form { 80 border-color: hsl(210, 40%, 60%); 81 } 82 83 form input { 84 background-color: transparent; 85 } 86 } 87</style>