Skip to content

Commit

Permalink
Optimize combo box implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
AurevoirXavier committed Jul 9, 2024
1 parent 323734e commit 5d38249
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 139 deletions.
4 changes: 2 additions & 2 deletions src/component/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ impl Audio {
Ok(Audio { notification, sink, _stream })
}

pub fn play(&self, audio_src: Source) {
self.sink.append(audio_src);
pub fn play_notification(&self) {
self.sink.append(self.notification.clone());
self.sink.sleep_until_end();
}
}
Expand Down
31 changes: 15 additions & 16 deletions src/component/function.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// std
use std::borrow::Cow;
// crates.io
use eframe::egui::WidgetText;
use serde::{Deserialize, Serialize};
// self
use super::setting::Chat;
use crate::widget::ComboBoxItem;

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
Expand All @@ -23,17 +23,6 @@ impl Function {
}
}

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 @@ -50,9 +39,19 @@ impl Default for Function {
Self::Rewrite
}
}
#[allow(clippy::from_over_into)]
impl Into<WidgetText> for &Function {
fn into(self) -> WidgetText {
self.basic_as_str().into()
impl ComboBoxItem for Function {
type Array = [Self; Self::COUNT];

const COUNT: usize = 2;

fn all() -> Self::Array {
[Self::Rewrite, Self::Translate]
}

fn as_str(&self) -> &'static str {
match self {
Self::Rewrite | Self::RewriteDirectly => "Rewrite",
Self::Translate | Self::TranslateDirectly => "Translate",
}
}
}
34 changes: 16 additions & 18 deletions src/component/openai.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ use async_openai::{
},
Client,
};
use eframe::egui::WidgetText;
use serde::{Deserialize, Serialize};
// self
use super::setting::Ai;
use crate::prelude::*;
use crate::{prelude::*, widget::ComboBoxItem};

