🔀 Merge pull request #368 from ajnart/ajnart/issue349

 Search and open services with the search bar
This commit is contained in:
Thomas Camlong
2022-08-25 11:41:08 +02:00
committed by GitHub
2 changed files with 56 additions and 3 deletions

View File

@@ -0,0 +1,18 @@
import { Anchor, Avatar, Group, Text } from '@mantine/core';
interface smallServiceItem {
label: string;
icon?: string;
url?: string;
}
export default function SmallServiceItem(props: any) {
const { service }: { service: smallServiceItem } = props;
// TODO : Use Next/link
return (
<Group>
{service.icon && <Avatar src={service.icon} />}
<Text>{service.label}</Text>
</Group>
);
}

View File

@@ -1,7 +1,7 @@
import { Kbd, createStyles, Autocomplete, Popover, ScrollArea, Divider } from '@mantine/core'; import { Kbd, createStyles, Autocomplete, Popover, ScrollArea, Divider } from '@mantine/core';
import { useClickOutside, useDebouncedValue, useHotkeys } from '@mantine/hooks'; import { useClickOutside, useDebouncedValue, useHotkeys } from '@mantine/hooks';
import { useForm } from '@mantine/form'; import { useForm } from '@mantine/form';
import React, { useEffect, useRef, useState } from 'react'; import React, { forwardRef, useEffect, useRef, useState } from 'react';
import { import {
IconSearch as Search, IconSearch as Search,
IconBrandYoutube as BrandYoutube, IconBrandYoutube as BrandYoutube,
@@ -15,6 +15,7 @@ import { useConfig } from '../../tools/state';
import { IModule } from '../ModuleTypes'; import { IModule } from '../ModuleTypes';
import { OverseerrModule } from '../overseerr'; import { OverseerrModule } from '../overseerr';
import { OverseerrMediaDisplay } from '../common'; import { OverseerrMediaDisplay } from '../common';
import SmallServiceItem from '../../components/AppShelf/SmallServiceItem';
const useStyles = createStyles((theme) => ({ const useStyles = createStyles((theme) => ({
hide: { hide: {
@@ -100,11 +101,36 @@ export default function SearchBar(props: any) {
if (!isModuleEnabled) { if (!isModuleEnabled) {
return null; return null;
} }
// Match all the services that contain the query in their name if the query is not empty
const autocompleteData = results.map((result) => ({ const matchingServices = config.services.filter((service) => {
if (form.values.query === '' || form.values.query === undefined) {
return false;
}
return service.name.toLowerCase().includes(form.values.query.toLowerCase());
});
const autocompleteData = matchingServices.map((service) => ({
label: service.name,
value: service.name,
icon: service.icon,
url: service.openedUrl ?? service.url,
}));
// Append the matching results to the autocomplete data
const autoCompleteResults = results.map((result) => ({
label: result.phrase, label: result.phrase,
value: result.phrase, value: result.phrase,
icon: result.icon,
url: result.url,
})); }));
autocompleteData.push(...autoCompleteResults);
const AutoCompleteItem = forwardRef<HTMLDivElement, any>(
({ label, value, icon, url, ...others }: any, ref) => (
<div ref={ref} {...others}>
<SmallServiceItem service={{ label, value, icon, url }} />
</div>
)
);
return ( return (
<form <form
onChange={() => { onChange={() => {
@@ -163,6 +189,15 @@ export default function SearchBar(props: any) {
onFocusCapture={() => setOpened(true)} onFocusCapture={() => setOpened(true)}
autoFocus autoFocus
variant="filled" variant="filled"
itemComponent={AutoCompleteItem}
onItemSubmit={(item) => {
setOpened(false);
if (item.url) {
results.splice(0, autocompleteData.length);
form.reset();
window.open(item.url);
}
}}
data={autocompleteData} data={autocompleteData}
icon={icon} icon={icon}
ref={textInput} ref={textInput}