Skip to content

Commit

Permalink
feat: add "Edit" system tray option for linking directly to widget co…
Browse files Browse the repository at this point in the history
…nfig form (#163)
  • Loading branch information
lars-berger authored Nov 27, 2024
1 parent 13a25c5 commit 901c6b6
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/desktop/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ tauri-build = { version = "2.0", features = [] }
[dependencies]
anyhow = "1"
async-trait = "0.1"
base64 = "0.22"
clap = { version = "4", features = ["derive"] }
crossbeam = "0.8"
reqwest = { version = "0.11", features = ["json"] }
Expand Down
57 changes: 50 additions & 7 deletions packages/desktop/src/sys_tray.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{collections::HashMap, path::PathBuf, str::FromStr, sync::Arc};

use anyhow::{bail, Context};
use base64::prelude::*;
use tauri::{
image::Image,
menu::{CheckMenuItem, Menu, MenuBuilder, Submenu, SubmenuBuilder},
Expand All @@ -25,6 +26,9 @@ enum MenuEvent {
ReloadConfigs,
OpenSettings,
Exit,
EditWidget {
path: PathBuf,
},
ToggleWidgetPreset {
enable: bool,
preset: String,
Expand All @@ -44,6 +48,9 @@ impl ToString for MenuEvent {
MenuEvent::ReloadConfigs => "reload_configs".to_string(),
MenuEvent::OpenSettings => "open_settings".to_string(),
MenuEvent::Exit => "exit".to_string(),
MenuEvent::EditWidget { path } => {
format!("edit_widget_{}", path.to_unicode_string())
}
MenuEvent::ToggleWidgetPreset {
enable,
preset,
Expand Down Expand Up @@ -83,6 +90,9 @@ impl FromStr for MenuEvent {
["reload", "configs"] => Ok(Self::ReloadConfigs),
["open", "settings"] => Ok(Self::OpenSettings),
["exit"] => Ok(Self::Exit),
["edit", "widget", path @ ..] => Ok(Self::EditWidget {
path: PathBuf::from(path.join("_")),
}),
["toggle", "widget", "config", enable @ ("true" | "false"), preset, path @ ..] => {
Ok(Self::ToggleWidgetPreset {
enable: *enable == "true",
Expand Down Expand Up @@ -278,11 +288,16 @@ impl SysTray {
.open_config_dir()
.context("Failed to open config folder."),
MenuEvent::ReloadConfigs => config.reload().await,
MenuEvent::OpenSettings => Self::open_settings_window(&app_handle),
MenuEvent::OpenSettings => {
Self::open_settings_window(&app_handle, None)
}
MenuEvent::Exit => {
app_handle.exit(0);
Ok(())
}
MenuEvent::EditWidget { path } => {
Self::open_settings_window(&app_handle, Some(&path))
}
MenuEvent::ToggleWidgetPreset {
enable,
path,
Expand Down Expand Up @@ -311,28 +326,50 @@ impl SysTray {
});
}

fn open_settings_window(app_handle: &AppHandle) -> anyhow::Result<()> {
fn open_settings_window(
app_handle: &AppHandle,
config_path: Option<&PathBuf>,
) -> anyhow::Result<()> {
// Get existing settings window if it's already open.
let settings_window = app_handle.get_webview_window("settings");

let route = match config_path {
None => "/index.html".to_string(),
Some(path) => {
format!(
"/index.html#/widget/{}",
BASE64_STANDARD.encode(path.to_unicode_string())
)
}
};

match &settings_window {
None => {
WebviewWindowBuilder::new(
app_handle,
"settings",
WebviewUrl::default(),
WebviewUrl::App(route.into()),
)
.title("Settings - Zebar")
.focused(true)
.visible(true)
.inner_size(900., 600.)
.build()
.context("Failed to build the settings window.")?;

Ok(())
}
Some(window) => window
.set_focus()
.context("Failed to focus the settings window."),
Some(window) => {
window
.eval(&format!("location.replace('{}')", route))
.context("Failed to navigate to widget edit page.")?;

window
.set_focus()
.context("Failed to focus the settings window.")?;

Ok(())
}
}
}

Expand Down Expand Up @@ -379,7 +416,13 @@ impl SysTray {
}
};

let mut presets_menu = SubmenuBuilder::new(&self.app_handle, label);
let mut presets_menu = SubmenuBuilder::new(&self.app_handle, label)
.text(
MenuEvent::EditWidget {
path: config_path.clone(),
},
"Edit",
);

// Add each widget config to the menu.
for preset in &widget_config.presets {
Expand Down
18 changes: 15 additions & 3 deletions packages/settings-ui/src/configs/WidgetConfigs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from '@glzr/components';
import { useParams } from '@solidjs/router';
import { IconChevronDown } from '@tabler/icons-solidjs';
import { invoke } from '@tauri-apps/api/core';
import { listen, type Event } from '@tauri-apps/api/event';
Expand All @@ -24,6 +25,8 @@ import { WidgetConfigSidebar } from './WidgetConfigSidebar';
import { WidgetConfigForm } from './WidgetConfigForm';

export function WidgetConfigs() {
const params = useParams();

const [configs, { mutate: mutateWidgetConfigs }] = createResource(
async () => invoke<Record<string, WidgetConfig>>('widget_configs'),
{ initialValue: {} },
Expand All @@ -34,11 +37,9 @@ export function WidgetConfigs() {
{ initialValue: {} },
);

createEffect(() => console.log('widgetStates', widgetStates()));

const [selectedConfigPath, setSelectedConfigPath] = createSignal<
string | null
>(null);
>(params.path ? atob(params.path) : null);

const [selectedPreset, setSelectedPreset] = createSignal<string | null>(
null,
Expand Down Expand Up @@ -84,6 +85,17 @@ export function WidgetConfigs() {
});
});

// Update selected config path when params change. This occurs when
// "Edit" is selected from the system tray menu.
createEffect(
on(
() => params.path,
() => {
setSelectedConfigPath(params.path ? atob(params.path) : null);
},
),
);

// Select the first config alphabetically on initial load.
createEffect(
on(
Expand Down
7 changes: 4 additions & 3 deletions packages/settings-ui/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
/* @refresh reload */
import './index.css';
import { Route, Router } from '@solidjs/router';
import { HashRouter, Route } from '@solidjs/router';
import { render } from 'solid-js/web';

import { WidgetConfigs } from './configs/WidgetConfigs';

render(
() => (
<Router>
<HashRouter>
<Route path="/" component={WidgetConfigs} />
</Router>
<Route path="/widget/:path" component={WidgetConfigs} />
</HashRouter>
),
document.getElementById('root')!,
);

0 comments on commit 901c6b6

Please sign in to comment.