Skip to content

Commit

Permalink
Get ready for refactoring hotkey
Browse files Browse the repository at this point in the history
  • Loading branch information
AurevoirXavier committed Jul 6, 2024
1 parent 961ca89 commit ec1a79b
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 328 deletions.
498 changes: 225 additions & 273 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ app_dirs2 = { version = "2.5" }
arboard = { version = "3.4" }
async-openai = { version = "0.23" }
color-eyre = { version = "0.6" }
eframe = { version = "0.27", features = ["persistence"] }
egui_commonmark = { version = "0.16" }
egui_extras = { version = "0.27", features = ["svg"] }
eframe = { version = "0.28", features = ["persistence"] }
egui_extras = { version = "0.28", features = ["svg"] }
enigo = { version = "0.2" }
futures = { version = "0.3" }
global-hotkey = { version = "0.5" }
Expand Down
18 changes: 10 additions & 8 deletions src/air.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// TODO: use unwrap here and return result in other places.

// std
use std::sync::Once;
// crates.io
Expand All @@ -18,16 +16,19 @@ struct AiR {
uis: Uis,
}
impl AiR {
fn init(ctx: Context) -> Self {
Self::set_fonts(&ctx);
fn init(ctx: &Context) -> Result<Self> {
Self::set_fonts(ctx);

// To enable SVG.
egui_extras::install_image_loaders(ctx);

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

Self { once, components, state, services, uis }
Ok(Self { once, components, state, services, uis })
}

fn set_fonts(ctx: &Context) {
Expand Down Expand Up @@ -82,6 +83,7 @@ impl App for AiR {
if focused {
// This must be called on the main thread and after the window fully get
// initialized.
//
// If possible find a place to call this only once.
self.once.call_once(Os::set_move_to_active_space);
}
Expand Down Expand Up @@ -128,7 +130,7 @@ pub fn launch() -> Result<()> {
.with_transparent(true),
..Default::default()
},
Box::new(|c| Box::new(AiR::init(c.egui_ctx.clone()))),
Box::new(|c| Ok(Box::new(AiR::init(&c.egui_ctx).unwrap()))),
)?;

Ok(())
Expand Down
10 changes: 7 additions & 3 deletions src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,26 @@ use crate::prelude::*;
#[derive(Debug)]
pub struct Components {
pub setting: Setting,
pub openai: Arc<Mutex<OpenAi>>,
#[cfg(feature = "tokenizer")]
pub tokenizer: Tokenizer,
pub openai: Arc<Mutex<OpenAi>>,
}
impl Components {
pub fn init() -> Result<Self> {
let setting = Setting::load()?;

// TODO: https://github.com/emilk/egui/discussions/4670.
debug_assert_eq!(setting.ai.temperature, setting.ai.temperature * 10. / 10.);

let openai = Arc::new(Mutex::new(OpenAi::new(setting.ai.clone())));
#[cfg(feature = "tokenizer")]
let tokenizer = Tokenizer::new(setting.ai.model.as_str());
let openai = Arc::new(Mutex::new(OpenAi::new(setting.ai.clone())));

Ok(Self {
setting,
openai,
#[cfg(feature = "tokenizer")]
tokenizer,
openai,
})
}

Expand Down
4 changes: 2 additions & 2 deletions src/component/openai.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl OpenAi {
];
let req = CreateChatCompletionRequestArgs::default()
.model(self.setting.model.as_str())
.temperature(self.setting.temperature_rounded())
.temperature(self.setting.temperature)
.max_tokens(4_096_u16)
.messages(&msg)
.build()?;
Expand All @@ -51,7 +51,7 @@ impl OpenAi {
}
}

// https://platform.openai.com/docs/models
// https://platform.openai.com/docs/models.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Model {
Gpt4o,
Expand Down
18 changes: 13 additions & 5 deletions src/component/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use crate::prelude::*;
#[derive(Debug)]
pub struct Quoter;
impl Quoter {
// const API: &'static str = "https://api.quotable.io/random";
const API: &'static str = "https://zenquotes.io/api/random";
pub const DEFAULT: &'static str = r#" -----------
< Thinking... >
-----------
Expand All @@ -19,15 +21,21 @@ impl Quoter {
pub async fn fetch(&self) -> Result<String> {
tracing::info!("fetching quote");

let b = HTTP_CLIENT.get_with_reties("https://api.quotable.io/random", 3, 500).await?;
let q = b.json::<Quote>()?;
let b = HTTP_CLIENT.get_with_reties(Self::API, 3, 500).await?;
// let q = b.json::<Quote>()?;
let q = b.json::<[Quote; 1]>()?;

Ok(format!("{}\n\n{}", q.content, q.author))
// Ok(format!("{}\n\n{}", q.content, q.author))
Ok(format!("{}\n\n{}", q[0].q, q[0].a))
}
}

#[derive(Debug, Deserialize)]
// struct Quote {
// author: String,
// content: String,
// }
struct Quote {
author: String,
content: String,
q: String,
a: String,
}
5 changes: 0 additions & 5 deletions src/component/setting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ pub struct Ai {
pub model: Model,
pub temperature: f32,
}
impl Ai {
pub fn temperature_rounded(&self) -> f32 {
(self.temperature * 10.).round() / 10.
}
}
impl Default for Ai {
fn default() -> Self {
Self {
Expand Down
3 changes: 0 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ mod prelude {
pub use crate::error::*;
}

// Only used for enable the svg support.
use egui_extras as _;

// std
use std::panic;
// crates.io
Expand Down
13 changes: 8 additions & 5 deletions src/service/hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ impl Hotkey {
let is_running_ = is_running.clone();
let receiver = GlobalHotKeyEvent::receiver();
let ctx = ctx.to_owned();
let openai = components.openai.to_owned();
let input = state.chat.input.to_owned();
let output = state.chat.output.to_owned();
let translation = state.setting.translation.to_owned();
let openai = components.openai.clone();
let input = state.chat.input.clone();
let output = state.chat.output.clone();
let translation = state.setting.translation.clone();
let abort_handle = rt
.spawn(async move {
// The manager need to be kept alive during the whole program life.
Expand Down Expand Up @@ -85,7 +85,7 @@ impl Hotkey {
if to_get_selected_text {
// Sleep for a while to reset the keyboard state after user
// triggers the hotkey.
time::sleep(Duration::from_millis(200)).await;
time::sleep(Duration::from_millis(1000)).await;
task::spawn_blocking(move || {
// TODO: handle the error.
Keyboard::init().unwrap().copy().unwrap();
Expand All @@ -94,6 +94,9 @@ impl Hotkey {
.unwrap();
}
if to_unhide {
// Generally, this needs some time to wait the window available
// first, but the previous sleep in `to_get_selected_text`is
// enough.
ctx.send_viewport_cmd(ViewportCommand::Focus);
}

Expand Down
10 changes: 5 additions & 5 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ impl Uis {
}

pub fn draw(&mut self, mut ctx: AiRContext) {
CentralPanel::default().frame(util::transparent_frame(ctx.egui_ctx)).show(
ctx.egui_ctx,
|ui| {
CentralPanel::default()
// FIXME: it looks like there some invalid cache.
.frame(util::transparent_frame(ctx.egui_ctx))
.show(ctx.egui_ctx, |ui| {
ui.horizontal(|ui| {
ui.selectable_value(&mut self.focused_panel, Panel::Chat, Panel::Chat.name());
ui.separator();
Expand All @@ -43,7 +44,6 @@ impl Uis {
Panel::Chat => self.chat.draw(ui, &mut ctx),
Panel::Setting => self.setting.draw(ui, &mut ctx),
}
},
);
});
}
}
27 changes: 11 additions & 16 deletions src/ui/panel/chat.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
// crates.io
use eframe::egui::*;
use egui_commonmark::*;
// self
use super::super::UiT;
use crate::air::AiRContext;
#[cfg(feature = "tokenizer")] use crate::component::util;

#[derive(Debug, Default)]
pub struct Chat {
// TODO: use widgets instead.
pub input: String,
pub output: String,
pub shortcut: ShortcutWidget,
pub output: OutputWidget,
}
impl UiT for Chat {
fn draw(&mut self, ui: &mut Ui, ctx: &mut AiRContext) {
Expand Down Expand Up @@ -63,7 +61,7 @@ impl UiT for Chat {
// ui.add_space(4.5);
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
let (ic, oc) =
ctx.components.tokenizer.count_token(&self.input, &self.output.value);
ctx.components.tokenizer.count_token(&self.input, &self.output);
let (ip, op) = ctx.components.setting.ai.model.prices();

ui.label(format!(
Expand Down Expand Up @@ -97,14 +95,17 @@ impl UiT for Chat {
});
});

CommonMarkViewer::new("Output").show_scrollable(ui, &mut Default::default(), {
if is_running {
if let Ok(o) = ctx.state.chat.output.try_read() {
o.clone_into(&mut self.output.value);
ScrollArea::vertical().id_source("Output").show(ui, |ui| {
ui.label({
// FIXME: `is_running` is conflict with `try_read`.
if is_running {
if let Ok(o) = ctx.state.chat.output.try_read() {
o.clone_into(&mut self.output);
}
}
}

&self.output.value
&self.output
});
});
}
}
Expand Down Expand Up @@ -143,9 +144,3 @@ impl Default for CopyWidget {
}
}
}

#[derive(Debug, Default)]
pub struct OutputWidget {
cache: CommonMarkCache,
value: String,
}

0 comments on commit ec1a79b

Please sign in to comment.