diff --git a/src/components/AppShelf/AddAppShelfItem.tsx b/src/components/AppShelf/AddAppShelfItem.tsx index c05d30e68..ac3b01c83 100644 --- a/src/components/AppShelf/AddAppShelfItem.tsx +++ b/src/components/AppShelf/AddAppShelfItem.tsx @@ -14,9 +14,10 @@ import { Text, } from '@mantine/core'; import { useForm } from '@mantine/form'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { IconApps as Apps } from '@tabler/icons'; import { v4 as uuidv4 } from 'uuid'; +import { useDebouncedValue } from '@mantine/hooks'; import { useConfig } from '../../tools/state'; import { ServiceTypeList } from '../../tools/types'; @@ -134,6 +135,14 @@ export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } & }, }); + const [debounced, cancel] = useDebouncedValue(form.values.name, 250); + useEffect(() => { + if (form.values.name !== debounced) return; + MatchIcon(form.values.name, form); + MatchService(form.values.name, form); + MatchPort(form.values.name, form); + }, [debounced]); + // Try to set const hostname to new URL(form.values.url).hostname) // If it fails, set it to the form.values.url let hostname = form.values.url; @@ -186,14 +195,7 @@ export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } & required label="Service name" placeholder="Plex" - value={form.values.name} - onChange={(event) => { - form.setFieldValue('name', event.currentTarget.value); - MatchIcon(event.currentTarget.value, form); - MatchService(event.currentTarget.value, form); - MatchPort(event.currentTarget.value, form); - }} - error={form.errors.name && 'Invalid icon url'} + {...form.getInputProps('name')} /> ); const queryUrl = config.settings.searchUrl ?? 'https://www.google.com/search?q='; const textInput = useRef(); - useHotkeys([['ctrl+K', () => textInput.current && textInput.current.focus()]]); + // Find a service with the type of 'Overseerr' + const service = config.services.find((s) => s.type === 'Overseerr'); + const form = useForm({ + initialValues: { + query: '', + }, + }); + + const [debounced, cancel] = useDebouncedValue(form.values.query, 250); + const [data, setData] = useState([]); + useEffect(() => { + if (form.values.query !== debounced || form.values.query === '') return; + setOpened(false); + setOpenedResults(true); + if (service) { + const serviceUrl = new URL(service.url); + axios + .post(`/api/modules/overseerr?query=${form.values.query}`, { + service, + }) + .then((res) => setData(res.data.results ?? [])); + } + }, [debounced]); + useHotkeys([['ctrl+K', () => textInput.current && textInput.current.focus()]]); const { classes, cx } = useStyles(); const rightSection = (
@@ -43,12 +74,6 @@ export default function SearchBar(props: any) {
); - const form = useForm({ - initialValues: { - query: '', - }, - }); - // If enabled modules doesn't contain the module, return null // If module in enabled @@ -57,6 +82,7 @@ export default function SearchBar(props: any) { return null; } + // Data with label as item.name return (
{ @@ -89,30 +115,40 @@ export default function SearchBar(props: any) { })} > setOpened(true)} - onBlurCapture={() => setOpened(false)} + opened={results} target={ - + trapFocus={false} + transition="pop-bottom-right" + onFocusCapture={() => setOpened(true)} + onBlurCapture={() => setOpened(false)} + target={ + + } + > + + tip: Use the prefixes !yt and !t in front of your query to search on + YouTube or for a Torrent respectively. + + } >