Track your online rabbitholes!

feat: filter rabbithole with a search query

authored by Govind Mohan and committed by Govind Mohan 7d275e5f e20997ab

Changed files
+44 -3
src
+1
package.json
··· 25 25 }, 26 26 "dependencies": { 27 27 "@svelteuidev/core": "^0.15.3", 28 + "fuse.js": "^7.0.0", 28 29 "radix-icons-svelte": "^1.2.1", 29 30 "uuid": "^9.0.0" 30 31 }
+43 -3
src/lib/Timeline.svelte
··· 1 1 <script> 2 + import Fuse from "fuse.js"; 2 3 import { onMount, createEventDispatcher } from "svelte"; 3 4 import { Badge, Button, Card, Group, Image, Input, Text, TextInput, Tooltip } from '@svelteuidev/core'; 4 5 import { MessageRequest } from "../utils" ··· 11 12 export let activeProject = {}; 12 13 export let websites = []; 13 14 15 + let searchResults = []; 14 16 let nameClicked = false; 15 17 let isHovering = false; 18 + let searchQuery = ""; 16 19 17 20 async function renameProject() { 18 21 if (activeProject.name === "") { ··· 38 41 url: event.detail.url 39 42 }); 40 43 } 44 + 45 + function checkWebsiteForQuery(websites) { 46 + const fuse = new Fuse(websites, { 47 + keys: ["name", "description", "url"], 48 + includeScore: true, 49 + // anything more has too many irrelevant results 50 + threshold: 0.3, 51 + }); 52 + 53 + const results = fuse.search(searchQuery); 54 + // const filteredResults = results.map((result) => result.item).filter((item, index, self) => self.indexOf(item) === index); 55 + return results; 56 + } 57 + 58 + function applySearchQuery(node) { 59 + const results = checkWebsiteForQuery(websites); 60 + searchResults = results.map(res => res.item); 61 + } 41 62 </script> 42 63 43 64 <div class="timeline"> ··· 69 90 {/if} 70 91 </Group> 71 92 <div class="feed"> 72 - {#each websites as site} 73 - <TimelineCard website={site} on:websiteDelete={deleteWebsite} /> 74 - {/each} 93 + <div class="search-bar"> 94 + <TextInput 95 + placeholder="Search" 96 + bind:value={searchQuery} 97 + on:input={applySearchQuery} 98 + /> 99 + </div> 100 + <!-- Following deadgrep's convention of 3 char minimum --> 101 + {#if searchQuery.length < 3} 102 + {#each websites as site} 103 + <TimelineCard website={site} on:websiteDelete={deleteWebsite} /> 104 + {/each} 105 + {:else} 106 + {#each searchResults as site} 107 + <TimelineCard website={site} on:websiteDelete={deleteWebsite} /> 108 + {/each} 109 + {/if} 75 110 </div> 76 111 </div> 77 112 ··· 94 129 .logo { 95 130 width: 150px; 96 131 height: auto; 132 + } 133 + 134 + .search-bar { 135 + width: inherit; 136 + margin-x: 20px 97 137 } 98 138 </style>