More UI stuff

This commit is contained in:
MrLetsplay 2024-02-07 22:02:11 +01:00
parent d90151ee5f
commit 47e17e4d42
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg

View File

@ -1,8 +1,12 @@
mod api;
use std::{
cell::RefCell,
io::{self, Write},
sync::Arc,
sync::{
mpsc::{Receiver, Sender},
Arc,
},
};
use api::OllamaAPI;
@ -10,15 +14,13 @@ use iced::{
alignment::{Horizontal, Vertical},
futures::StreamExt,
widget::{button, column, container, row, scrollable, text, text_input},
window::{self},
Application, Command, Length, Settings, Theme,
window, Application, Command, Length, Settings, Subscription, Theme,
};
use tokio::sync::RwLock;
use crate::api::OllamaChat;
enum UI {
Loading,
Error(String),
Chats(UIState),
}
@ -28,15 +30,23 @@ struct UIState {
active_chat: Option<usize>,
chat_input: String,
busy: bool,
send: Sender<UIMessage>,
recv: RefCell<Option<Receiver<UIMessage>>>,
}
impl UIState {
fn create(api_url: &str) -> anyhow::Result<Self> {
fn create(
api_url: &str,
send: Sender<UIMessage>,
recv: Receiver<UIMessage>,
) -> anyhow::Result<Self> {
Ok(Self {
ollama_api: Arc::new(RwLock::new(OllamaAPI::create(api_url)?)),
active_chat: None,
chat_input: String::from(""),
busy: false,
send,
recv: RefCell::new(Some(recv)),
})
}
}
@ -44,7 +54,6 @@ impl UIState {
#[derive(Debug, Clone)]
enum UIMessage {
Nop,
LoadDone,
CreateChat,
OpenChat(usize),
ChatInput(String),
@ -55,42 +64,39 @@ enum UIMessage {
fn main() -> anyhow::Result<()> {
println!("Making request");
UI::run(Settings {
window: window::Settings {
size: (720, 480),
..window::Settings::default()
},
..Settings::default()
})?;
let (send, recv) = std::sync::mpsc::channel();
let mut settings = Settings::with_flags(UIFlags { send, recv });
settings.window = window::Settings {
size: (720, 480),
..window::Settings::default()
};
UI::run(settings)?;
Ok(())
}
struct UIFlags {
send: Sender<UIMessage>,
recv: Receiver<UIMessage>,
}
impl Application for UI {
type Executor = iced::executor::Default;
type Message = UIMessage;
type Theme = Theme;
type Flags = ();
type Flags = UIFlags;
fn new(_flags: Self::Flags) -> (Self, iced::Command<Self::Message>) {
(
UI::Loading,
Command::perform(
async {
/*let api = OllamaAPI::create("http://localhost:11434").unwrap();
let mut chat = api.create_chat("dolphin-mixtral");
chat.send_system("You are a bot that only replies with \"Hello\" and nothing else. You must never reply with anything other than \"Hello\"");
chat.send_user("Who are you?");
// println!("{}", amogus.get().await?);
fn new(flags: Self::Flags) -> (Self, iced::Command<Self::Message>) {
let state: UI;
let state_result = UIState::create("http://localhost:11434", flags.send, flags.recv);
if let Ok(s) = state_result {
state = UI::Chats(s);
} else {
state = UI::Error(String::from("Failed to initialize Ollama API"));
}
let mut a = chat.complete().await.unwrap();
while let Some(v) = a.next().await {
println!("GOT = {:?}", v);
}*/
},
|_| UIMessage::LoadDone,
),
)
(state, Command::none())
}
fn title(&self) -> String {
@ -99,18 +105,6 @@ impl Application for UI {
fn update(&mut self, message: Self::Message) -> iced::Command<Self::Message> {
match self {
UI::Loading => match message {
UIMessage::LoadDone => {
let state = UIState::create("http://localhost:11434");
if let Ok(state) = state {
*self = UI::Chats(state);
} else {
*self = UI::Error(String::from("Failed to initialize Ollama API"));
}
Command::none()
}
_ => Command::none(),
},
UI::Chats(state) => match message {
UIMessage::CreateChat => {
let chat = state
@ -139,6 +133,7 @@ impl Application for UI {
let content = state.chat_input.clone();
state.chat_input = String::from("");
state.busy = true;
let send = state.send.clone();
let ollama_api = state.ollama_api.clone();
return Command::perform(
async move {
@ -150,6 +145,8 @@ impl Application for UI {
chat = api.chats[index].clone();
let mut chat = chat.write().await;
chat.send_user(&content);
chat.current_message =
Some(Arc::new(RwLock::new(String::from(""))));
}
//let mut chat = chat.write().await;
@ -164,18 +161,17 @@ impl Application for UI {
let content = content.unwrap();
let chat = chat.clone();
let mut chat = chat.write().await;
let chat_arc = chat.clone();
let chat = chat_arc.read().await;
let msg = chat.current_message.clone();
if let Some(msg) = msg {
msg.write().await.push_str(&content);
} else {
chat.current_message =
Some(Arc::new(RwLock::new(String::from(&content))));
}
print!("{}", content);
let _ = io::stdout().flush();
let _ = send.send(UIMessage::Nop);
}
}
//state.ollama_api.complete(&x);
@ -198,12 +194,6 @@ impl Application for UI {
fn view(&self) -> iced::Element<'_, Self::Message, iced::Renderer<Self::Theme>> {
match self {
UI::Loading => text("Loading")
.width(Length::Fill)
.height(Length::Fill)
.vertical_alignment(Vertical::Center)
.horizontal_alignment(Horizontal::Center)
.into(),
UI::Error(message) => text(String::from("Error: ") + message)
.width(Length::Fill)
.height(Length::Fill)
@ -293,4 +283,24 @@ impl Application for UI {
fn theme(&self) -> Self::Theme {
Theme::Dark
}
fn subscription(&self) -> iced::Subscription<Self::Message> {
match self {
UI::Chats(state) => iced::subscription::unfold(
"external messages",
state.recv.take(),
move |recv| async move {
let msg = recv.as_ref().unwrap().recv();
if let Err(_) = msg {
return (UIMessage::Nop, recv);
}
let msg = msg.unwrap();
(msg, recv)
},
),
_ => Subscription::none(),
}
}
}