Skip to content

Commit

Permalink
Configuration Auto Reload (#376)
Browse files Browse the repository at this point in the history
- Update configuration to indicate which properties require a restart
- Update configuration GUI to not restart unless required
- Update server to provide updated configuration to all components
- Add global shortcut configuration

---------

Co-authored-by: Tago <joel@spyglass.fyi>
  • Loading branch information
travolin and Tago committed Mar 15, 2023
1 parent ad857d5 commit d2bbe85
Show file tree
Hide file tree
Showing 39 changed files with 654 additions and 199 deletions.
78 changes: 78 additions & 0 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions crates/client/public/fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,8 @@ export async function recrawl_domain(domain) {
return await invoke("recrawl_domain", { domain });
}

export async function save_user_settings(settings) {
return await invoke("save_user_settings", { settings });
export async function save_user_settings(settings, restart) {
return await invoke("save_user_settings", { settings, restart });
}

export async function searchDocs(lenses, query) {
Expand Down
4 changes: 2 additions & 2 deletions crates/client/public/glue.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export async function recrawl_domain(domain) {
return await invoke('recrawl_domain', { domain });
}

export async function save_user_settings(settings) {
return await invoke('save_user_settings', { settings: Object.fromEntries(settings) });
export async function save_user_settings(settings, restart) {
return await invoke('save_user_settings', { settings: Object.fromEntries(settings), restart });
}

export async function searchDocs(lenses, query) {
Expand Down
147 changes: 147 additions & 0 deletions crates/client/src/components/forms/keybinding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
use shared::{
accelerator,
keyboard::{KeyCode, ModifiersState},
};
use web_sys::HtmlInputElement;
use yew::prelude::*;

use crate::components::{KeyComponent, ModifierIcon};

use super::FormFieldProps;
use crate::components::forms::SettingChangeEvent;
use std::str::FromStr;

pub enum Msg {
HandleInput,
KeyDown(KeyboardEvent),
}

pub struct KeyBinding {
value: String,
node_ref: NodeRef,
}

impl Component for KeyBinding {
type Message = Msg;
type Properties = FormFieldProps;

fn create(ctx: &Context<Self>) -> Self {
let props = ctx.props();

Self {
value: props.value.clone(),
node_ref: NodeRef::default(),
}
}

fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
let props = ctx.props();

match msg {
Msg::HandleInput => {
if let Some(el) = self.node_ref.cast::<HtmlInputElement>() {
self.value = el.value();
props.onchange.emit(SettingChangeEvent {
setting_name: props.name.clone(),
new_value: self.value.clone(),
restart_required: props.restart_required,
});
}

true
}
Msg::KeyDown(evt) => {
if evt.alt_key() || evt.ctrl_key() || evt.meta_key() {
let mut val = String::from("");
if evt.meta_key() {
val.push_str("Cmd+");
}

if evt.ctrl_key() {
val.push_str("Ctrl+");
}

if evt.alt_key() {
val.push_str("Alt+");
}

if evt.shift_key() {
val.push_str("Shift+");
}

let mut modifier = ModifiersState::empty();
modifier.set(ModifiersState::ALT, evt.alt_key());
modifier.set(ModifiersState::CONTROL, evt.ctrl_key());
modifier.set(ModifiersState::SHIFT, evt.shift_key());
modifier.set(ModifiersState::SUPER, evt.meta_key());

if let Ok(key) = KeyCode::from_str(evt.key().to_uppercase().as_str()) {
match key {
KeyCode::Unidentified(_) => {
if let Ok(key) =
KeyCode::from_str(evt.code().to_uppercase().as_str())
{
match key {
KeyCode::Unidentified(_) => (),
_ => {
val.push_str(key.to_str());
evt.prevent_default();
}
}
}
}
_ => {
val.push_str(key.to_str());
}
}
}

self.value = val;

props.onchange.emit(SettingChangeEvent {
setting_name: props.name.clone(),
new_value: self.value.clone(),
restart_required: props.restart_required,
});
}
true
}
}
}

fn view(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();

let key_binding = if let Ok(acc) = accelerator::parse_accelerator(
self.value.as_str(),
crate::utils::get_os().to_string().as_str(),
) {
html! {
<>
<ModifierIcon modifier={acc.mods}></ModifierIcon>
<KeyComponent>{acc.key.to_str()}</KeyComponent>
</>
}
} else {
html! {
<KeyComponent>{"Invalid"}</KeyComponent>
}
};

html! {
<div class="w-full flex flex-row items-center gap-1">
<input
ref={self.node_ref.clone()}
spellcheck="false"
oninput={link.callback(|_| Msg::HandleInput)}
onkeydown={link.callback(Msg::KeyDown)}
value={self.value.clone()}
type="text"
class="grow form-input w-full text-sm rounded bg-stone-700 border-stone-800"
/>

{key_binding}
</div>
}
}
}
21 changes: 21 additions & 0 deletions crates/client/src/components/forms/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use yew::prelude::*;

use shared::form::{FormType, SettingOpts};

mod keybinding;
mod pathlist;
mod stringlist;
mod text;
Expand All @@ -12,16 +13,20 @@ pub use stringlist::*;
pub use text::*;
pub use toggle::*;

use crate::components::forms::keybinding::KeyBinding;

#[derive(Clone)]
pub struct SettingChangeEvent {
pub setting_name: String,
pub new_value: String,
pub restart_required: bool,
}

#[derive(Properties, PartialEq)]
pub struct FormFieldProps {
pub name: String,
pub value: String,
pub restart_required: bool,
pub onchange: Callback<SettingChangeEvent>,
}

Expand Down Expand Up @@ -60,6 +65,7 @@ impl FormElement {
<Toggle
name={props.setting_name.clone()}
value={self.opts.value.clone()}
restart_required={props.opts.restart_required}
onchange={Callback::from(move |evt| onchange.emit(evt))}
/>
}
Expand All @@ -69,6 +75,7 @@ impl FormElement {
<Text
name={props.setting_name.clone()}
value={self.opts.value.clone()}
restart_required={props.opts.restart_required}
onchange={Callback::from(move |evt| onchange.emit(evt))}
/>
}
Expand All @@ -78,6 +85,7 @@ impl FormElement {
<PathField
name={props.setting_name.clone()}
value={self.opts.value.clone()}
restart_required={props.opts.restart_required}
onchange={Callback::from(move |evt| onchange.emit(evt))}
/>
}
Expand All @@ -87,6 +95,7 @@ impl FormElement {
<PathList
name={props.setting_name.clone()}
value={self.opts.value.clone()}
restart_required={props.opts.restart_required}
onchange={Callback::from(move |evt| onchange.emit(evt))}
/>
}
Expand All @@ -96,6 +105,7 @@ impl FormElement {
<StringList
name={props.setting_name.clone()}
value={self.opts.value.clone()}
restart_required={props.opts.restart_required}
onchange={Callback::from(move |evt| onchange.emit(evt))}
/>
}
Expand All @@ -105,6 +115,17 @@ impl FormElement {
<Text
name={props.setting_name.clone()}
value={self.opts.value.clone()}
restart_required={props.opts.restart_required}
onchange={Callback::from(move |evt| onchange.emit(evt))}
/>
}
}
FormType::KeyBinding => {
html! {
<KeyBinding
name={props.setting_name.clone()}
value={self.opts.value.clone()}
restart_required={props.opts.restart_required}
onchange={Callback::from(move |evt| onchange.emit(evt))}
/>
}
Expand Down
Loading

0 comments on commit d2bbe85

Please sign in to comment.