diff --git a/Cargo.lock b/Cargo.lock index d3f5e85..958d959 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3932,7 +3932,7 @@ dependencies = [ [[package]] name = "websurfx" -version = "0.21.6" +version = "0.22.0" dependencies = [ "actix-cors", "actix-files", diff --git a/Cargo.toml b/Cargo.toml index 13048c7..eb31f59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "websurfx" -version = "0.21.6" +version = "0.22.0" edition = "2021" description = "An open-source alternative to Searx that provides clean, ad-free, and organic results with incredible speed while keeping privacy and security in mind." repository = "https://github.com/neon-mmd/websurfx" diff --git a/public/static/cookies.js b/public/static/cookies.js index 677eff7..6b55e02 100644 --- a/public/static/cookies.js +++ b/public/static/cookies.js @@ -16,8 +16,9 @@ document.addEventListener( let cookie = decodeURIComponent(document.cookie) // Set the value of the input field to the decoded cookie value if it is not empty // Otherwise, display a message indicating that no cookies have been saved on the user's system - document.querySelector('.cookies input').value = - cookie !== '' ? cookie : 'No cookies have been saved on your system' + document.querySelector('.cookies input').value = cookie.length + ? cookie + : 'No cookies have been saved on your system' } catch (error) { // If there is an error decoding the cookie, log the error to the console // and display an error message in the input field @@ -25,5 +26,5 @@ document.addEventListener( document.querySelector('.cookies input').value = 'Error decoding cookie' } }, - false + false, ) diff --git a/public/static/index.js b/public/static/index.js index 050829a..515065a 100644 --- a/public/static/index.js +++ b/public/static/index.js @@ -2,16 +2,25 @@ * Selects the input element for the search box * @type {HTMLInputElement} */ -const searchBox = document.querySelector('input'); +const searchBox = document.querySelector('input') /** * Redirects the user to the search results page with the query parameter */ function searchWeb() { - const query = searchBox.value.trim(); - if (query) { - window.location.href = `search?q=${encodeURIComponent(query)}`; - } + const query = searchBox.value.trim() + try { + let safeSearchLevel = document.querySelector('.search_options select').value + if (query) { + window.location.href = `search?q=${encodeURIComponent( + query, + )}&safesearch=${encodeURIComponent(safeSearchLevel)}` + } + } catch (error) { + if (query) { + window.location.href = `search?q=${encodeURIComponent(query)}` + } + } } /** @@ -19,7 +28,7 @@ function searchWeb() { * @param {KeyboardEvent} e - The keyboard event object */ searchBox.addEventListener('keyup', (e) => { - if (e.key === 'Enter') { - searchWeb(); - } -}); + if (e.key === 'Enter') { + searchWeb() + } +}) diff --git a/public/static/pagination.js b/public/static/pagination.js index 4f5697c..bdbfb39 100644 --- a/public/static/pagination.js +++ b/public/static/pagination.js @@ -3,8 +3,8 @@ * @returns {void} */ function navigate_forward() { - const url = new URL(window.location); - const searchParams = url.searchParams; + let url = new URL(window.location); + let searchParams = url.searchParams; let q = searchParams.get('q'); let page = parseInt(searchParams.get('page')); @@ -23,8 +23,8 @@ function navigate_forward() { * @returns {void} */ function navigate_backward() { - const url = new URL(window.location); - const searchParams = url.searchParams; + let url = new URL(window.location); + let searchParams = url.searchParams; let q = searchParams.get('q'); let page = parseInt(searchParams.get('page')); diff --git a/public/static/search_area_options.js b/public/static/search_area_options.js new file mode 100644 index 0000000..10e0390 --- /dev/null +++ b/public/static/search_area_options.js @@ -0,0 +1,18 @@ +document.addEventListener( + 'DOMContentLoaded', + () => { + let url = new URL(window.location) + let searchParams = url.searchParams + + let safeSearchLevel = searchParams.get('safesearch') + + if ( + safeSearchLevel >= 0 && + safeSearchLevel <= 2 && + safeSearchLevel !== null + ) { + document.querySelector('.search_options select').value = safeSearchLevel + } + }, + false, +) diff --git a/public/static/settings.js b/public/static/settings.js index 42b8a4b..fc0e118 100644 --- a/public/static/settings.js +++ b/public/static/settings.js @@ -1,5 +1,5 @@ /** - * This function handles the toggling of selections of all upstream search engines + * This function handles the toggling of selections of all upstream search engines * options in the settings page under the tab engines. */ function toggleAllSelection() { @@ -8,12 +8,12 @@ function toggleAllSelection() { .forEach( (engine_checkbox) => (engine_checkbox.checked = - document.querySelector('.select_all').checked) + document.querySelector('.select_all').checked), ) } /** - * This function adds the functionality to sidebar buttons to only show settings + * This function adds the functionality to sidebar buttons to only show settings * related to that tab. * @param {HTMLElement} current_tab - The current tab that was clicked. */ @@ -43,20 +43,28 @@ function setClientSettings() { // Loop through all select tags and add their values to the cookie dictionary document.querySelectorAll('select').forEach((select_tag) => { - if (select_tag.name === 'themes') { - cookie_dictionary['theme'] = select_tag.value - } else if (select_tag.name === 'colorschemes') { - cookie_dictionary['colorscheme'] = select_tag.value + switch (select_tag.name) { + case 'themes': + cookie_dictionary['theme'] = select_tag.value + break + case 'colorschemes': + cookie_dictionary['colorscheme'] = select_tag.value + break + case 'safe_search_levels': + cookie_dictionary['safe_search_level'] = Number(select_tag.value) + break } }) // Loop through all engine checkboxes and add their values to the cookie dictionary let engines = [] + document.querySelectorAll('.engine').forEach((engine_checkbox) => { - if (engine_checkbox.checked === true) { + if (engine_checkbox.checked) { engines.push(engine_checkbox.parentNode.parentNode.innerText.trim()) } }) + cookie_dictionary['engines'] = engines // Set the expiration date for the cookie to 1 year from the current date @@ -65,7 +73,7 @@ function setClientSettings() { // Save the cookie to the user's machine document.cookie = `appCookie=${JSON.stringify( - cookie_dictionary + cookie_dictionary, )}; expires=${expiration_date.toUTCString()}` // Display a success message to the user @@ -79,9 +87,9 @@ function setClientSettings() { } /** - * This functions gets the saved cookies if it is present on the user's machine If it - * is available then it is parsed and converted to an object which is then used to - * retrieve the preferences that the user had selected previously and is then loaded in the + * This functions gets the saved cookies if it is present on the user's machine If it + * is available then it is parsed and converted to an object which is then used to + * retrieve the preferences that the user had selected previously and is then loaded in the * website otherwise the function does nothing and the default server side settings are loaded. */ function getClientSettings() { @@ -89,21 +97,19 @@ function getClientSettings() { let cookie = decodeURIComponent(document.cookie) // If the cookie is not empty, parse it and use it to set the user's preferences - if (cookie !== '') { - let cookie_value = decodeURIComponent(document.cookie) + if (cookie.length) { + let cookie_value = cookie .split(';') .map((item) => item.split('=')) .reduce((acc, [_, v]) => (acc = JSON.parse(v)) && acc, {}) // Loop through all link tags and update their href values to match the user's preferences - let links = Array.from(document.querySelectorAll('link')).forEach( - (item) => { - if (item.href.includes('static/themes')) { - item.href = `static/themes/${cookie_value['theme']}.css` - } else if (item.href.includes('static/colorschemes')) { - item.href = `static/colorschemes/${cookie_value['colorscheme']}.css` - } + Array.from(document.querySelectorAll('link')).forEach((item) => { + if (item.href.includes('static/themes')) { + item.href = `static/themes/${cookie_value['theme']}.css` + } else if (item.href.includes('static/colorschemes')) { + item.href = `static/colorschemes/${cookie_value['colorscheme']}.css` } - ) + }) } } diff --git a/public/static/themes/simple.css b/public/static/themes/simple.css index 3d9c3b9..340e58a 100644 --- a/public/static/themes/simple.css +++ b/public/static/themes/simple.css @@ -70,6 +70,28 @@ body { filter: brightness(1.2); } +.search_area .search_options { + display: flex; + justify-content: space-between; + align-items: center; +} + +.search_area .search_options select { + margin: 0.7rem 0; + width: 20rem; + background-color: var(--color-one); + color: var(--foreground-color); + padding: 1rem 2rem; + border-radius: 0.5rem; + outline: none; + border: none; + text-transform: capitalize; +} + +.search_area .search_options option:hover { + background-color: var(--color-one); +} + .result_not_found { display: flex; flex-direction: column; @@ -499,7 +521,8 @@ footer { color: var(--foreground-color); } -.settings_container .user_interface select { +.settings_container .user_interface select, +.settings_container .general select { margin: 0.7rem 0; width: 20rem; background-color: var(--background-color); @@ -511,7 +534,8 @@ footer { text-transform: capitalize; } -.settings_container .user_interface option:hover { +.settings_container .user_interface option:hover, +.settings_container .general option:hover { background-color: var(--color-one); } diff --git a/public/templates/engines_tab.html b/public/templates/engines_tab.html index 0e36b49..ffca881 100644 --- a/public/templates/engines_tab.html +++ b/public/templates/engines_tab.html @@ -1,4 +1,5 @@
Select the search engines from the list of engines that you want results diff --git a/public/templates/general_tab.html b/public/templates/general_tab.html index b83935a..92fc592 100644 --- a/public/templates/general_tab.html +++ b/public/templates/general_tab.html @@ -1,4 +1,13 @@
Coming soon!!
++ Select a safe search level from the menu below to filter content based on + the level. +
+
Select the theme from the available themes to be used in user interface
diff --git a/src/models/aggregation_models.rs b/src/models/aggregation_models.rs
index 656297f..bab7e62 100644
--- a/src/models/aggregation_models.rs
+++ b/src/models/aggregation_models.rs
@@ -122,6 +122,8 @@ pub struct SearchResults {
/// search query was filtered when the safe search level set to 3 and it
/// was present in the `Blocklist` file.
pub filtered: bool,
+ /// Stores the safe search level `safesearch` provided in the search url.
+ pub safe_search_level: u8,
}
impl SearchResults {
@@ -147,6 +149,7 @@ impl SearchResults {
engine_errors_info: engine_errors_info.to_owned(),
disallowed: Default::default(),
filtered: Default::default(),
+ safe_search_level: Default::default(),
}
}
@@ -178,4 +181,9 @@ impl SearchResults {
pub fn results(&mut self) -> Vec