diff --git a/public/static/animations/simple-frosted-glow.css b/public/static/animations/simple-frosted-glow.css new file mode 100644 index 0000000..58d4ae6 --- /dev/null +++ b/public/static/animations/simple-frosted-glow.css @@ -0,0 +1,15 @@ +.results_aggregated .result { + margin: 1rem; + padding: 1rem; + border-radius: 1rem; +} + +.results_aggregated .result:hover { + box-shadow: + inset 0 0 3rem var(--color-two), + inset 0 0 6rem var(--color-five), + inset 0 0 9rem var(--color-three), + 0 0 0.25rem var(--color-two), + 0 0 0.5rem var(--color-five), + 0 0 0.75rem var(--color-three); +} diff --git a/public/static/settings.js b/public/static/settings.js index fc0e118..b8d8f88 100644 --- a/public/static/settings.js +++ b/public/static/settings.js @@ -50,6 +50,9 @@ function setClientSettings() { case 'colorschemes': cookie_dictionary['colorscheme'] = select_tag.value break + case 'animations': + cookie_dictionary['animation'] = select_tag.value || null + break case 'safe_search_levels': cookie_dictionary['safe_search_level'] = Number(select_tag.value) break @@ -103,13 +106,50 @@ function getClientSettings() { .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 - 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` + let links = Array.from(document.querySelectorAll('link')) + + // A check to determine whether the animation link exists under the head tag or not. + // If it does not exists then create and add a new animation link under the head tag + // and update the other link tags href according to the settings provided by the user + // via the UI. On the other hand if it does exist then just update all the link tags + // href according to the settings provided by the user via the UI. + if (!links.some((item) => item.href.includes('static/animations'))) { + if (cookie_value['animation']) { + let animation_link = document.createElement('link') + animation_link.href = `static/animations/${cookie_value['animation']}.css` + animation_link.rel = 'stylesheet' + animation_link.type = 'text/css' + document.querySelector('head').appendChild(animation_link) } - }) + // Loop through all link tags and update their href values to match the user's preferences + links.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` + } + }) + } else { + // Loop through all link tags and update their href values to match the user's preferences + links.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` + } else if ( + item.href.includes('static/animations') && + cookie_value['animation'] + ) { + item.href = `static/colorschemes/${cookie_value['animation']}.css` + } + }) + if (!cookie_value['animation']) { + document + .querySelector('head') + .removeChild( + links.filter((item) => item.href.includes('static/animations')), + ) + } + } } } diff --git a/src/config/parser.rs b/src/config/parser.rs index b33936a..20a4a1a 100644 --- a/src/config/parser.rs +++ b/src/config/parser.rs @@ -115,6 +115,7 @@ impl Config { style: Style::new( globals.get::<_, String>("theme")?, globals.get::<_, String>("colorscheme")?, + globals.get::<_, Option>("animation")?, ), #[cfg(feature = "redis-cache")] redis_url: globals.get::<_, String>("redis_url")?, diff --git a/src/models/parser_models.rs b/src/models/parser_models.rs index a669bd6..75a4c13 100644 --- a/src/models/parser_models.rs +++ b/src/models/parser_models.rs @@ -17,6 +17,9 @@ pub struct Style { /// It stores the parsed colorscheme option used to set a colorscheme for the /// theme being used. pub colorscheme: String, + /// It stores the parsed animation option used to set an animation for the + /// theme being used. + pub animation: Option, } impl Style { @@ -27,8 +30,12 @@ impl Style { /// * `theme` - It takes the parsed theme option used to set a theme for the website. /// * `colorscheme` - It takes the parsed colorscheme option used to set a colorscheme /// for the theme being used. - pub fn new(theme: String, colorscheme: String) -> Self { - Style { theme, colorscheme } + pub fn new(theme: String, colorscheme: String, animation: Option) -> Self { + Style { + theme, + colorscheme, + animation, + } } } diff --git a/src/server/router.rs b/src/server/router.rs index ea8387b..b9fe1d4 100644 --- a/src/server/router.rs +++ b/src/server/router.rs @@ -13,7 +13,12 @@ use std::fs::read_to_string; #[get("/")] pub async fn index(config: web::Data) -> Result> { Ok(HttpResponse::Ok().body( - crate::templates::views::index::index(&config.style.colorscheme, &config.style.theme).0, + crate::templates::views::index::index( + &config.style.colorscheme, + &config.style.theme, + &config.style.animation, + ) + .0, )) } @@ -28,6 +33,7 @@ pub async fn not_found( crate::templates::views::not_found::not_found( &config.style.colorscheme, &config.style.theme, + &config.style.animation, ) .0, )) @@ -47,7 +53,12 @@ pub async fn robots_data(_req: HttpRequest) -> Result) -> Result> { Ok(HttpResponse::Ok().body( - crate::templates::views::about::about(&config.style.colorscheme, &config.style.theme).0, + crate::templates::views::about::about( + &config.style.colorscheme, + &config.style.theme, + &config.style.animation, + ) + .0, )) } @@ -60,6 +71,7 @@ pub async fn settings( crate::templates::views::settings::settings( &config.style.colorscheme, &config.style.theme, + &config.style.animation, &config .upstream_search_engines .keys() diff --git a/src/server/routes/search.rs b/src/server/routes/search.rs index 670ee60..84ba3de 100644 --- a/src/server/routes/search.rs +++ b/src/server/routes/search.rs @@ -72,6 +72,7 @@ pub async fn search( crate::templates::views::search::search( &config.style.colorscheme, &config.style.theme, + &config.style.animation, query, &results?, ) diff --git a/src/templates/partials/header.rs b/src/templates/partials/header.rs index c477aec..e248248 100644 --- a/src/templates/partials/header.rs +++ b/src/templates/partials/header.rs @@ -13,7 +13,7 @@ use maud::{html, Markup, PreEscaped, DOCTYPE}; /// # Returns /// /// It returns the compiled html markup code for the header as a result. -pub fn header(colorscheme: &str, theme: &str) -> Markup { +pub fn header(colorscheme: &str, theme: &str, animation: &Option) -> Markup { html!( (DOCTYPE) html lang="en" @@ -24,6 +24,9 @@ pub fn header(colorscheme: &str, theme: &str) -> Markup { meta name="viewport" content="width=device-width, initial-scale=1"; link href=(format!("static/colorschemes/{colorscheme}.css")) rel="stylesheet" type="text/css"; link href=(format!("static/themes/{theme}.css")) rel="stylesheet" type="text/css"; + @if animation.is_some() { + link href=(format!("static/animations/{}.css", animation.as_ref().unwrap())) rel="stylesheet" type="text/css"; + } } (PreEscaped("")) diff --git a/src/templates/partials/settings_tabs/user_interface.rs b/src/templates/partials/settings_tabs/user_interface.rs index c978c3e..d94465b 100644 --- a/src/templates/partials/settings_tabs/user_interface.rs +++ b/src/templates/partials/settings_tabs/user_interface.rs @@ -60,6 +60,17 @@ pub fn user_interface() -> Result> { option value=(k){(v)} } } + h3{"select animation"} + p class="description"{ + "Select the animation for your theme to be used in user interface" + } + select name="animations"{ + option value=""{"none"} + @for (k,v) in style_option_list("animations")?{ + option value=(k){(v)} + } + } + } )) } diff --git a/src/templates/views/about.rs b/src/templates/views/about.rs index 9ee2d6d..3f34819 100644 --- a/src/templates/views/about.rs +++ b/src/templates/views/about.rs @@ -14,9 +14,9 @@ use crate::templates::partials::{footer::footer, header::header}; /// # Returns /// /// It returns the compiled html markup code as a result. -pub fn about(colorscheme: &str, theme: &str) -> Markup { +pub fn about(colorscheme: &str, theme: &str, animation: &Option) -> Markup { html!( - (header(colorscheme, theme)) + (header(colorscheme, theme, animation)) main class="about-container"{ article { div{ diff --git a/src/templates/views/index.rs b/src/templates/views/index.rs index d55ef7d..9d3742e 100644 --- a/src/templates/views/index.rs +++ b/src/templates/views/index.rs @@ -14,7 +14,7 @@ use crate::templates::partials::{bar::bar, footer::footer, header::header}; /// # Returns /// /// It returns the compiled html markup code as a result. -pub fn index(colorscheme: &str, theme: &str) -> Markup { +pub fn index(colorscheme: &str, theme: &str, animation: &Option) -> Markup { let logo_svg = r#" @@ -26,7 +26,7 @@ pub fn index(colorscheme: &str, theme: &str) -> Markup { "#; html!( - (header(colorscheme, theme)) + (header(colorscheme, theme, animation)) main class="search-container"{ (PreEscaped(logo_svg)) (bar(&String::default())) diff --git a/src/templates/views/not_found.rs b/src/templates/views/not_found.rs index 9e23da9..853f260 100644 --- a/src/templates/views/not_found.rs +++ b/src/templates/views/not_found.rs @@ -13,9 +13,9 @@ use maud::{html, Markup}; /// # Returns /// /// It returns the compiled html markup code as a result. -pub fn not_found(colorscheme: &str, theme: &str) -> Markup { +pub fn not_found(colorscheme: &str, theme: &str, animation: &Option) -> Markup { html!( - (header(colorscheme, theme)) + (header(colorscheme, theme, animation)) main class="error_container"{ img src="images/robot-404.svg" alt="Image of broken robot."; .error_content{ diff --git a/src/templates/views/search.rs b/src/templates/views/search.rs index 9fef7f0..07b8b42 100644 --- a/src/templates/views/search.rs +++ b/src/templates/views/search.rs @@ -22,11 +22,12 @@ use crate::{ pub fn search( colorscheme: &str, theme: &str, + animation: &Option, query: &str, search_results: &SearchResults, ) -> Markup { html!( - (header(colorscheme, theme)) + (header(colorscheme, theme, animation)) main class="results"{ (search_bar(&search_results.engine_errors_info, search_results.safe_search_level, query)) .results_aggregated{ diff --git a/src/templates/views/settings.rs b/src/templates/views/settings.rs index 7b69ac7..6da5202 100644 --- a/src/templates/views/settings.rs +++ b/src/templates/views/settings.rs @@ -25,10 +25,11 @@ use crate::templates::partials::{ pub fn settings( colorscheme: &str, theme: &str, + animation: &Option, engine_names: &[&String], ) -> Result> { Ok(html!( - (header(colorscheme, theme)) + (header(colorscheme, theme, animation)) main class="settings"{ h1{"Settings"} hr; diff --git a/tests/index.rs b/tests/index.rs index 892e0b9..563c2d9 100644 --- a/tests/index.rs +++ b/tests/index.rs @@ -24,7 +24,12 @@ async fn test_index() { assert_eq!(res.status(), 200); let config = Config::parse(true).unwrap(); - let template = views::index::index(&config.style.colorscheme, &config.style.theme).0; + let template = views::index::index( + &config.style.colorscheme, + &config.style.theme, + &config.style.animation, + ) + .0; assert_eq!(res.text().await.unwrap(), template); } diff --git a/websurfx/config.lua b/websurfx/config.lua index 62ae412..2444f86 100644 --- a/websurfx/config.lua +++ b/websurfx/config.lua @@ -1,18 +1,18 @@ -- ### General ### logging = true -- an option to enable or disable logs. -debug = false -- an option to enable or disable debug mode. -threads = 10 -- the amount of threads that the app will use to run (the value should be greater than 0). +debug = false -- an option to enable or disable debug mode. +threads = 10 -- the amount of threads that the app will use to run (the value should be greater than 0). -- ### Server ### -port = "8080" -- port on which server should be launched +port = "8080" -- port on which server should be launched binding_ip = "127.0.0.1" --ip address on the which server should be launched. -production_use = false -- whether to use production mode or not (in other words this option should be used if it is to be used to host it on the server to provide a service to a large number of users (more than one)) +production_use = false -- whether to use production mode or not (in other words this option should be used if it is to be used to host it on the server to provide a service to a large number of users (more than one)) -- if production_use is set to true -- There will be a random delay before sending the request to the search engines, this is to prevent DDoSing the upstream search engines from a large number of simultaneous requests. -request_timeout = 30 -- timeout for the search requests sent to the upstream search engines to be fetched (value in seconds). +request_timeout = 30 -- timeout for the search requests sent to the upstream search engines to be fetched (value in seconds). rate_limiter = { - number_of_requests = 20, -- The number of request that are allowed within a provided time limit. - time_limit = 3, -- The time limit in which the quantity of requests that should be accepted. + number_of_requests = 20, -- The number of request that are allowed within a provided time limit. + time_limit = 3, -- The time limit in which the quantity of requests that should be accepted. } -- ### Search ### @@ -43,11 +43,20 @@ safe_search = 2 -- tomorrow-night -- }} colorscheme = "catppuccin-mocha" -- the colorscheme name which should be used for the website theme -theme = "simple" -- the theme name which should be used for the website +-- The different themes provided are: +-- {{ +-- simple +-- }} +theme = "simple" -- the theme name which should be used for the website +-- The different animations provided are: +-- {{ +-- simple-frosted-glow +-- }} +animation = "simple-frosted-glow" -- the animation name which should be used with the theme or `nil` if you don't want any animations. -- ### Caching ### redis_url = "redis://127.0.0.1:8082" -- redis connection url address on which the client should connect on. -cache_expiry_time = 600 -- This option takes the expiry time of the search results (value in seconds and the value should be greater than or equal to 60 seconds). +cache_expiry_time = 600 -- This option takes the expiry time of the search results (value in seconds and the value should be greater than or equal to 60 seconds). -- ### Search Engines ### upstream_search_engines = { DuckDuckGo = true,