diff --git a/src/components/nostr/ChatComponent.vue b/src/components/nostr/ChatComponent.vue index 5fa8a05..9f64e02 100644 --- a/src/components/nostr/ChatComponent.vue +++ b/src/components/nostr/ChatComponent.vue @@ -23,12 +23,47 @@
-

Peers ({{ peers.length }})

+
+

Peers ({{ filteredPeers.length }})

+ + {{ resultCount }} found + +
+ +
+
+ +
+ +
+ +
+
+ +
+ +

No peers found matching "{{ searchQuery }}"

+

Try searching by username or pubkey

+
+ +
-

{{ message.content }}

+

{{ message.content }}

{{ formatTime(message.created_at) }}

@@ -119,7 +154,7 @@ -
+
- +
@@ -159,12 +194,47 @@
-

Peers ({{ peers.length }})

+
+

Peers ({{ filteredPeers.length }})

+ + {{ resultCount }} found + +
+ +
+
+ +
+ +
+ +
+
+ +
+ +

No peers found matching "{{ searchQuery }}"

+

Try searching by username or pubkey

+
+ +
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue' -import { Send, RefreshCw, MessageSquare, ArrowLeft } from 'lucide-vue-next' +import { Send, RefreshCw, MessageSquare, ArrowLeft, Search, X } from 'lucide-vue-next' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { ScrollArea } from '@/components/ui/scroll-area' import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar' import { useNostrChat } from '@/composables/useNostrChat' +import { useFuzzySearch } from '@/composables/useFuzzySearch' import { getAuthToken } from '@/lib/config/lnbits' import { config } from '@/lib/config' @@ -290,8 +361,6 @@ interface Peer { pubkey: string } - - // State const peers = ref([]) const selectedPeer = ref(null) @@ -306,6 +375,36 @@ const scrollTarget = ref(null) // Mobile detection const isMobile = ref(false) +// Fuzzy search for peers +// This integrates the useFuzzySearch composable to provide intelligent search functionality +// for finding peers by username or pubkey with typo tolerance and scoring +const { + searchQuery, + filteredItems: filteredPeers, + isSearching, + resultCount, + clearSearch +} = useFuzzySearch(peers, { + fuseOptions: { + keys: [ + { name: 'username', weight: 0.7 }, // Username has higher weight for better UX + { name: 'pubkey', weight: 0.3 } // Pubkey has lower weight but still searchable + ], + threshold: 0.3, // Fuzzy matching threshold (0.0 = perfect, 1.0 = match anything) + distance: 100, // Maximum distance for fuzzy matching + ignoreLocation: true, // Ignore location for better performance + useExtendedSearch: false, // Don't use extended search syntax + minMatchCharLength: 1, // Minimum characters to match + shouldSort: true, // Sort results by relevance + findAllMatches: false, // Don't find all matches for performance + location: 0, // Start search from beginning + isCaseSensitive: false, // Case insensitive search + }, + resultLimit: 50, // Limit results for performance + matchAllWhenSearchEmpty: true, // Show all peers when search is empty + minSearchLength: 1, // Start searching after 1 character +}) + // Check if device is mobile const checkMobile = () => { isMobile.value = window.innerWidth < 768 // md breakpoint