Skip to content

Commit

Permalink
Enable UI chat
Browse files Browse the repository at this point in the history
  • Loading branch information
AurevoirXavier committed Jul 8, 2024
1 parent e57d86c commit c94f68d
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 43 deletions.
35 changes: 34 additions & 1 deletion src/component/function.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
// std
use std::borrow::Cow;
// crates.io
use eframe::egui::WidgetText;
use serde::{Deserialize, Serialize};
// self
use super::setting::Chat;

#[derive(Debug)]
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum Function {
Rewrite,
RewriteDirectly,
Translate,
TranslateDirectly,
}
impl Function {
pub fn basic(&self) -> Self {
match self {
Self::Rewrite | Self::RewriteDirectly => Self::Rewrite,
Self::Translate | Self::TranslateDirectly => Self::Translate,
}
}

pub fn basic_all() -> [Self; 2] {
[Self::Rewrite, Self::Translate]
}

pub fn basic_as_str(&self) -> &'static str {
match self {
Self::Rewrite | Self::RewriteDirectly => "Rewrite",
Self::Translate | Self::TranslateDirectly => "Translate",
}
}

pub fn is_directly(&self) -> bool {
matches!(self, Self::RewriteDirectly | Self::TranslateDirectly)
}
Expand All @@ -22,3 +44,14 @@ impl Function {
}
}
}
impl Default for Function {
fn default() -> Self {
Self::Rewrite
}
}
#[allow(clippy::from_over_into)]
impl Into<WidgetText> for &Function {
fn into(self) -> WidgetText {
self.basic_as_str().into()
}
}
3 changes: 2 additions & 1 deletion src/component/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ impl FromStr for Keys {

fn key_of(key: char) -> Result<Key> {
// TODO: create a `CGKeyCode` table for macOS in `build.rs`.
// Currently, we only support limited keys on macOS.
// Currently, we only support limited keys on macOS from:
// https://eastmanreference.com/complete-list-of-applescript-key-codes.
#[cfg(target_os = "macos")]
let k = Key::Other(match key {
'A' => 0,
Expand Down
24 changes: 22 additions & 2 deletions src/component/setting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use std::{borrow::Cow, fs, path::PathBuf};
// crates.io
use app_dirs2::AppDataType;
use async_openai::config::OPENAI_API_BASE;
use eframe::egui::WidgetText;
use serde::{Deserialize, Serialize};
// self
use super::openai::Model;
use super::{function::Function, openai::Model};
use crate::{prelude::*, APP_INFO};

#[derive(Debug, Default, Serialize, Deserialize)]
Expand Down Expand Up @@ -53,10 +54,11 @@ impl Setting {
pub struct General {
pub font_size: f32,
pub hide_on_lost_focus: bool,
pub active_func: Function,
}
impl Default for General {
fn default() -> Self {
Self { font_size: 13., hide_on_lost_focus: true }
Self { font_size: 13., hide_on_lost_focus: true, active_func: Default::default() }
}
}

Expand Down Expand Up @@ -145,6 +147,24 @@ pub enum Language {
// English (United Kingdom).
EnGb,
}
impl Language {
pub fn as_str(&self) -> &'static str {
match self {
Self::ZhCn => "zh-CN",
Self::EnGb => "en-GB",
}
}

pub fn all() -> [Self; 2] {
[Self::ZhCn, Self::EnGb]
}
}
#[allow(clippy::from_over_into)]
impl Into<WidgetText> for &Language {
fn into(self) -> WidgetText {
self.as_str().into()
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// TODO: Some errors are not used since we use `.unwrap()`.
// TODO: check unused error types.

#[derive(Debug, thiserror::Error)]
pub enum Error {
Expand Down
1 change: 0 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! AI with Rust.

// TODO: check this.
// hide console window on Windows in release
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#![deny(
Expand Down
8 changes: 6 additions & 2 deletions src/service/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,16 @@ impl Chat {
Self { tx, openai, chat_setting, abort_handle }
}

pub fn abort(&self) {
self.abort_handle.abort();
pub fn send(&self, args: ChatArgs) {
self.tx.send(args).expect("send must succeed");
}

pub fn renew(&mut self, setting: &Setting) {
*self.openai.blocking_lock() = OpenAi::new(setting.ai.clone());
*self.chat_setting.blocking_lock() = setting.chat.clone();
}

pub fn abort(&self) {
self.abort_handle.abort();
}
}
6 changes: 3 additions & 3 deletions src/service/hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl Hotkey {
_ => continue,
};

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

if to_unhide {
ctx.send_viewport_cmd(ViewportCommand::Focus);
Expand All @@ -80,11 +80,11 @@ impl Hotkey {
Ok(Self(abort))
}

// TODO: fn renew.

pub fn abort(&self) {
self.0.store(true, Ordering::Release);
}

// TODO: fn renew.
}

struct Manager {
Expand Down
25 changes: 16 additions & 9 deletions src/ui/panel/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ pub struct Chat {
}
impl UiT for Chat {
fn draw(&mut self, ui: &mut Ui, ctx: &mut AiRContext) {
// TODO: other running cases.
let ic_chatting = ctx.services.is_chatting();
let is_chatting = ctx.services.is_chatting();
let size = ui.available_size();

ScrollArea::vertical().id_source("Input").max_height((size.y - 50.) / 2.).show(ui, |ui| {
let input = ui.add_sized(
(size.x, ui.available_height()),
TextEdit::multiline({
if ic_chatting {
if is_chatting {
if let Some(i) = ctx.state.chat.input.try_read() {
i.clone_into(&mut self.input);
}
Expand All @@ -45,9 +44,12 @@ impl UiT for Chat {
modifier && i.key_pressed(Key::Enter)
});

// TODO: send.
if to_send {
tracing::info!("to send");
ctx.services.chat.send((
ctx.components.setting.general.active_func.basic(),
self.input.clone(),
false,
));
}
}
});
Expand Down Expand Up @@ -79,11 +81,16 @@ impl UiT for Chat {
// Shortcuts.
ui.horizontal(|ui| {
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
if ic_chatting {
if is_chatting {
ui.spinner();
} else {
// TODO: retry.
if ui.add(self.shortcut.retry.clone()).clicked() {}
if ui.add(self.shortcut.retry.clone()).clicked() {
ctx.services.chat.send((
ctx.components.setting.general.active_func.basic(),
self.input.clone(),
false,
));
}
}
if !self.shortcut.copy.triggered {
if ui.add(self.shortcut.copy.copy_img.clone()).clicked() {
Expand All @@ -101,7 +108,7 @@ impl UiT for Chat {

ScrollArea::vertical().id_source("Output").show(ui, |ui| {
ui.label({
if ic_chatting {
if is_chatting {
if let Some(o) = ctx.state.chat.output.try_read() {
o.clone_into(&mut self.output);
}
Expand Down
43 changes: 20 additions & 23 deletions src/ui/panel/setting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use eframe::egui::*;
use super::super::UiT;
use crate::{
air::AiRContext,
component::{openai::Model, setting::Language},
component::{function::Function, openai::Model, setting::Language},
};

#[derive(Debug, Default)]
Expand Down Expand Up @@ -40,6 +40,22 @@ impl UiT for Setting {
}
});
ui.end_row();

// TODO: `hide_on_lost_focus`.

ui.label("Active Function");
ComboBox::from_id_source("Active Function")
.selected_text(&ctx.components.setting.general.active_func)
.show_ui(ui, |ui| {
Function::basic_all().iter().for_each(|f| {
ui.selectable_value(
&mut ctx.components.setting.general.active_func,
f.to_owned(),
f,
);
});
});
ui.end_row();
});
});

Expand Down Expand Up @@ -92,7 +108,7 @@ impl UiT for Setting {
.selectable_value(
&mut ctx.components.setting.ai.model,
m.to_owned(),
m.as_str(),
m,
)
.changed();
});
Expand Down Expand Up @@ -128,7 +144,7 @@ impl UiT for Setting {
ui.selectable_value(
&mut ctx.components.setting.chat.translation.a,
l.to_owned(),
l.as_str(),
l,
);
});
});
Expand All @@ -142,7 +158,7 @@ impl UiT for Setting {
ui.selectable_value(
&mut ctx.components.setting.chat.translation.b,
l.to_owned(),
l.as_str(),
l,
);
});
});
Expand Down Expand Up @@ -172,22 +188,3 @@ impl Default for ApiKeyWidget {
Self { label: "show".into(), visibility: true }
}
}

impl Language {
pub fn as_str(&self) -> &'static str {
match self {
Self::ZhCn => "zh-CN",
Self::EnGb => "en-GB",
}
}

fn all() -> [Self; 2] {
[Self::ZhCn, Self::EnGb]
}
}
#[allow(clippy::from_over_into)]
impl Into<WidgetText> for &Language {
fn into(self) -> WidgetText {
self.as_str().into()
}
}

0 comments on commit c94f68d

Please sign in to comment.