diff --git a/README.md b/README.md index adcfec9..504c3db 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,22 @@ To download Verve, visit the [releases section](https://github.com/ParthJadhav/v 📌 It's worth noting that the default shortcut for opening Verve is `CMD + Shift + G`, and this can be changed from the preferences section within the app. This allows you to customize the app to your specific needs and preferences, making it even more convenient and easy to use. +## 🎨 Themes + +Verve theme is stored in: + +`/Users//Library/Application Support/com.parth-jadhav.verve/theme.json` + +Editing the theme file will change the theme of the app. Restart the app to see the changes. + +Download themes: [Themes](./docs/themes.md) + +Contributions would be amazing 👆 + + ## 💫 Upcoming Features - Extension support [Linked Issue](https://github.com/ParthJadhav/verve/issues/13) -- Let users theme the app by adding a customization interface in the Preferences window [Linked Issue](https://github.com/ParthJadhav/verve/issues/1) - Add a calculator feature that allows users to perform calculations and conversions using natural language input [Linked Issue](https://github.com/ParthJadhav/verve/issues/2) - Add a scroll feature to display all search results [Linked Issue](https://github.com/ParthJadhav/verve/issues/3) - Replace icons with generic extension-based icons [Linked Issue](https://github.com/ParthJadhav/verve/issues/4) diff --git a/docs/app.png b/docs/app.png index b01d623..8958741 100644 Binary files a/docs/app.png and b/docs/app.png differ diff --git a/docs/preferences.png b/docs/preferences.png index 94ed6b4..36db841 100644 Binary files a/docs/preferences.png and b/docs/preferences.png differ diff --git a/docs/preview.gif b/docs/preview.gif index 9781c2b..7ebd5b6 100644 Binary files a/docs/preview.gif and b/docs/preview.gif differ diff --git a/docs/themes.md b/docs/themes.md new file mode 100644 index 0000000..5381ba3 --- /dev/null +++ b/docs/themes.md @@ -0,0 +1,29 @@ +# 🎨 Themes + +Download and Paste the theme file in + +`/Users//Library/Application Support/com.parth-jadhav.verve/theme.json` + +and restart the app to see the changes. + +![Verve Dark Theme](./themes/theme-default/theme-default.png) +Download: [theme-default.json](./themes/theme-default/theme.json) + +![Verve Blue Theme](./themes/theme-blue/theme-blue.png) + +Download: [theme-blue.json](./themes/theme-blue/theme.json) + +![Verve Dracula Theme](./themes/theme-green/theme-green.png) + + +Download: [theme-green.json](./themes/theme-green/theme.json) + +### Create your own theme + +You can create your own theme by editing the theme.json file. You can find the theme.json file in the following location: + +`/Users//Library/Application Support/com.parth-jadhav.verve/theme.json` + +Save the file & Restart the app. + +Create a Pull request to add your theme to the list. \ No newline at end of file diff --git a/docs/themes/theme-blue/theme-blue.png b/docs/themes/theme-blue/theme-blue.png new file mode 100644 index 0000000..bd3a159 Binary files /dev/null and b/docs/themes/theme-blue/theme-blue.png differ diff --git a/docs/themes/theme-blue/theme.json b/docs/themes/theme-blue/theme.json new file mode 100644 index 0000000..d5ce8d4 --- /dev/null +++ b/docs/themes/theme-blue/theme.json @@ -0,0 +1,10 @@ +{ + "primary_bg_color": "rgba(20, 20, 80, 0.6)", + "secondary_bg_color": "rgba(84, 101, 115, 0.6)", + "primary_text_color": "#FFFFFF", + "secondary_text_color": "#878787", + "primary_accent_color": "#556CE5", + "secondary_accent_color": "#48A5FF", + "highlight_overlay": "rgba(255, 255, 255, 0.1)", + "dark_overlay": "rgba(0, 0, 0, 0.1)" +} \ No newline at end of file diff --git a/docs/themes/theme-default/theme-default.png b/docs/themes/theme-default/theme-default.png new file mode 100644 index 0000000..29b6c29 Binary files /dev/null and b/docs/themes/theme-default/theme-default.png differ diff --git a/docs/themes/theme-default/theme.json b/docs/themes/theme-default/theme.json new file mode 100644 index 0000000..f5cd52f --- /dev/null +++ b/docs/themes/theme-default/theme.json @@ -0,0 +1,10 @@ +{ + "primary_bg_color": "rgba(20, 45, 30, 0.6)", + "secondary_bg_color": "rgba(84, 101, 115, 0.6)", + "primary_text_color": "#FFFFFF", + "secondary_text_color": "#878787", + "primary_accent_color": "#556CE5", + "secondary_accent_color": "#48A5FF", + "highlight_overlay": "rgba(255, 255, 255, 0.1)", + "dark_overlay": "rgba(0, 0, 0, 0.1)" +} \ No newline at end of file diff --git a/docs/themes/theme-green/theme-green.png b/docs/themes/theme-green/theme-green.png new file mode 100644 index 0000000..2266903 Binary files /dev/null and b/docs/themes/theme-green/theme-green.png differ diff --git a/docs/themes/theme-green/theme.json b/docs/themes/theme-green/theme.json new file mode 100644 index 0000000..f5cd52f --- /dev/null +++ b/docs/themes/theme-green/theme.json @@ -0,0 +1,10 @@ +{ + "primary_bg_color": "rgba(20, 45, 30, 0.6)", + "secondary_bg_color": "rgba(84, 101, 115, 0.6)", + "primary_text_color": "#FFFFFF", + "secondary_text_color": "#878787", + "primary_accent_color": "#556CE5", + "secondary_accent_color": "#48A5FF", + "highlight_overlay": "rgba(255, 255, 255, 0.1)", + "dark_overlay": "rgba(0, 0, 0, 0.1)" +} \ No newline at end of file diff --git a/package.json b/package.json index 1d1b9cd..f6f04ba 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "verve", "private": true, - "version": "0.1.0", + "version": "0.2.0", "type": "module", "scripts": { "dev": "vite", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 94566c4..b42ae59 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2901,7 +2901,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "verve" -version = "0.1.0" +version = "0.2.0" dependencies = [ "auto-launch", "directories", @@ -2912,6 +2912,7 @@ dependencies = [ "strsim", "tauri", "tauri-build", + "window-vibrancy", ] [[package]] @@ -3053,6 +3054,18 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "window-vibrancy" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f762d9cc392fb85e6b1b5eed1ef13d73fed5149a5cbb017a7137497d14ef612" +dependencies = [ + "cocoa", + "objc", + "raw-window-handle", + "windows-sys", +] + [[package]] name = "windows" version = "0.32.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ad98aab..7aee6f5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "verve" -version = "0.1.0" +version = "0.2.0" description = "Verve is a lightweight and blazingly fast launcher for accessing and opening applications, files and documents." authors = ["jadhavparth99@gmail.com"] license = "GNU AFFERO GENERAL PUBLIC LICENSE" @@ -22,6 +22,7 @@ directories = "4.0.1" plist = "1" strsim = "0.10.0" auto-launch = "0.4.0" +window-vibrancy = "0.3.2" [features] # by default Tauri runs in production mode diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 5d91a95..1bf14ab 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -6,6 +6,7 @@ use util::utils::{ convert_all_app_icons_to_png, create_preferences_if_missing, get_icon, handle_input, launch_on_login, open_command, }; +use window_vibrancy::{apply_vibrancy, NSVisualEffectMaterial}; fn create_system_tray() -> SystemTray { let quit = CustomMenuItem::new("Quit".to_string(), "Quit"); @@ -32,31 +33,33 @@ fn main() { ]) .setup(|app| { app.set_activation_policy(tauri::ActivationPolicy::Accessory); - app.get_window("main").unwrap().hide().unwrap(); + let window = app.get_window("main").unwrap(); + #[cfg(target_os = "macos")] + apply_vibrancy(&window, NSVisualEffectMaterial::HudWindow, None, Some(10.0)) + .expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS"); + window.hide().unwrap(); Ok(()) }) .system_tray(create_system_tray()) .on_system_tray_event(|app, event| match event { - SystemTrayEvent::MenuItemClick { id, .. } => { - match id.as_str() { - "Hide" => { - let window = app.get_window("main").unwrap(); - window.hide().unwrap(); - } - "Show" => { - let window = app.get_window("main").unwrap(); - window.show().unwrap(); - } - "Preferences" => { - let window = app.get_window("main").unwrap(); - window.emit("PreferencesClicked", Some("Yes")).unwrap(); - } - "Quit" => { - std::process::exit(0); - } - _ => {} + SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() { + "Hide" => { + let window = app.get_window("main").unwrap(); + window.hide().unwrap(); } - } + "Show" => { + let window = app.get_window("main").unwrap(); + window.show().unwrap(); + } + "Preferences" => { + let window = app.get_window("main").unwrap(); + window.emit("PreferencesClicked", Some("Yes")).unwrap(); + } + "Quit" => { + std::process::exit(0); + } + _ => {} + }, _ => {} }) .run(tauri::generate_context!()) diff --git a/src-tauri/src/util.rs b/src-tauri/src/util.rs index f21f9c6..aabe582 100644 --- a/src-tauri/src/util.rs +++ b/src-tauri/src/util.rs @@ -14,6 +14,18 @@ pub(crate) mod utils { use std::time::Instant; use strsim::jaro_winkler; + #[derive(Serialize, Deserialize)] + struct Theme { + primary_bg_color: String, + secondary_bg_color: String, + primary_text_color: String, + secondary_text_color: String, + primary_accent_color: String, + secondary_accent_color: String, + highlight_overlay: String, + dark_overlay: String, + } + #[derive(Serialize, Deserialize)] struct Preferences { shortcut: String, @@ -94,6 +106,7 @@ pub(crate) mod utils { pub fn create_preferences_if_missing() { if let Some(proj_dirs) = ProjectDirs::from("com", "parth jadhav", "verve") { let preferences_path = proj_dirs.config_dir().join("preferences.json"); + let theme_path = proj_dirs.config_dir().join("theme.json"); if !preferences_path.exists() { let preference = Preferences { shortcut: String::from("Command+Shift+G"), @@ -101,9 +114,22 @@ pub(crate) mod utils { menu_bar_icon: true, }; let preference_text = serde_json::to_string(&preference).unwrap(); - println!("{}", preference_text); fs::write(preferences_path, &preference_text).unwrap(); } + if !theme_path.exists() { + let theme = Theme { + primary_bg_color: String::from("rgba(20, 20, 30, 0.6)"), + secondary_bg_color: String::from("rgba(84, 101, 115, 0.6)"), + primary_text_color: String::from("#FFFFFF"), + secondary_text_color: String::from("#878787"), + primary_accent_color: String::from("#556CE5"), + secondary_accent_color: String::from("#48A5FF"), + highlight_overlay: String::from("rgba(255, 255, 255, 0.1)"), + dark_overlay: String::from("rgba(0, 0, 0, 0.1)"), + }; + let theme_text = serde_json::to_string(&theme).unwrap(); + fs::write(theme_path, &theme_text).unwrap(); + } } } @@ -124,7 +150,12 @@ pub(crate) mod utils { }); } - fn search(input: &str, search_locations: Vec<&str>, extension: Option<&str>, depth: Option) -> Vec { + fn search( + input: &str, + search_locations: Vec<&str>, + extension: Option<&str>, + depth: Option, + ) -> Vec { let (location, more_locations) = search_locations.split_first().unwrap(); let mut result: Vec = SearchBuilder::default() .search_input(input) @@ -157,21 +188,18 @@ pub(crate) mod utils { ); similarity_sort(&mut result, input.as_str()); } else { - result = search( - input.trim_start_matches("/"), - vec![ - "/Users/" - ], - None, - Some(10000) - ); - println!("{:?}", result); + result = search( + input.trim_start_matches("/"), + vec!["/Users/"], + None, + Some(10000), + ); + println!("{:?}", result); } let time_taken = start_time.elapsed().as_secs_f32(); return (result, time_taken); } - #[tauri::command] pub fn get_icon(app_name: &str) -> String { if let Some(proj_dirs) = ProjectDirs::from("com", "parth jadhav", "verve") { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index d89b152..1307a17 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "verve", - "version": "0.1.0" + "version": "0.2.0" }, "tauri": { "systemTray": { diff --git a/src/main.ts b/src/main.ts index 47f10e5..329ba29 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,14 +14,30 @@ const app = new App({ target: document.getElementById("app"), }); -(async () => { - // get and set values - paths.set("appDataDirPath", await appDataDir()); - +const fetchPreferencesData = async () => { const preferencesData = await readTextFile(await join(paths.get("appDataDirPath"), `preferences.json`)).then((data) => JSON.parse(data)); Object.keys(preferencesData).forEach((key) => { preferences.set(key, preferencesData[key]); }); +} + +const reloadTheme = async () => { + const theme = await readTextFile(await join(paths.get("appDataDirPath"), `theme.json`)).then((data) => JSON.parse(data)); + // @ts-ignore + const style = document.styleSheets[0].cssRules[0].style; + style.setProperty("--primary-bg-color", theme.primary_bg_color); + style.setProperty("--secondary-bg-color", theme.secondary_bg_color); + style.setProperty("--primary-text-color", theme.primary_text_color); + style.setProperty("--secondary-text-color", theme.secondary_text_color); + style.setProperty("--primary-accent-color", theme.primary_accent_color); + style.setProperty("--secondary-accent-color", theme.secondary_accent_color); +} + +(async () => { + // get and set values + paths.set("appDataDirPath", await appDataDir()); + await fetchPreferencesData(); + await reloadTheme(); document.addEventListener("keydown", (event) => { if (event.key === "Escape") { diff --git a/src/routes/App/App.svelte b/src/routes/App/App.svelte index 2af46ae..0b2b138 100644 --- a/src/routes/App/App.svelte +++ b/src/routes/App/App.svelte @@ -15,11 +15,11 @@ let executionTime: number = 0; document.onkeyup = function (event) { - if (event.metaKey && event.key === ",") { - appState.app = false; - appState.settings = true; - } - }; + if (event.metaKey && event.key === ",") { + appState.app = false; + appState.settings = true; + } + }; const onBlur = async () => { await appWindow.hide(); @@ -73,19 +73,19 @@ }; - +
{#if appState.app} {#await appWindow.setSize(new LogicalSize(750, 100))}{/await} - +
{/if} {#if appState.settings} - {#await appWindow.setSize(new LogicalSize(750, 400))}{/await} + {#await appWindow.setSize(new LogicalSize(750, 352))}{/await} {/if}
@@ -94,7 +94,7 @@ .container { height: 100%; width: 750px; - background: var(--primary-bg-color); + background-color: var(--primary-bg-color); border-radius: 10px; } diff --git a/src/routes/App/lib/SearchBar.svelte b/src/routes/App/lib/SearchBar.svelte index 45f4ecd..f4595e8 100644 --- a/src/routes/App/lib/SearchBar.svelte +++ b/src/routes/App/lib/SearchBar.svelte @@ -27,9 +27,10 @@ width: 100%; height: 56px; border-radius: 8px 8px 0px 0px; - background: var(--secondary-bg-color); + background: var(--dark-overlay); padding-left: 16px; border: none; + border-bottom: 1px solid var(--highlight-overlay); font-family: Helvetica; font-style: normal; color: var(--primary-text-color); @@ -42,7 +43,7 @@ #searchBarForm { width: 733px; height: 56px; - background: var(--secondary-bg-color); + background: transparent; border-radius: 10px; border: none; } diff --git a/src/routes/App/lib/SearchResult.svelte b/src/routes/App/lib/SearchResult.svelte index 4304d16..3a0294d 100644 --- a/src/routes/App/lib/SearchResult.svelte +++ b/src/routes/App/lib/SearchResult.svelte @@ -5,6 +5,7 @@ import { convertFileSrc } from "@tauri-apps/api/tauri"; import { appWindow, LogicalSize } from "@tauri-apps/api/window"; import { afterUpdate } from "svelte"; + import { preferences } from "../../../cache.js"; afterUpdate(async () => { const height = document.getElementsByClassName("container")[0].clientHeight; @@ -16,9 +17,9 @@ }); async function getIcon(app_name: string) { - const fallbackIcon = convertFileSrc(await resolveResource( - "assets/default.svg" - )); + const fallbackIcon = convertFileSrc( + await resolveResource("assets/default.svg") + ); if ( [ "Migration Assistant", @@ -29,12 +30,14 @@ "AirPort Utility", ].includes(app_name) ) { - const icon_path = await resolveResource(`assets/appIcons/${app_name}.app.png`); - return {icon: convertFileSrc(icon_path), fallbackIcon}; + const icon_path = await resolveResource( + `assets/appIcons/${app_name}.app.png` + ); + return { icon: convertFileSrc(icon_path), fallbackIcon }; } const appDataDirPath = await appDataDir(); const filePath = await join(appDataDirPath, `appIcons/${app_name}.app.png`); - return {icon: convertFileSrc(filePath), fallbackIcon}; + return { icon: convertFileSrc(filePath), fallbackIcon }; } async function handleKeydown(event) { @@ -77,13 +80,19 @@ {#if results.length > 0 && results[0] !== " "} {#each results.slice(0, 5) as result} @@ -93,40 +102,40 @@ \ No newline at end of file + .appName { + font-family: Helvetica; + font-style: normal; + font-weight: 500; + font-size: 14px; + line-height: 20px; + margin: 0; + color: var(--primary-text-color); + } + diff --git a/src/routes/Settings/Settings.svelte b/src/routes/Settings/Settings.svelte index 381a22d..3eeb2b3 100644 --- a/src/routes/Settings/Settings.svelte +++ b/src/routes/Settings/Settings.svelte @@ -52,7 +52,7 @@ .Settings { position: relative; width: 100%; - height: 100%; + height: 352px; background: var(--primary-bg-color); border-radius: 10px; align-items: center; diff --git a/src/style.css b/src/style.css index e172263..9a76ae2 100644 --- a/src/style.css +++ b/src/style.css @@ -1,7 +1,9 @@ :root { font-family: Inter, Avenir, Helvetica, Arial, sans-serif; - --primary-bg-color: #141414; - --secondary-bg-color: #232323; + --primary-bg-color: rgba(20, 20, 30, 0.6); + --highlight-overlay: rgba(255, 255, 255, 0.1); + --dark-overlay: rgba(0, 0, 0, 0.1); + --secondary-bg-color: rgba(84, 101, 115, 0.6); --primary-text-color: #FFFFFF; --secondary-text-color: #878787; --primary-accent-color: #556CE5; @@ -23,6 +25,6 @@ body { .seperator { position: relative; width: 750px; - border: 1px solid var(--secondary-bg-color); + border: 1px solid var(--highlight-overlay); margin-bottom: 40px; } \ No newline at end of file