diff --git a/package.json b/package.json
index b81ca8858..47e1b68cb 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
"@mantine/next": "^5.2.3",
"@mantine/notifications": "^5.7.2",
"@mantine/prism": "^5.0.0",
+ "@mantine/spotlight": "^5.8.2",
"@nivo/core": "^0.79.0",
"@nivo/line": "^0.79.1",
"@tabler/icons": "^1.78.0",
diff --git a/src/modules/index.ts b/src/modules/index.ts
index f3b7292a7..c4e86eadf 100644
--- a/src/modules/index.ts
+++ b/src/modules/index.ts
@@ -8,3 +8,4 @@ export * from './weather';
export * from './docker';
export * from './overseerr';
export * from './usenet';
+export * from './spotlight';
diff --git a/src/modules/spotlight/SpotlightModule.tsx b/src/modules/spotlight/SpotlightModule.tsx
new file mode 100644
index 000000000..c6526257b
--- /dev/null
+++ b/src/modules/spotlight/SpotlightModule.tsx
@@ -0,0 +1,107 @@
+import { Button, Group } from '@mantine/core';
+import { IconSearch, IconBrandYoutube, IconDownload, IconMovie } from '@tabler/icons';
+import { SpotlightProvider, openSpotlight } from '@mantine/spotlight';
+import type { SpotlightAction } from '@mantine/spotlight';
+import { useState } from 'react';
+import { IModule } from '../ModuleTypes';
+
+export const SpotlightModule: IModule = {
+ title: 'Spotlight',
+ icon: IconSearch,
+ component: SpotlightModuleComponent,
+ id: 'spotlight',
+};
+
+interface SearchEngine {
+ name: string;
+ enabled: boolean;
+ description: string;
+ icon: React.ReactNode;
+ url: string;
+ shortcut: string;
+}
+const searchEngines: SearchEngine[] = [
+ {
+ name: 'Google',
+ enabled: true,
+ description: 'Search using your search engine (defined in settings)',
+ icon: ,
+ url: 'https://www.google.com/search?q=',
+ shortcut: 'g',
+ },
+ {
+ name: 'Youtube',
+ enabled: true,
+ description: 'Search Youtube',
+ icon: ,
+ url: 'https://www.youtube.com/results?search_query=',
+ shortcut: 'y',
+ },
+ {
+ name: 'Download',
+ enabled: true,
+ description: 'Search for torrents',
+ icon: ,
+ url: 'https://1337x.to/search/',
+ shortcut: 't',
+ },
+ {
+ name: 'Movies',
+ icon: ,
+ enabled: false,
+ description: 'Search for movies using Overseerr',
+ url: 'https://www.imdb.com/find?q=',
+ shortcut: 'm',
+ },
+];
+
+function SpotlightControl() {
+ return (
+
+
+
+ );
+}
+
+export function SpotlightModuleComponent(props: any) {
+ const [selectedSearchEngine, setSearchEngine] = useState(searchEngines[0]);
+ const actions: SpotlightAction[] = searchEngines.map((engine) => ({
+ title: engine.name,
+ description: engine.description,
+ icon: engine.icon,
+ onTrigger: () => {
+ setSearchEngine(engine);
+ },
+ closeOnTrigger: false,
+ }));
+ return (
+
+ useSearchBrowser(researchString, selectedSearchEngine, setSearchEngine, searchEngines)
+ }
+ >
+
+
+ );
+}
+function useSearchBrowser(
+ search: string,
+ selectedSearchEngine: SearchEngine,
+ setSearchEngine: React.Dispatch>,
+ searchEngines: SearchEngine[]
+): void {
+ // First check if the value of search contains any shortcut
+ const foundSearchEngine = searchEngines.find((engine) => search.includes(`!${engine.shortcut}`));
+ if (foundSearchEngine) {
+ // If a shortcut is found, use it
+ setSearchEngine(foundSearchEngine);
+ search.replace(`!${foundSearchEngine.shortcut}`, '');
+ } else {
+ // If no shortcut is found, do nothing (for now)
+ }
+}
diff --git a/src/modules/spotlight/index.tsx b/src/modules/spotlight/index.tsx
new file mode 100644
index 000000000..27e68ef6c
--- /dev/null
+++ b/src/modules/spotlight/index.tsx
@@ -0,0 +1 @@
+export { SpotlightModule } from './SpotlightModule';
diff --git a/yarn.lock b/yarn.lock
index 87dd94f19..d04d88e82 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1231,6 +1231,20 @@ __metadata:
languageName: node
linkType: hard
+"@mantine/spotlight@npm:^5.8.2":
+ version: 5.8.2
+ resolution: "@mantine/spotlight@npm:5.8.2"
+ dependencies:
+ "@mantine/utils": 5.8.2
+ peerDependencies:
+ "@mantine/core": 5.8.2
+ "@mantine/hooks": 5.8.2
+ react: ">=16.8.0"
+ react-dom: ">=16.8.0"
+ checksum: 162eec73807649015d56359c8cdd565447b7ace86fd66705047657320be73e52e27119dc5f3b3e85367f316181b8cf9afeb18f9993cf396718fa20b5d1edccc1
+ languageName: node
+ linkType: hard
+
"@mantine/ssr@npm:5.2.3":
version: 5.2.3
resolution: "@mantine/ssr@npm:5.2.3"
@@ -1301,6 +1315,15 @@ __metadata:
languageName: node
linkType: hard
+"@mantine/utils@npm:5.8.2":
+ version: 5.8.2
+ resolution: "@mantine/utils@npm:5.8.2"
+ peerDependencies:
+ react: ">=16.8.0"
+ checksum: bb6b1de7e8bee92751410e634e7e475ea38eef4d822ee955aa885a739c4379c8d8cbdc12aee570b6c1dcf83ae1202297f1f1c3d78b11de3e3ffe64076edd3a71
+ languageName: node
+ linkType: hard
+
"@motionone/animation@npm:^10.12.0":
version: 10.13.1
resolution: "@motionone/animation@npm:10.13.1"
@@ -4835,6 +4858,7 @@ __metadata:
"@mantine/next": ^5.2.3
"@mantine/notifications": ^5.7.2
"@mantine/prism": ^5.0.0
+ "@mantine/spotlight": ^5.8.2
"@next/bundle-analyzer": ^12.1.4
"@next/eslint-plugin-next": ^12.1.4
"@nivo/core": ^0.79.0