Merge pull request #1230 from homarr-labs/feat/ph-capture-missing-icons

This commit is contained in:
Thomas Camlong 2025-04-22 15:29:05 +02:00 committed by GitHub
commit eedb2aff2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 24 additions and 8 deletions

View File

@ -37,11 +37,20 @@ export function IconSearch({ icons }: IconSearchProps) {
const router = useRouter() const router = useRouter()
const pathname = usePathname() const pathname = usePathname()
const [searchQuery, setSearchQuery] = useState(initialQuery ?? "") const [searchQuery, setSearchQuery] = useState(initialQuery ?? "")
const [debouncedQuery, setDebouncedQuery] = useState(initialQuery ?? "")
const [selectedCategories, setSelectedCategories] = useState<string[]>(initialCategories ?? []) const [selectedCategories, setSelectedCategories] = useState<string[]>(initialCategories ?? [])
const [sortOption, setSortOption] = useState<SortOption>(initialSort) const [sortOption, setSortOption] = useState<SortOption>(initialSort)
const timeoutRef = useRef<NodeJS.Timeout | null>(null) const timeoutRef = useRef<NodeJS.Timeout | null>(null)
const { resolvedTheme } = useTheme() const { resolvedTheme } = useTheme()
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedQuery(searchQuery)
}, 200)
return () => clearTimeout(timer)
}, [searchQuery])
// Extract all unique categories // Extract all unique categories
const allCategories = useMemo(() => { const allCategories = useMemo(() => {
const categories = new Set<string>() const categories = new Set<string>()
@ -66,11 +75,17 @@ export function IconSearch({ icons }: IconSearchProps) {
// Then filter by search query // Then filter by search query
if (query.trim()) { if (query.trim()) {
const q = query.toLowerCase() // Normalization function: lowercase, remove spaces and hyphens
const normalizeString = (str: string) => str.toLowerCase().replace(/[-\s]/g, '')
const normalizedQuery = normalizeString(query)
filtered = filtered.filter(({ name, data }) => { filtered = filtered.filter(({ name, data }) => {
if (name.toLowerCase().includes(q)) return true // Check normalized name
if (data.aliases.some((alias) => alias.toLowerCase().includes(q))) return true if (normalizeString(name).includes(normalizedQuery)) return true
if (data.categories.some((category) => category.toLowerCase().includes(q))) return true // Check normalized aliases
if (data.aliases.some((alias) => normalizeString(alias).includes(normalizedQuery))) return true
// Check normalized categories
if (data.categories.some((category) => normalizeString(category).includes(normalizedQuery))) return true
return false return false
}) })
} }
@ -89,6 +104,7 @@ export function IconSearch({ icons }: IconSearchProps) {
} }
// Default sort (relevance or fallback to alphabetical) // Default sort (relevance or fallback to alphabetical)
// TODO: Implement actual relevance sorting
return filtered.sort((a, b) => a.name.localeCompare(b.name)) return filtered.sort((a, b) => a.name.localeCompare(b.name))
}, },
[icons], [icons],
@ -114,10 +130,10 @@ export function IconSearch({ icons }: IconSearchProps) {
return matches return matches
}, [icons, searchQuery]) }, [icons, searchQuery])
// Use useMemo for filtered icons // Use useMemo for filtered icons with debounced query
const filteredIcons = useMemo(() => { const filteredIcons = useMemo(() => {
return filterIcons(searchQuery, selectedCategories, sortOption) return filterIcons(debouncedQuery, selectedCategories, sortOption)
}, [filterIcons, searchQuery, selectedCategories, sortOption]) }, [filterIcons, debouncedQuery, selectedCategories, sortOption])
const updateResults = useCallback( const updateResults = useCallback(
(query: string, categories: string[], sort: SortOption) => { (query: string, categories: string[], sort: SortOption) => {

View File

@ -7,7 +7,7 @@ import { Suspense, useEffect } from "react"
export function PostHogProvider({ children }: { children: React.ReactNode }) { export function PostHogProvider({ children }: { children: React.ReactNode }) {
useEffect(() => { useEffect(() => {
if (process.env.NODE_ENV === "development" || process.env.DISABLE_POSTHOG === "true") return if (process.env.DISABLE_POSTHOG === "true") return
// biome-ignore lint/style/noNonNullAssertion: The NEXT_PUBLIC_POSTHOG_KEY environment variable is guaranteed to be set in production. // biome-ignore lint/style/noNonNullAssertion: The NEXT_PUBLIC_POSTHOG_KEY environment variable is guaranteed to be set in production.
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
ui_host: "https://eu.posthog.com", ui_host: "https://eu.posthog.com",