Skip to content

Commit

Permalink
Notification sound toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
AurevoirXavier committed Jul 17, 2024
1 parent 9b626ec commit ca05aee
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/component/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::setting::Chat;
use crate::widget::ComboBoxItem;

#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
#[serde(default, rename_all = "kebab-case")]
#[serde(rename_all = "kebab-case")]
pub enum Function {
Rewrite,
RewriteDirectly,
Expand Down
4 changes: 2 additions & 2 deletions src/component/setting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl Default for General {
font_size: 13.,
hide_on_lost_focus: true,
stick_to_top: Default::default(),
notification_sound: Default::default(),
notification_sound: true,
active_func: Default::default(),
}
}
Expand Down Expand Up @@ -201,7 +201,7 @@ pub struct Development {
}

#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")]
#[serde(rename_all = "kebab-case")]
pub enum LogLevel {
Trace,
Debug,
Expand Down
14 changes: 5 additions & 9 deletions src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,18 @@ use keyboard::Keyboard;
mod quoter;
use quoter::Quoter;

// std
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
// crates.io
use eframe::egui::Context;
use tokio::runtime::Runtime;
// self
use crate::{component::Components, prelude::*, state::State};
use crate::{component::Components, prelude::*, state::State, util::ArtBool};

#[derive(Debug)]
pub struct Services {
pub keyboard: Keyboard,
pub rt: Option<Runtime>,
pub quoter: Quoter,
pub is_chatting: Arc<AtomicBool>,
pub is_chatting: ArtBool,
pub chat: Chat,
pub audio: Audio,
pub hotkey: Hotkey,
Expand All @@ -39,7 +34,7 @@ impl Services {
let keyboard = Keyboard::new();
let rt = Runtime::new()?;
let quoter = Quoter::new(&rt, state.chat.quote.clone(), state.chat.input.clone());
let is_chatting = Arc::new(AtomicBool::new(false));
let is_chatting = ArtBool::new(false);
let chat = Chat::new(
keyboard.clone(),
&rt,
Expand All @@ -52,6 +47,7 @@ impl Services {
let hotkey = Hotkey::new(
ctx,
&components.setting.hotkeys,
state.general.notification_sound.clone(),
state.ui.focused_panel.clone(),
keyboard.clone(),
audio.clone(),
Expand All @@ -62,7 +58,7 @@ impl Services {
}

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

pub fn abort(&mut self) {
Expand Down
32 changes: 16 additions & 16 deletions src/service/chat.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// std
use std::{
sync::{
atomic::{AtomicBool, Ordering},
atomic::Ordering,
mpsc::{self, Sender},
Arc,
},
Expand All @@ -19,15 +19,15 @@ use crate::{
setting::{Ai, Chat as ChatSetting},
},
state::Chat as ChatState,
util,
util::{self, ArtBool},
};

pub type ChatArgs = (Function, String, bool);

#[derive(Debug)]
pub struct Chat {
pub tx: Sender<ChatArgs>,
to_interrupt: Arc<AtomicBool>,
to_interrupt: ArtBool,
// TODO?: get rid of the `Mutex`.
openai: Arc<Mutex<OpenAi>>,
chat_setting: Arc<Mutex<ChatSetting>>,
Expand All @@ -37,13 +37,13 @@ impl Chat {
pub fn new(
keyboard: Keyboard,
rt: &Runtime,
is_chatting: Arc<AtomicBool>,
is_chatting: ArtBool,
ai_setting: &Ai,
chat_setting: &ChatSetting,
state: &ChatState,
) -> Self {
let (tx, rx) = mpsc::channel();
let to_interrupt = Arc::new(AtomicBool::new(false));
let to_interrupt = ArtBool::new(false);
let to_interrupt_ = to_interrupt.clone();
let openai = Arc::new(Mutex::new(OpenAi::new(ai_setting.to_owned())));
let openai_ = openai.clone();
Expand All @@ -59,7 +59,7 @@ impl Chat {
'listen: loop {
let (func, content, type_in): ChatArgs = rx.recv().unwrap();

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

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

Expand All @@ -74,16 +74,16 @@ impl Chat {
.await,
"failed to create the chat stream",
) else {
is_chatting.store(false, Ordering::Relaxed);
error.store(true, Ordering::Relaxed);
is_chatting.store(false);
error.store(true);

continue;
};

while let Some(r) = stream.next().await {
if to_interrupt_.load(Ordering::Relaxed) {
to_interrupt_.store(false, Ordering::Relaxed);
is_chatting.store(false, Ordering::Relaxed);
if to_interrupt_.load() {
to_interrupt_.store(false);
is_chatting.store(false);

continue 'listen;
}
Expand All @@ -92,8 +92,8 @@ impl Chat {
r,
"failed to retrieve the next item from the stream",
) else {
is_chatting.store(false, Ordering::Relaxed);
error.store(true, Ordering::Relaxed);
is_chatting.store(false);
error.store(true);

continue 'listen;
};
Expand All @@ -116,8 +116,8 @@ impl Chat {
// Allow the UI a moment to refresh the content.
time::sleep(Duration::from_millis(50)).await;

is_chatting.store(false, Ordering::Relaxed);
error.store(false, Ordering::Relaxed);
is_chatting.store(false);
error.store(false);
}
})
.abort_handle();
Expand All @@ -130,7 +130,7 @@ impl Chat {
}

pub fn interrupt(&self) {
self.to_interrupt.store(true, Ordering::Relaxed);
self.to_interrupt.store(true);
}

pub fn renew(&self, ai_setting: &Ai, chat_setting: &ChatSetting) {
Expand Down
20 changes: 10 additions & 10 deletions src/service/hotkey.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
// std
use std::{
fmt::{Debug, Formatter, Result as FmtResult},
sync::{
atomic::{AtomicBool, Ordering},
mpsc::Sender,
Arc,
},
sync::{mpsc::Sender, Arc},
thread,
time::Duration,
};
Expand All @@ -20,18 +16,20 @@ use crate::{
component::{function::Function, keyboard::Keys, os::Os, setting::Hotkeys},
prelude::*,
ui::panel::Panel,
util::ArtBool,
};

pub struct Hotkey {
// The manager need to be kept alive during the whole program life.
_manager: GlobalHotKeyManager,
manager: Arc<RwLock<Manager>>,
abort: Arc<AtomicBool>,
abort: ArtBool,
}
impl Hotkey {
pub fn new(
ctx: &Context,
hotkeys: &Hotkeys,
notification_sound: ArtBool,
focused_panel: Arc<RwLock<Panel>>,
keyboard: Keyboard,
audio: Audio,
Expand All @@ -41,7 +39,7 @@ impl Hotkey {
let ctx = ctx.to_owned();
let manager = Arc::new(RwLock::new(Manager::new(&_manager, hotkeys)?));
let manager_ = manager.clone();
let abort = Arc::new(AtomicBool::new(false));
let abort = ArtBool::new(false);
let abort_ = abort.clone();
let hk_rx = GlobalHotKeyEvent::receiver();
let mut clipboard = Clipboard::new()?;
Expand All @@ -59,13 +57,15 @@ impl Hotkey {
Os::new()
};

while !abort_.load(Ordering::Relaxed) {
while !abort_.load() {
// Block the thread until a hotkey event is received.
let e = hk_rx.recv().unwrap();

// We don't care about the release event.
if let HotKeyState::Pressed = e.state {
audio.play_notification();
if notification_sound.load() {
audio.play_notification();
}

let (func, keys) = manager_.read().match_func(e.id);
let to_focus = !func.is_directly();
Expand Down Expand Up @@ -116,7 +116,7 @@ impl Hotkey {
}

pub fn abort(&self) {
self.abort.store(true, Ordering::Release);
self.abort.store(true);
}
}
impl Debug for Hotkey {
Expand Down
19 changes: 12 additions & 7 deletions src/state.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,43 @@
// std
use std::sync::{
atomic::{AtomicBool, AtomicU32},
Arc,
};
use std::sync::{atomic::AtomicU32, Arc};
// crates.io
use parking_lot::RwLock;
use tracing::Level;
use tracing_subscriber::{reload::Handle, EnvFilter, Registry};
// self
use crate::{component::setting::Setting, prelude::*, ui::panel::Panel};
use crate::{component::setting::Setting, prelude::*, ui::panel::Panel, util::ArtBool};

#[derive(Debug)]
pub struct State {
pub general: General,
pub chat: Chat,
pub development: Development,
pub ui: Ui,
}
impl State {
pub fn new(log_filter_handle: Handle<EnvFilter, Registry>, setting: &Setting) -> Result<Self> {
let general =
General { notification_sound: ArtBool::new(setting.general.notification_sound) };
let development = Development { log_filter_handle };

development.reload_log_filter(setting.development.log_level.into())?;

Ok(Self { chat: Default::default(), development, ui: Default::default() })
Ok(Self { general, chat: Default::default(), development, ui: Default::default() })
}
}

#[derive(Debug, Default)]
pub struct General {
pub notification_sound: ArtBool,
}

#[derive(Debug, Default)]
pub struct Chat {
pub quote: Arc<RwLock<String>>,
pub input: Arc<RwLock<String>>,
pub output: Arc<RwLock<String>>,
pub token_counts: Arc<(AtomicU32, AtomicU32)>,
pub error: Arc<AtomicBool>,
pub error: ArtBool,
}

#[derive(Debug)]
Expand Down
4 changes: 1 addition & 3 deletions src/ui/panel/chat.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// std
use std::sync::atomic::Ordering;
// crates.io
use eframe::egui::*;
// self
Expand Down Expand Up @@ -69,7 +67,7 @@ impl Chat {
ui.separator();
// Information.
ui.horizontal(|ui| {
let tip = if ctx.state.chat.error.load(Ordering::Relaxed) {
let tip = if ctx.state.chat.error.load() {
RichText::new(format!(
"An error occurred while connecting with \"{}\". Press CTRL/META+ENTER to retry.",
ctx.components.setting.ai.api_base
Expand Down
12 changes: 12 additions & 0 deletions src/ui/panel/setting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ impl Setting {
}
}

ui.end_row();
ui.label("Notification Sound");
if ui
.add(widget::toggle(&mut ctx.components.setting.general.notification_sound))
.changed()
{
ctx.state
.general
.notification_sound
.store(ctx.components.setting.general.notification_sound);
}

ui.end_row();
// TODO: move to a better place.
ui.add(widget::combo_box(
Expand Down
36 changes: 35 additions & 1 deletion src/util.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,42 @@
// std
use std::fmt::Debug;
use std::{
fmt::Debug,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
};
// crates.io
use eframe::egui::*;

macro_rules! impl_arts {
($($n:ident, $t:ty, $i:ty,)+) => {
$(
#[derive(Clone, Debug, Default)]
pub struct $n(pub Arc<$t>);
impl $n {
#[inline]
pub fn new(value: $i) -> Self {
Self(Arc::new(<$t>::new(value)))
}

#[inline]
pub fn load(&self) -> $i {
self.0.load(Ordering::Relaxed)
}

#[inline]
pub fn store(&self, value: $i) {
self.0.store(value, Ordering::Relaxed)
}
}
)+
};
}
impl_arts! {
ArtBool, AtomicBool, bool,
}

pub fn unwrap_or_tracing<T, E>(result: Result<T, E>, tracing_prefix: &str) -> Option<T>
where
E: Debug,
Expand Down

0 comments on commit ca05aee

Please sign in to comment.