Skip to content

Commit

Permalink
More configuration options (#58)
Browse files Browse the repository at this point in the history
* feat(dataans): make `always-on-top` configurable;

* feat(dataans): make `hide-window-decorations` configurable;

* feat(dataans): make `hide-taskbar-icon` configurable;

* feat(dataans): regenerate space avatar image using keybinding;

* feat(front): select space right after its creation;

* refactor(front): fix clippy warning;
  • Loading branch information
TheBestTvarynka authored Nov 2, 2024
1 parent 1011b7b commit 7b7ee20
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 29 deletions.
28 changes: 28 additions & 0 deletions dataans/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ pub struct KeyBindings {
/// Find note in the selected space.
#[serde(default = "find_note_in_selected_space")]
pub find_note_in_selected_space: String,
/// Regenerate space avatar image.
#[serde(default = "regenerate_space_avatar")]
pub regenerate_space_avatar: String,
}

fn regenerate_space_avatar() -> String {
"ControlLeft+keyR".into()
}

fn find_note_in_selected_space() -> String {
Expand Down Expand Up @@ -122,6 +129,27 @@ pub struct App {
/// App toggle: show/hide app.
#[serde(default = "app_toggle")]
pub app_toggle: String,
/// Always on top.
#[serde(default = "always_on_top")]
pub always_on_top: bool,
/// Hide app window decorations.
#[serde(default = "hide_window_decorations")]
pub hide_window_decorations: bool,
/// Hide app icon on taskbar.
#[serde(default = "hide_taskbar_icon")]
pub hide_taskbar_icon: bool,
}

fn hide_taskbar_icon() -> bool {
false
}

fn hide_window_decorations() -> bool {
false
}

fn always_on_top() -> bool {
false
}

fn app_toggle() -> String {
Expand Down
6 changes: 6 additions & 0 deletions dataans/common/src/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ impl Id {
}
}

impl AsRef<Uuid> for Id {
fn as_ref(&self) -> &Uuid {
&self.0
}
}

impl From<Uuid> for Id {
fn from(value: Uuid) -> Self {
Self(value)
Expand Down
7 changes: 6 additions & 1 deletion dataans/src-tauri/resources/configs/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ delete-current-space = "ControlLeft+Delete"
select-prev-list-item = "AltLeft+Digit1"
select-next-list-item = "AltLeft+Digit2"
find-note = "ControlLeft+keyF"
find-note-in-selected-space = "ControlLeft+keyM"
regenerate-space-avatar = "ControlLeft+keyR"

[appearance]
theme = "theme_dark.toml"

[app]
app-toggle = "F2"
app-toggle = "F2"
always-on-top = false
hide-window-decorations = false
hide-taskbar-icon = false
31 changes: 28 additions & 3 deletions dataans/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const LOGS_DIR: &str = "logs";

fn toggle_app_visibility(app: &AppHandle) -> Result<()> {
if let Some(window) = app.get_webview_window(MAIN_WINDOW_NAME) {
if window.is_visible().unwrap_or(true) {
if window.is_visible().unwrap_or(false) {
info!("Hide main window");
window.hide()?;
} else {
Expand Down Expand Up @@ -126,9 +126,10 @@ fn main() {
warn!("Cannot find the 'main' try icon :(");
}

let config = crate::config::load_config_inner(app.handle());

// Set up global shortcut
let app_toggle = crate::config::load_config_inner(app.handle()).app.app_toggle;
let visibility_shortcut = Shortcut::from_str(&app_toggle).unwrap();
let visibility_shortcut = Shortcut::from_str(&config.app.app_toggle).unwrap();
debug!(?visibility_shortcut);

app.handle().plugin(
Expand All @@ -152,6 +153,30 @@ fn main() {

app.global_shortcut().register(visibility_shortcut)?;

if config.app.always_on_top {
if let Some(window) = app.handle().get_webview_window(MAIN_WINDOW_NAME) {
window.set_always_on_top(true)?;
} else {
error!("{MAIN_WINDOW_NAME} window not found! Cannot set 'always-on-top'.");
}
}

if config.app.hide_window_decorations {
if let Some(window) = app.handle().get_webview_window(MAIN_WINDOW_NAME) {
window.set_decorations(false)?;
} else {
error!("{MAIN_WINDOW_NAME} window not found! Cannot set 'hide-window-decorations'.");
}
}

if config.app.hide_taskbar_icon {
if let Some(window) = app.handle().get_webview_window(MAIN_WINDOW_NAME) {
window.set_skip_taskbar(true)?;
} else {
error!("{MAIN_WINDOW_NAME} window not found! Cannot set 'hide-taskbar-icon'.");
}
}

Ok(())
})
.on_window_event(|window, event| {
Expand Down
3 changes: 1 addition & 2 deletions dataans/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
"x": 0,
"y": 0,
"closable": true,
"maximized": true,
"alwaysOnTop": false
"maximized": true
}
],
"security": {
Expand Down
12 changes: 8 additions & 4 deletions dataans/src/notes/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub fn Info(
set_spaces: SignalSetter<Vec<OwnedSpace>>,
delete_state_space: SignalSetter<SpaceId>,
#[prop(into)] toggle_note_search: Callback<(), ()>,
#[prop(into)] set_selected_space: Callback<OwnedSpace, ()>,
config: Config,
) -> impl IntoView {
let (show_edit_modal, set_show_edit_modal) = create_signal(false);
Expand All @@ -30,17 +31,17 @@ pub fn Info(

let current_space_name = current_space.name.to_string();

let key_bindings = config.key_bindings;
let key_bindings = &config.key_bindings;

use_hotkeys!((key_bindings.edit_current_space) => move |_| {
use_hotkeys!((key_bindings.edit_current_space.clone()) => move |_| {
set_show_edit_modal.set(true);
});

use_hotkeys!((key_bindings.delete_current_space) => move |_| {
use_hotkeys!((key_bindings.delete_current_space.clone()) => move |_| {
set_show_delete_modal.set(true);
});

use_hotkeys!((key_bindings.find_note_in_selected_space) => move |_| toggle_note_search.call(()));
use_hotkeys!((key_bindings.find_note_in_selected_space.clone()) => move |_| toggle_note_search.call(()));

let space = Some(current_space.clone());

Expand Down Expand Up @@ -81,12 +82,15 @@ pub fn Info(
</Show>
<Show when=move || show_edit_modal.get()>{
let space = space.clone();
let config = config.clone();
view! {
<Modal>
<SpaceForm
space
on_cancel=move |_| set_show_edit_modal.set(false)
set_spaces
set_selected_space
config
/>
</Modal>
}
Expand Down
17 changes: 15 additions & 2 deletions dataans/src/notes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod note;
pub mod note_preview;

use common::note::UpdateNote;
use common::space::Space as SpaceData;
use common::space::{OwnedSpace, Space as SpaceData};
use common::Config;
use leptos::*;
use wasm_bindgen::JsCast;
Expand All @@ -23,7 +23,11 @@ use crate::FindNoteMode;
pub fn Notes(config: Config) -> impl IntoView {
let global_state = expect_context::<RwSignal<GlobalState>>();

let (current_space, _) = create_slice(global_state, |state| state.selected_space.clone(), |_, _: ()| ());
let (current_space, set_selected_space_s) = create_slice(
global_state,
|state| state.selected_space.clone(),
|state, space| state.selected_space = Some(space),
);

let (_, set_spaces) = create_slice(
global_state,
Expand Down Expand Up @@ -59,6 +63,14 @@ pub fn Notes(config: Config) -> impl IntoView {
|state, notes| state.notes = notes,
);

let set_selected_space = move |space: OwnedSpace| {
let space_id = space.id;
set_selected_space_s.set(space);
spawn_local(async move {
set_notes.set(list_notes(space_id).await.expect("Notes listing should not fail"));
});
};

let (_, delete_note) = create_slice(
global_state,
|_state| (),
Expand Down Expand Up @@ -124,6 +136,7 @@ pub fn Notes(config: Config) -> impl IntoView {
});
focus_element(SEARCH_NOTE_INPUT_ID);
}
set_selected_space
config=config.clone()
/>
</Show>
Expand Down
28 changes: 26 additions & 2 deletions dataans/src/spaces/app_info/app_info_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ pub fn AppInfoWindow(#[prop(into)] close: Callback<(), ()>) -> impl IntoView {
{move || {
let Config { key_bindings, appearance, app } = global_config.get();

let KeyBindings { toggle_spaces_bar, create_space, edit_current_space, delete_current_space, select_next_list_item, select_prev_list_item, find_note, find_note_in_selected_space } = key_bindings;
let KeyBindings { toggle_spaces_bar, create_space, edit_current_space, delete_current_space, select_next_list_item, select_prev_list_item, find_note, find_note_in_selected_space, regenerate_space_avatar } = key_bindings;
let Appearance { theme } = appearance;
let App { app_toggle } = app;
let App { app_toggle, always_on_top, hide_window_decorations, hide_taskbar_icon } = app;

view!{
<table class="app-window-config-table">
Expand All @@ -58,6 +58,24 @@ pub fn AppInfoWindow(#[prop(into)] close: Callback<(), ()>) -> impl IntoView {
<span class="inline-code">{app_toggle}</span>
</td>
</tr>
<tr>
<td>"Always on top"</td>
<td>
<span class="inline-code">{always_on_top}</span>
</td>
</tr>
<tr>
<td>"Hide window decorations"</td>
<td>
<span class="inline-code">{hide_window_decorations}</span>
</td>
</tr>
<tr>
<td>"Hide app taskbar icon"</td>
<td>
<span class="inline-code">{hide_taskbar_icon}</span>
</td>
</tr>

// Appearance config
<tr>
Expand Down Expand Up @@ -129,6 +147,12 @@ pub fn AppInfoWindow(#[prop(into)] close: Callback<(), ()>) -> impl IntoView {
<span class="inline-code">{find_note_in_selected_space}</span>
</td>
</tr>
<tr>
<td>"Regenerate space avatar image"</td>
<td>
<span class="inline-code">{regenerate_space_avatar}</span>
</td>
</tr>
</table>
}
}}
Expand Down
2 changes: 1 addition & 1 deletion dataans/src/spaces/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub fn Spaces(

view! {
<div class="spaces-container">
<Tools set_spaces spaces_minimized set_spaces_minimized set_find_node_mode set_query=set_query.into() config=config.clone() />
<Tools set_spaces spaces_minimized set_spaces_minimized set_find_node_mode set_query=set_query.into() set_selected_space config=config.clone() />
{move || match find_note_mode.get() {
FindNoteMode::None => view!{
<SpacesList config=config.clone() selected_space spaces spaces_minimized set_selected_space />
Expand Down
25 changes: 21 additions & 4 deletions dataans/src/spaces/space_form.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use common::space::{OwnedSpace, Space, UpdateSpace};
use common::Config;
use leptos::*;
use leptos_hotkeys::use_hotkeys;
use leptos_hotkeys::{use_hotkeys, use_hotkeys_scoped};
use time::OffsetDateTime;
use uuid::Uuid;

Expand All @@ -14,6 +15,8 @@ pub fn SpaceForm(
space: Option<OwnedSpace>,
#[prop(into)] on_cancel: Callback<(), ()>,
set_spaces: SignalSetter<Vec<OwnedSpace>>,
set_selected_space: Callback<OwnedSpace, ()>,
config: Config,
) -> impl IntoView {
let (space_name, set_space_name) = create_signal(space.as_ref().map(|s| s.name.to_string()).unwrap_or_default());
let (avatar_path, set_avatar_path) = create_signal(
Expand Down Expand Up @@ -55,26 +58,40 @@ pub fn SpaceForm(
})
.await
.expect("Space updating should not fail");

None
} else {
let new_space_id = Uuid::new_v4();
create_space(Space {
id: Uuid::new_v4().into(),
id: new_space_id.into(),
name: name.into(),
created_at: OffsetDateTime::now_utc().into(),
avatar: avatar.into(),
})
.await
.expect("Space creation should not fail");

Some(new_space_id)
}
};

spawn_local(async move {
action.await;
set_spaces.set(list_spaces().await.expect("list spaces should not fail"));
let new_space_id = action.await;
let spaces = list_spaces().await.expect("list spaces should not fail");
let new_current_space = new_space_id
.and_then(|new_space_id| spaces.iter().find(|space| *space.id.as_ref() == new_space_id).cloned());

set_spaces.set(spaces);
if let Some(space) = new_current_space {
set_selected_space.call(space);
}
});
};

use_hotkeys!(("Escape") => move |_| on_cancel.call(()));
use_hotkeys!(("Enter") => move |_| create_space());
let regenerate_space_avatar = config.key_bindings.regenerate_space_avatar.clone();
use_hotkeys!((regenerate_space_avatar) => move |_| generate_avatar());

view! {
<div class="create-space-window" on:load=move |_| info!("on_load")>
Expand Down
Loading

0 comments on commit 7b7ee20

Please sign in to comment.