Skip to content

Commit

Permalink
Allow control hide on lost focus
Browse files Browse the repository at this point in the history
  • Loading branch information
aurexav committed Jul 9, 2024
1 parent ffe9e9b commit 3058ad1
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 22 deletions.
6 changes: 4 additions & 2 deletions src/air.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl AiR {

let once = Once::new();
let components = Components::new()?;
let state = Default::default();
let state = State::new(&components.setting);
let services = Services::new(ctx, &components, &state)?;
let uis = Uis::new();

Expand Down Expand Up @@ -89,7 +89,9 @@ impl App for AiR {
}
// TODO: https://github.com/emilk/egui/issues/4468.
// Allow 1 second for initialization during the first boot.
else if raw_input.time.unwrap_or_default() >= 1. {
else if raw_input.time.unwrap_or_default() >= 1.
&& self.components.setting.general.hide_on_lost_focus
{
// TODO: https://github.com/emilk/egui/discussions/4635.
// We can get rid of the OS API if this works.
// ctx.send_viewport_cmd(ViewportCommand::Minimized(false));
Expand Down
1 change: 1 addition & 0 deletions src/component/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub enum Function {
RewriteDirectly,
Translate,
TranslateDirectly,
// TODO: refactor code.
}
impl Function {
pub fn basic(&self) -> Self {
Expand Down
12 changes: 6 additions & 6 deletions src/component/setting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ impl Rewrite {
const DEFAULT: &str = "As a language professor, assist me in refining text! \
Amend any grammatical errors and enhance the language to sound more like a native speaker! \
Text is always provided in format ```AiR\n$TEXT\n```! \
$TEXT can be provided in any style, such as programming code! \
Maintain the origin style but without the ```AiR\n\n``` surroundings! \
Return the refined $TEXT only!";
$TEXT can be provided in any style! \
Discard the ```AiR\n\n``` surroundings! \
Extract the $TEXT and return the refined $TEXT only!";

if self.additional_prompt.is_empty() {
DEFAULT.into()
Expand All @@ -122,9 +122,9 @@ impl Translation {
"As a language professor, assist me in translate text between {} and {}! \
Amend any grammatical errors and enhance the language to sound more like a native speaker! \
Text is always provided in format ```AiR\n$TEXT\n```! \
$TEXT can be provided in any style, such as programming code! \
Maintain the origin style but without the ```AiR\n\n``` surroundings! \
Return the translated $TEXT only!",
$TEXT can be provided in any style! \
Discard the ```AiR\n\n``` surroundings! \
Extract the $TEXT and return the translated $TEXT only!",
self.a.as_str(),
self.b.as_str(),
);
Expand Down
11 changes: 8 additions & 3 deletions src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,19 @@ impl Services {
let is_chatting = Arc::new(AtomicBool::new(false));
let chat =
Chat::new(keyboard.clone(), &rt, is_chatting.clone(), &components.setting, &state.chat);
let hotkey =
Hotkey::new(ctx, keyboard.clone(), &components.setting.hotkeys, chat.tx.clone())?;
let hotkey = Hotkey::new(
ctx,
keyboard.clone(),
&components.setting.hotkeys,
state.general.hide_on_lost_focus.clone(),
chat.tx.clone(),
)?;

Ok(Self { keyboard, rt: Some(rt), quoter, is_chatting, chat, hotkey })
}

pub fn is_chatting(&self) -> bool {
self.is_chatting.load(Ordering::SeqCst)
self.is_chatting.load(Ordering::Relaxed)
}

pub fn abort(&mut self) {
Expand Down
4 changes: 2 additions & 2 deletions src/service/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl Chat {
loop {
let (func, content, type_in): ChatArgs = rx.recv().unwrap();

is_chatting.store(true, Ordering::SeqCst);
is_chatting.store(true, Ordering::Relaxed);

tracing::info!("func: {func:?}");

Expand Down Expand Up @@ -80,7 +80,7 @@ impl Chat {
// Allow the UI a moment to refresh the content.
time::sleep(Duration::from_millis(50)).await;

is_chatting.store(false, Ordering::SeqCst);
is_chatting.store(false, Ordering::Relaxed);
}
})
.abort_handle();
Expand Down
9 changes: 5 additions & 4 deletions src/service/hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ impl Hotkey {
ctx: &Context,
keyboard: Keyboard,
hotkeys: &Hotkeys,
hide_on_lost_focus: Arc<AtomicBool>,
tx: Sender<ChatArgs>,
) -> Result<Self> {
let ctx = ctx.to_owned();
Expand All @@ -48,9 +49,9 @@ impl Hotkey {
// We don't care about the release event.
if let HotKeyState::Pressed = e.state {
let (func, keys) = manager.match_func(e.id);
let to_unhide = !func.is_directly();
let to_focus = !func.is_directly();

if to_unhide {
if to_focus && hide_on_lost_focus.load(Ordering::Relaxed) {
Os::unhide();
}

Expand All @@ -71,9 +72,9 @@ impl Hotkey {
_ => continue,
};

tx.send((func, content, !to_unhide)).expect("send must succeed");
tx.send((func, content, !to_focus)).expect("send must succeed");

if to_unhide {
if to_focus {
ctx.send_viewport_cmd(ViewportCommand::Focus);
}
}
Expand Down
28 changes: 25 additions & 3 deletions src/state.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
// std
use std::sync::Arc;
use std::sync::{atomic::AtomicBool, Arc};
// crates.io
use parking_lot::RwLock;
// self
use crate::component::setting::Setting;

#[derive(Debug, Default)]
#[derive(Debug)]
pub struct State {
pub general: General,
pub chat: Chat,
}
impl State {
pub fn new(setting: &Setting) -> Self {
Self {
general: General {
hide_on_lost_focus: Arc::new(AtomicBool::new(setting.general.hide_on_lost_focus)),
},
chat: Chat {
quote: Arc::new(RwLock::new(String::new())),
input: Arc::new(RwLock::new(String::new())),
output: Arc::new(RwLock::new(String::new())),
},
}
}
}

#[derive(Debug)]
pub struct General {
pub hide_on_lost_focus: Arc<AtomicBool>,
}

#[derive(Debug, Default)]
#[derive(Debug)]
pub struct Chat {
pub quote: Arc<RwLock<String>>,
pub input: Arc<RwLock<String>>,
Expand Down
45 changes: 43 additions & 2 deletions src/ui/panel/setting.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// std
use std::sync::atomic::Ordering;
// crates.io
use eframe::egui::*;
use eframe::egui::{self, *};
// self
use super::super::UiT;
use crate::{
Expand Down Expand Up @@ -41,7 +43,15 @@ impl UiT for Setting {
});
ui.end_row();

// TODO: `hide_on_lost_focus`.
ui.label("Hide on Lost Focus");
if ui.add(toggle(&mut ctx.components.setting.general.hide_on_lost_focus)).changed()
{
ctx.state.general.hide_on_lost_focus.store(
ctx.components.setting.general.hide_on_lost_focus,
Ordering::Relaxed,
);
};
ui.end_row();

ui.label("Active Function");
ComboBox::from_id_source("Active Function")
Expand Down Expand Up @@ -188,3 +198,34 @@ impl Default for ApiKeyWidget {
Self { label: "show".into(), visibility: true }
}
}

// https://github.com/emilk/egui/blob/aa96b257460a07b30489d104fae08d095a9e3a4e/crates/egui_demo_lib/src/demo/toggle_switch.rs#L109.
fn toggle(on: &mut bool) -> impl Widget + '_ {
fn toggle_ui(ui: &mut Ui, on: &mut bool) -> Response {
let desired_size = ui.spacing().interact_size.y * vec2(2.0, 1.0);
let (rect, mut response) = ui.allocate_exact_size(desired_size, Sense::click());

if response.clicked() {
*on = !*on;

response.mark_changed();
}
if ui.is_rect_visible(rect) {
let how_on = ui.ctx().animate_bool_responsive(response.id, *on);
let visuals = ui.style().interact_selectable(&response, *on);
let rect = rect.expand(visuals.expansion);
let radius = 0.5 * rect.height();

ui.painter().rect(rect, radius, visuals.bg_fill, visuals.bg_stroke);

let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
let center = egui::pos2(circle_x, rect.center().y);

ui.painter().circle(center, 0.75 * radius, visuals.bg_fill, visuals.fg_stroke);
}

response
}

move |ui: &mut Ui| toggle_ui(ui, on)
}

0 comments on commit 3058ad1

Please sign in to comment.