From 48170fe8996ac4d346904562ed6491ec440cb570 Mon Sep 17 00:00:00 2001 From: vycdev Date: Sat, 1 Jun 2024 07:24:42 +0300 Subject: [PATCH] Enhancement: separate Internet search settings for quicklaunch (#3541) --------- Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com> --- docs/configs/settings.md | 16 +++++++-- src/components/quicklaunch.jsx | 63 +++++++++++++++++++++------------- src/pages/index.jsx | 16 --------- 3 files changed, 53 insertions(+), 42 deletions(-) diff --git a/docs/configs/settings.md b/docs/configs/settings.md index ea5db734eaf..2f387a65b75 100644 --- a/docs/configs/settings.md +++ b/docs/configs/settings.md @@ -377,9 +377,10 @@ You can use the 'Quick Launch' feature to search services, perform a web search There are a few optional settings for the Quick Launch feature: -- `searchDescriptions`: which lets you control whether item descriptions are included in searches. This is off by default. When enabled, results that match the item name will be placed above those that only match the description. +- `searchDescriptions`: which lets you control whether item descriptions are included in searches. This is false by default. When enabled, results that match the item name will be placed above those that only match the description. - `hideInternetSearch`: disable automatically including the currently-selected web search (e.g. from the widget) as a Quick Launch option. This is false by default, enabling the feature. -- `showSearchSuggestions`: shows search suggestions for the internet search. This value will be inherited from the search widget if it is not specified. If it is not specified there either, it will default to false. +- `showSearchSuggestions`: show search suggestions for the internet search. If this is not specified then the setting will be inherited from the search widget. If it is not specified there either, it will default to false. For custom providers the `suggestionUrl` needs to be set in order for this to work. +- `provider`: search engine provider. If none is specified it will try to use the provider set for the Search Widget, if neither are present then internet search will be disabled. - `hideVisitURL`: disable detecting and offering an option to open URLs. This is false by default, enabling the feature. ```yaml @@ -388,6 +389,17 @@ quicklaunch: hideInternetSearch: true showSearchSuggestions: true hideVisitURL: true + provider: google # google, duckduckgo, bing, baidu, brave or custom +``` + +or for a custom search: + +```yaml +quicklaunch: + provider: custom + url: https://www.ecosia.org/search?q= + target: _blank + suggestionUrl: https://ac.ecosia.org/autocomplete?type=list&q= ``` ## Homepage Version diff --git a/src/components/quicklaunch.jsx b/src/components/quicklaunch.jsx index aaa40493cf0..5a63e000cb4 100644 --- a/src/components/quicklaunch.jsx +++ b/src/components/quicklaunch.jsx @@ -1,26 +1,18 @@ import { useTranslation } from "react-i18next"; import { useEffect, useState, useRef, useCallback, useContext } from "react"; import classNames from "classnames"; +import useSWR from "swr"; import ResolvedIcon from "./resolvedicon"; +import { getStoredProvider, searchProviders } from "./widgets/search/search"; import { SettingsContext } from "utils/contexts/settings"; -export default function QuickLaunch({ - servicesAndBookmarks, - searchString, - setSearchString, - isOpen, - close, - searchProvider, -}) { +export default function QuickLaunch({ servicesAndBookmarks, searchString, setSearchString, isOpen, close }) { const { t } = useTranslation(); const { settings } = useContext(SettingsContext); const { searchDescriptions = false, hideVisitURL = false } = settings?.quicklaunch ?? {}; - const showSearchSuggestions = !!( - settings?.quicklaunch?.showSearchSuggestions ?? searchProvider?.showSearchSuggestions - ); const searchField = useRef(); @@ -29,9 +21,42 @@ export default function QuickLaunch({ const [url, setUrl] = useState(null); const [searchSuggestions, setSearchSuggestions] = useState([]); + const { data: widgets } = useSWR("/api/widgets"); + const searchWidget = Object.values(widgets).find((w) => w.type === "search"); + + let searchProvider; + + if (settings?.quicklaunch?.provider === "custom" && settings?.quicklaunch?.url?.length > 0) { + searchProvider = settings.quicklaunch; + } else if (settings?.quicklaunch?.provider && settings?.quicklaunch?.provider !== "custom") { + searchProvider = searchProviders[settings.quicklaunch.provider]; + } else if (searchWidget) { + // If there is no search provider in quick launch settings, try to get it from the search widget + if (Array.isArray(searchWidget.options?.provider)) { + // If search provider is a list, try to retrieve from localstorage, fall back to the first + searchProvider = getStoredProvider() ?? searchProviders[searchWidget.options.provider[0]]; + } else if (searchWidget.options?.provider === "custom") { + searchProvider = searchWidget.options; + } else { + searchProvider = searchProviders[searchWidget.options?.provider]; + } + } + + if (searchProvider) { + searchProvider.showSearchSuggestions = !!( + settings?.quicklaunch?.showSearchSuggestions ?? + searchWidget?.options?.showSearchSuggestions ?? + false + ); + } + function openCurrentItem(newWindow) { const result = results[currentItemIndex]; - window.open(result.href, newWindow ? "_blank" : result.target ?? settings.target ?? "_blank", "noreferrer"); + window.open( + result.href, + newWindow ? "_blank" : result.target ?? searchProvider?.target ?? settings.target ?? "_blank", + "noreferrer", + ); } const closeAndReset = useCallback(() => { @@ -119,7 +144,7 @@ export default function QuickLaunch({ type: "search", }); - if (showSearchSuggestions && searchProvider.suggestionUrl) { + if (searchProvider.showSearchSuggestions && searchProvider.suggestionUrl) { if (searchString.trim() !== searchSuggestions[0]?.trim()) { fetch( `/api/search/searchSuggestion?query=${encodeURIComponent(searchString)}&providerName=${ @@ -172,17 +197,7 @@ export default function QuickLaunch({ return () => { abortController.abort(); }; - }, [ - searchString, - servicesAndBookmarks, - searchDescriptions, - hideVisitURL, - showSearchSuggestions, - searchSuggestions, - searchProvider, - url, - t, - ]); + }, [searchString, servicesAndBookmarks, searchDescriptions, hideVisitURL, searchSuggestions, searchProvider, url, t]); const [hidden, setHidden] = useState(true); useEffect(() => { diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 4ae5d93a869..75674c3046d 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -26,7 +26,6 @@ import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/conf import ErrorBoundary from "components/errorboundry"; import themes from "utils/styles/themes"; import QuickLaunch from "components/quicklaunch"; -import { getStoredProvider, searchProviders } from "components/widgets/search/search"; const ThemeToggle = dynamic(() => import("components/toggles/theme"), { ssr: false, @@ -204,20 +203,6 @@ function Home({ initialSettings }) { const [searching, setSearching] = useState(false); const [searchString, setSearchString] = useState(""); - let searchProvider = null; - const searchWidget = Object.values(widgets).find((w) => w.type === "search"); - if (searchWidget) { - if (Array.isArray(searchWidget.options?.provider)) { - // if search provider is a list, try to retrieve from localstorage, fall back to the first - searchProvider = getStoredProvider() ?? searchProviders[searchWidget.options.provider[0]]; - } else if (searchWidget.options?.provider === "custom") { - searchProvider = searchWidget.options; - } else { - searchProvider = searchProviders[searchWidget.options?.provider]; - } - // to pass to quicklaunch - searchProvider.showSearchSuggestions = searchWidget.options?.showSearchSuggestions; - } const headerStyle = settings?.headerStyle || "underlined"; useEffect(() => { @@ -404,7 +389,6 @@ function Home({ initialSettings }) { setSearchString={setSearchString} isOpen={searching} close={setSearching} - searchProvider={settings.quicklaunch?.hideInternetSearch ? null : searchProvider} />