Added option to set secondary search provider

This commit is contained in:
Paweł Malak 2022-03-25 14:28:40 +01:00
parent 2c0491a5b0
commit 16121ff547
9 changed files with 79 additions and 25 deletions

View file

@ -1,5 +1,6 @@
### v2.3.0 (TBA) ### v2.3.0 (TBA)
- Added custom theme editor ([#246](https://github.com/pawelmalak/flame/issues/246)) - Added custom theme editor ([#246](https://github.com/pawelmalak/flame/issues/246))
- Added option to set secondary search provider ([#295](https://github.com/pawelmalak/flame/issues/295))
- Fixed bug where pressing Enter with empty search bar would redirect to search results ([#325](https://github.com/pawelmalak/flame/issues/325)) - Fixed bug where pressing Enter with empty search bar would redirect to search results ([#325](https://github.com/pawelmalak/flame/issues/325))
- Fixed bug where user could create empty app or bookmark which was causing page to go blank ([#332](https://github.com/pawelmalak/flame/issues/332)) - Fixed bug where user could create empty app or bookmark which was causing page to go blank ([#332](https://github.com/pawelmalak/flame/issues/332))
- Added new theme: Mint - Added new theme: Mint

View file

@ -64,16 +64,22 @@ export const SearchBar = (props: Props): JSX.Element => {
}; };
const searchHandler = (e: KeyboardEvent<HTMLInputElement>) => { const searchHandler = (e: KeyboardEvent<HTMLInputElement>) => {
const { isLocal, search, query, isURL, sameTab, rawQuery } = searchParser( const {
inputRef.current.value isLocal,
); encodedURL,
primarySearch,
secondarySearch,
isURL,
sameTab,
rawQuery,
} = searchParser(inputRef.current.value);
if (isLocal) { if (isLocal) {
setLocalSearch(search); setLocalSearch(encodedURL);
} }
if (e.code === 'Enter' || e.code === 'NumpadEnter') { if (e.code === 'Enter' || e.code === 'NumpadEnter') {
if (!query.prefix) { if (!primarySearch.prefix) {
// Prefix not found -> emit notification // Prefix not found -> emit notification
createNotification({ createNotification({
title: 'Error', title: 'Error',
@ -91,21 +97,20 @@ export const SearchBar = (props: Props): JSX.Element => {
redirectUrl(bookmarkSearchResult[0].bookmarks[0].url, sameTab); redirectUrl(bookmarkSearchResult[0].bookmarks[0].url, sameTab);
} else { } else {
// no local results -> search the internet with the default search provider if query is not empty // no local results -> search the internet with the default search provider if query is not empty
if (!/^ *$/.test(rawQuery)) { if (!/^ *$/.test(rawQuery)) {
let template = query.template; let template = primarySearch.template;
if (query.prefix === 'l') { if (primarySearch.prefix === 'l') {
template = 'https://duckduckgo.com/?q='; template = secondarySearch.template;
} }
const url = `${template}${search}`; const url = `${template}${encodedURL}`;
redirectUrl(url, sameTab); redirectUrl(url, sameTab);
} }
} }
} else { } else {
// Valid query -> redirect to search results // Valid query -> redirect to search results
const url = `${query.template}${search}`; const url = `${primarySearch.template}${encodedURL}`;
redirectUrl(url, sameTab); redirectUrl(url, sameTab);
} }
} else if (e.code === 'Escape') { } else if (e.code === 'Escape') {

View file

@ -167,7 +167,7 @@ export const GeneralSettings = (): JSX.Element => {
{/* === SEARCH OPTIONS === */} {/* === SEARCH OPTIONS === */}
<SettingsHeadline text="Search" /> <SettingsHeadline text="Search" />
<InputGroup> <InputGroup>
<label htmlFor="defaultSearchProvider">Default search provider</label> <label htmlFor="defaultSearchProvider">Primary search provider</label>
<select <select
id="defaultSearchProvider" id="defaultSearchProvider"
name="defaultSearchProvider" name="defaultSearchProvider"
@ -186,6 +186,34 @@ export const GeneralSettings = (): JSX.Element => {
</select> </select>
</InputGroup> </InputGroup>
{formData.defaultSearchProvider === 'l' && (
<InputGroup>
<label htmlFor="secondarySearchProvider">
Secondary search provider
</label>
<select
id="secondarySearchProvider"
name="secondarySearchProvider"
value={formData.secondarySearchProvider}
onChange={(e) => inputChangeHandler(e)}
>
{[...queries, ...customQueries].map((query: Query, idx) => {
const isCustom = idx >= queries.length;
return (
<option key={idx} value={query.prefix}>
{isCustom && '+'} {query.name}
</option>
);
})}
</select>
<span>
Will be used when "Local search" is primary search provider and
there are not any local results
</span>
</InputGroup>
)}
<InputGroup> <InputGroup>
<label htmlFor="searchSameTab"> <label htmlFor="searchSameTab">
Open search results in the same tab Open search results in the same tab

View file

@ -17,6 +17,7 @@ export interface Config {
hideCategories: boolean; hideCategories: boolean;
hideSearch: boolean; hideSearch: boolean;
defaultSearchProvider: string; defaultSearchProvider: string;
secondarySearchProvider: string;
dockerApps: boolean; dockerApps: boolean;
dockerHost: string; dockerHost: string;
kubernetesApps: boolean; kubernetesApps: boolean;

View file

@ -10,6 +10,7 @@ export interface WeatherForm {
export interface GeneralForm { export interface GeneralForm {
defaultSearchProvider: string; defaultSearchProvider: string;
secondarySearchProvider: string;
searchSameTab: boolean; searchSameTab: boolean;
pinAppsByDefault: boolean; pinAppsByDefault: boolean;
pinCategoriesByDefault: boolean; pinCategoriesByDefault: boolean;

View file

@ -4,7 +4,8 @@ export interface SearchResult {
isLocal: boolean; isLocal: boolean;
isURL: boolean; isURL: boolean;
sameTab: boolean; sameTab: boolean;
search: string; encodedURL: string;
query: Query; primarySearch: Query;
secondarySearch: Query;
rawQuery: string; rawQuery: string;
} }

View file

@ -1,5 +1,5 @@
import { queries } from './searchQueries.json'; import { queries } from './searchQueries.json';
import { Query, SearchResult } from '../interfaces'; import { SearchResult } from '../interfaces';
import { store } from '../store/store'; import { store } from '../store/store';
import { isUrlOrIp } from '.'; import { isUrlOrIp } from '.';
@ -8,8 +8,13 @@ export const searchParser = (searchQuery: string): SearchResult => {
isLocal: false, isLocal: false,
isURL: false, isURL: false,
sameTab: false, sameTab: false,
search: '', encodedURL: '',
query: { primarySearch: {
name: '',
prefix: '',
template: '',
},
secondarySearch: {
name: '', name: '',
prefix: '', prefix: '',
template: '', template: '',
@ -25,20 +30,26 @@ export const searchParser = (searchQuery: string): SearchResult => {
// Match prefix and query // Match prefix and query
const splitQuery = searchQuery.match(/^\/([a-z]+)[ ](.+)$/i); const splitQuery = searchQuery.match(/^\/([a-z]+)[ ](.+)$/i);
// Extract prefix
const prefix = splitQuery ? splitQuery[1] : config.defaultSearchProvider; const prefix = splitQuery ? splitQuery[1] : config.defaultSearchProvider;
const search = splitQuery // Encode url
const encodedURL = splitQuery
? encodeURIComponent(splitQuery[2]) ? encodeURIComponent(splitQuery[2])
: encodeURIComponent(searchQuery); : encodeURIComponent(searchQuery);
const query = [...queries, ...customQueries].find( // Find primary search engine template
(q: Query) => q.prefix === prefix const findProvider = (prefix: string) => {
); return [...queries, ...customQueries].find((q) => q.prefix === prefix);
};
// If search provider was found const primarySearch = findProvider(prefix);
if (query) { const secondarySearch = findProvider(config.secondarySearchProvider);
result.query = query;
result.search = search; // If search providers were found
if (primarySearch) {
result.primarySearch = primarySearch;
result.encodedURL = encodedURL;
if (prefix === 'l') { if (prefix === 'l') {
result.isLocal = true; result.isLocal = true;
@ -46,6 +57,10 @@ export const searchParser = (searchQuery: string): SearchResult => {
result.sameTab = config.searchSameTab; result.sameTab = config.searchSameTab;
} }
if (secondarySearch) {
result.secondarySearch = secondarySearch;
}
return result; return result;
} }

View file

@ -17,6 +17,7 @@ export const configTemplate: Config = {
hideCategories: false, hideCategories: false,
hideSearch: false, hideSearch: false,
defaultSearchProvider: 'l', defaultSearchProvider: 'l',
secondarySearchProvider: 'd',
dockerApps: false, dockerApps: false,
dockerHost: 'localhost', dockerHost: 'localhost',
kubernetesApps: false, kubernetesApps: false,

View file

@ -15,6 +15,7 @@
"hideCategories": false, "hideCategories": false,
"hideSearch": false, "hideSearch": false,
"defaultSearchProvider": "l", "defaultSearchProvider": "l",
"secondarySearchProvider": "d",
"dockerApps": false, "dockerApps": false,
"dockerHost": "localhost", "dockerHost": "localhost",
"kubernetesApps": false, "kubernetesApps": false,