generated from hack-ink/rust-initializer
-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
26d9023
commit 80c0be5
Showing
13 changed files
with
409 additions
and
330 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Lately, I've been, I've been losing sleep. Dreaming about the things that we could be. But baby, I've been, I've been praying hard. Said no more counting dollars, we'll be counting stars. Yeah, we'll be counting stars. I see this life, like a swinging vine. Swing my heart across the line. And in my face is flashing signs. Seek it out and ye' shall find. Old, but I'm not that old. Young, but I'm not that bold. And I don't think the world is sold. On just doing what we're told. I feel something so right doing the wrong thing. I feel something so wrong doing the right thing. I couldn't lie, couldn't lie, couldn't lie. Everything that kills me makes me feel alive. Lately, I've been, I've been losing sleep. Dreaming about the things that we could be. But baby, I've been, I've been praying hard. Said no more counting dollars, we'll be counting stars. Lately, I've been, I've been losing sleep. Dreaming about the things that we could be. But baby, I've been, I've been praying hard. Said no more counting dollars, we'll be, we'll be counting stars. I feel your love and I feel it burn. Down this river, every turn. Hope is our four-letter word. Make that money, watch it burn. Old, but I'm not that old. Young, but I'm not that bold. And I don't think the world is sold. On just doing what we're told. I feel something so wrong doing the right thing. I couldn't lie, couldn't lie, couldn't lie. Everything that drowns me makes me wanna fly. Lately, I've been, I've been losing sleep. Dreaming about the things that we could be. But baby, I've been, I've been praying hard. Said no more counting dollars, we'll be counting stars. Lately, I've been, I've been losing sleep. Dreaming about the things that we could be. But baby, I've been, I've been praying hard. Said no more counting dollars, we'll be, we'll be counting stars. Take that money, watch it burn. Sink in the river the lessons I learned. Take that money, watch it burn. Sink in the river the lessons I learned. Take that money, watch it burn. Sink in the river the lessons I learned. Take that money, watch it burn. Sink in the river the lessons I learned. Everything that kills me makes me feel alive. Lately, I've been, I've been losing sleep. Dreaming about the things that we could be. But baby, I've been, I've been praying hard. Said no more counting dollars, we'll be counting stars. Lately, I've been, I've been losing sleep. Dreaming about the things that we could be. But baby, I've been, I've been praying hard. Said no more counting dollars, we'll be, we'll be counting stars. Take that money, watch it burn. Sink in the river the lessons I've learned. Take that money, watch it burn. Sink in the river the lessons I've learned. Take that money, watch it burn. Sink in the river the lessons I've learned. Take that money, watch it burn. Sink in the river the lessons I've learned. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,187 +1,109 @@ | ||
// std | ||
use std::sync::atomic::Ordering; | ||
// crates.io | ||
use eframe::egui::*; | ||
// self | ||
use super::super::UiT; | ||
use crate::{air::AiRContext, component::openai::Model, util, widget}; | ||
use crate::{air::AiRContext, widget::SMALL_FONT_OFFSET}; | ||
|
||
#[derive(Debug, Default)] | ||
#[cfg_attr(not(feature = "dev"), derive(Default))] | ||
#[derive(Debug)] | ||
pub struct Chat { | ||
input: String, | ||
output: String, | ||
shortcut: ShortcutWidget, | ||
pub input: String, | ||
pub output: String, | ||
} | ||
impl UiT for Chat { | ||
fn draw(&mut self, ui: &mut Ui, ctx: &mut AiRContext) { | ||
let dark_mode = ui.visuals().dark_mode; | ||
let size = ui.available_size(); | ||
let is_chatting = ctx.services.is_chatting(); | ||
|
||
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 is_chatting { | ||
if let Some(i) = ctx.state.chat.input.try_read() { | ||
i.clone_into(&mut self.input); | ||
} | ||
} | ||
impl Chat { | ||
pub fn draw(&mut self, ctx: &mut AiRContext, ui: &mut Ui, bar_height: f32) { | ||
let size = ui.min_rect().size(); | ||
let h = size.y - bar_height * 2.; | ||
let separator_h = ui.spacing().item_spacing.y * 2.; | ||
// TODO: this isn't really the height. | ||
let shortcut_h = ctx.components.setting.general.font_size; | ||
let scroll_h = (h - separator_h - shortcut_h) / 2.; | ||
// let scroll_h = (h - shortcut_h) / 2.; | ||
|
||
&mut self.input | ||
}) | ||
.hint_text(&*ctx.state.chat.quote.read()), | ||
); | ||
// dbg!(size.y, h, shortcut_h, scroll_h); | ||
|
||
if input.has_focus() { | ||
self.shortcut.copy.triggered = false; | ||
let dark_mode = ui.visuals().dark_mode; | ||
let is_chatting = ctx.services.is_chatting(); | ||
|
||
let to_send = input.ctx.input(|i| { | ||
let modifier = if cfg!(target_os = "macos") { | ||
i.modifiers.mac_cmd | ||
} else { | ||
i.modifiers.ctrl | ||
}; | ||
// Input. | ||
ui.vertical(|ui| { | ||
ui.set_height(scroll_h); | ||
|
||
modifier && i.key_pressed(Key::Enter) | ||
}); | ||
ScrollArea::vertical().id_source("Input").show(ui, |ui| { | ||
let input = ui.add_sized( | ||
(size.x, scroll_h), | ||
TextEdit::multiline({ | ||
if is_chatting { | ||
if let Some(i) = ctx.state.chat.input.try_read() { | ||
i.clone_into(&mut self.input); | ||
} | ||
} | ||
|
||
if to_send { | ||
ctx.services.chat.send(( | ||
ctx.components.setting.general.active_func.basic(), | ||
self.input.clone(), | ||
false, | ||
)); | ||
} | ||
} | ||
}); | ||
&mut self.input | ||
}) | ||
.hint_text(&*ctx.state.chat.quote.read()), | ||
); | ||
|
||
// Indicators. | ||
ui.horizontal(|ui| { | ||
ui.with_layout(Layout::right_to_left(Align::Center), |ui| { | ||
ui.vertical(|ui| { | ||
ui.add_space(4.5); | ||
ui.with_layout(Layout::right_to_left(Align::Center), |ui| { | ||
let tcs = &ctx.state.chat.token_counts; | ||
let (itc, otc) = | ||
(tcs.0.load(Ordering::Relaxed), tcs.1.load(Ordering::Relaxed)); | ||
let (ip, op) = ctx.components.setting.ai.model.prices(); | ||
if input.has_focus() { | ||
let to_send = input.ctx.input(|i| { | ||
let modifier = if cfg!(target_os = "macos") { | ||
i.modifiers.mac_cmd | ||
} else { | ||
i.modifiers.ctrl | ||
}; | ||
|
||
ui.hyperlink_to(format!( | ||
"input: {itc} output: {otc} price: ${:.6}", | ||
util::price_rounded(itc as f32 * ip + otc as f32 * op) | ||
),Model::PRICE_URI).on_hover_text("The token indicator might not work if you are using a custom API provider."); | ||
modifier && i.key_pressed(Key::Enter) | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
ui.separator(); | ||
|
||
// Shortcuts. | ||
ui.horizontal(|ui| { | ||
ui.with_layout(Layout::right_to_left(Align::Center), |ui| { | ||
if is_chatting { | ||
ui.spinner(); | ||
} else { | ||
// TODO: change retry to send. | ||
// TODO: the state will not be synced if previous action is triggered by hotkey. | ||
if ui.add(self.shortcut.retry.img(dark_mode)).clicked() { | ||
if to_send { | ||
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(dark_mode)).clicked() { | ||
self.shortcut.copy.triggered = true; | ||
ctx.components | ||
.clipboard | ||
.set_text(&self.output) | ||
.expect("clipboard must be available"); | ||
} | ||
} else { | ||
ui.add(self.shortcut.copy.copied_img(dark_mode)); | ||
} | ||
}); | ||
}); | ||
ui.separator(); | ||
// Information. | ||
ui.horizontal(|ui| { | ||
let tip = RichText::new(if is_chatting { | ||
"Thinking" | ||
} else { | ||
"Press CTRL/CMD+Enter to Send" | ||
}) | ||
.color(if dark_mode { Color32::GOLD } else { Color32::BROWN }); | ||
|
||
ScrollArea::vertical().id_source("Output").show(ui, |ui| { | ||
ui.label({ | ||
ui.set_height(shortcut_h); | ||
ui.with_layout(Layout::centered_and_justified(Direction::LeftToRight), |ui| { | ||
ui.label(tip.size(ctx.components.setting.general.font_size - SMALL_FONT_OFFSET)); | ||
}); | ||
}); | ||
ui.separator(); | ||
// Output. | ||
ui.vertical(|ui| { | ||
ui.set_height(scroll_h); | ||
|
||
ScrollArea::vertical().id_source("Output").show(ui, |ui| { | ||
if is_chatting { | ||
if let Some(o) = ctx.state.chat.output.try_read() { | ||
o.clone_into(&mut self.output); | ||
} | ||
} | ||
|
||
&self.output | ||
// Read-only trick. | ||
let mut output = self.output.as_str(); | ||
|
||
ui.add_sized((size.x, scroll_h), TextEdit::multiline(&mut output)); | ||
}); | ||
}); | ||
} | ||
} | ||
|
||
#[derive(Debug, Default)] | ||
struct ShortcutWidget { | ||
copy: CopyWidget, | ||
retry: RetryWidget, | ||
} | ||
#[derive(Debug)] | ||
struct CopyWidget { | ||
copy_img_l: Image<'static>, | ||
copy_img_d: Image<'static>, | ||
copied_img_l: Image<'static>, | ||
copied_img_d: Image<'static>, | ||
triggered: bool, | ||
} | ||
impl CopyWidget { | ||
fn copy_img(&self, dark_mode: bool) -> Image<'static> { | ||
if dark_mode { | ||
self.copy_img_d.clone() | ||
} else { | ||
self.copy_img_l.clone() | ||
} | ||
} | ||
|
||
fn copied_img(&self, dark_mode: bool) -> Image<'static> { | ||
if dark_mode { | ||
self.copied_img_d.clone() | ||
} else { | ||
self.copied_img_l.clone() | ||
} | ||
} | ||
} | ||
impl Default for CopyWidget { | ||
fn default() -> Self { | ||
Self { | ||
copy_img_d: widget::image_button(include_image!("../../../asset/copy-dark.svg")), | ||
copy_img_l: widget::image_button(include_image!("../../../asset/copy-light.svg")), | ||
copied_img_d: widget::image_button(include_image!("../../../asset/copied-dark.svg")), | ||
copied_img_l: widget::image_button(include_image!("../../../asset/copied-light.svg")), | ||
triggered: false, | ||
} | ||
} | ||
} | ||
#[derive(Debug)] | ||
struct RetryWidget { | ||
retry_img_d: Image<'static>, | ||
retry_img_l: Image<'static>, | ||
} | ||
impl RetryWidget { | ||
fn img(&self, dark_mode: bool) -> Image<'static> { | ||
if dark_mode { | ||
self.retry_img_d.clone() | ||
} else { | ||
self.retry_img_l.clone() | ||
} | ||
} | ||
} | ||
impl Default for RetryWidget { | ||
#[cfg(feature = "dev")] | ||
impl Default for Chat { | ||
fn default() -> Self { | ||
Self { | ||
retry_img_d: widget::image_button(include_image!("../../../asset/retry-dark.svg")), | ||
retry_img_l: widget::image_button(include_image!("../../../asset/retry-light.svg")), | ||
} | ||
const TEXT: &str = include_str!("../../../dev/text.txt"); | ||
|
||
Self { input: TEXT.into(), output: TEXT.into() } | ||
} | ||
} |
Oops, something went wrong.