#[derive(Debug)]
pub struct OpenAi {
Expand Down Expand Up @@ -59,35 +58,34 @@ pub enum Model {
Gpt35Turbo,
}
impl Model {
pub const MODEL_URI: &'static str = "https://platform.openai.com/docs/models";
// pub const MODEL_URI: &'static str = "https://platform.openai.com/docs/models";
pub const PRICE_URI: &'static str = "https://openai.com/pricing";

pub fn as_str(&self) -> &'static str {
match self {
Self::Gpt4o => "gpt-4o",
Self::Gpt35Turbo => "gpt-3.5-turbo",
}
}

pub fn prices(&self) -> (f32, f32) {
match self {
Self::Gpt4o => (0.000005, 0.000015),
Self::Gpt35Turbo => (0.0000005, 0.0000015),
}
}

pub fn all() -> [Self; 2] {
[Self::Gpt4o, Self::Gpt35Turbo]
}
}
impl Default for Model {
fn default() -> Self {
Self::Gpt4o
}
}
#[allow(clippy::from_over_into)]
impl Into<WidgetText> for &Model {
fn into(self) -> WidgetText {
self.as_str().into()
impl ComboBoxItem for Model {
type Array = [Self; Self::COUNT];

const COUNT: usize = 2;

fn all() -> Self::Array {
[Self::Gpt4o, Self::Gpt35Turbo]
}

fn as_str(&self) -> &'static str {
match self {
Self::Gpt4o => "gpt-4o",
Self::Gpt35Turbo => "gpt-3.5-turbo",
}
}
}
1 change: 1 addition & 0 deletions src/component/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use serde::Deserialize;
use super::net::{Http, Response, HTTP_CLIENT};
use crate::prelude::*;

// TODO?: actually, we could request this from AI.
#[derive(Debug)]
pub struct Quoter;
impl Quoter {
Expand Down
25 changes: 11 additions & 14 deletions src/component/setting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +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::{function::Function, openai::Model};
use crate::{prelude::*, APP_INFO};
use crate::{prelude::*, widget::ComboBoxItem, APP_INFO};

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
Expand Down Expand Up @@ -153,23 +152,21 @@ pub enum Language {
// English (United Kingdom).
EnGb,
}
impl Language {
pub fn as_str(&self) -> &'static str {
impl ComboBoxItem for Language {
type Array = [Self; Self::COUNT];

const COUNT: usize = 2;

fn all() -> Self::Array {
[Self::ZhCn, Self::EnGb]
}

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)]
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod os;
mod service;
mod state;
mod ui;
mod widget;

mod prelude {
pub type Result<T, E = Error> = std::result::Result<T, E>;
Expand Down
2 changes: 1 addition & 1 deletion src/service/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl Audio {

loop {
match rx.recv().expect("receive must succeed") {
Effect::Notification => audio.play(audio.notification.clone()),
Effect::Notification => audio.play_notification(),
Effect::Abort => return,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/service/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl Keyboard {
loop {
let act = rx.recv().expect("receive must succeed");

tracing::info!("receive action: {act:?}");
tracing::debug!("receive action: {act:?}");

match act {
Action::Copy => kb.copy().expect("keyboard action must succeed"),
Expand Down
102 changes: 15 additions & 87 deletions src/ui/panel/setting.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
// std
use std::sync::atomic::Ordering;
// crates.io
use eframe::egui::{self, *};
use eframe::egui::*;
// self
use super::super::UiT;
use crate::{
air::AiRContext,
component::{function::Function, openai::Model, setting::Language},
};
use crate::{air::AiRContext, widget};

#[derive(Debug, Default)]
pub struct Setting {
Expand Down Expand Up @@ -44,7 +41,9 @@ impl UiT for Setting {
ui.end_row();

ui.label("Hide on Lost Focus");
if ui.add(toggle(&mut ctx.components.setting.general.hide_on_lost_focus)).changed()
if ui
.add(widget::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,
Expand All @@ -53,18 +52,10 @@ impl UiT for Setting {
};
ui.end_row();

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.add(widget::combo_box(
"Active Function",
&mut ctx.components.setting.general.active_func,
));
ui.end_row();
});
});
Expand Down Expand Up @@ -109,20 +100,9 @@ impl UiT for Setting {
ui.end_row();

// TODO: we might not need to renew the client if only the model changed.
ui.label("Model");
ComboBox::from_id_source("Model")
.selected_text(&ctx.components.setting.ai.model)
.show_ui(ui, |ui| {
Model::all().iter().for_each(|m| {
changed |= ui
.selectable_value(
&mut ctx.components.setting.ai.model,
m.to_owned(),
m,
)
.changed();
});
});
changed |= ui
.add(widget::combo_box("Model", &mut ctx.components.setting.ai.model))
.changed();
ui.end_row();

// TODO: we might not need to renew the client if only the temperature changed.
Expand All @@ -146,32 +126,11 @@ impl UiT for Setting {
// TODO: [`crate::component::setting::Chat`].
ui.collapsing("Translation", |ui| {
Grid::new("Translation").num_columns(2).striped(true).show(ui, |ui| {
ui.label("A");
ComboBox::from_id_source("A")
.selected_text(&ctx.components.setting.chat.translation.a)
.show_ui(ui, |ui| {
Language::all().iter().for_each(|l| {
ui.selectable_value(
&mut ctx.components.setting.chat.translation.a,
l.to_owned(),
l,
);
});
});
// TODO: A and B should be mutually exclusive.
ui.add(widget::combo_box("A", &mut ctx.components.setting.chat.translation.a));
ui.end_row();

ui.label("B");
ComboBox::from_id_source("B")
.selected_text(&ctx.components.setting.chat.translation.b)
.show_ui(ui, |ui| {
Language::all().iter().for_each(|l| {
ui.selectable_value(
&mut ctx.components.setting.chat.translation.b,
l.to_owned(),
l,
);
});
});
ui.add(widget::combo_box("B", &mut ctx.components.setting.chat.translation.b));
ui.end_row();
});
});
Expand All @@ -198,34 +157,3 @@ 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)
}
Loading

0 comments on commit 5d38249

Please sign in to comment.