diff --git a/build_info.matthias_build b/build_info.matthias_build index 4430a03a..c0c73274 100644 --- a/build_info.matthias_build +++ b/build_info.matthias_build @@ -1 +1 @@ -2024.01.14. 14:10 \ No newline at end of file +2024.01.14. 22:22 \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index 3338cb57..5655bb02 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,5 +1,6 @@ use egui::{vec2, Align, Color32, Layout, RichText}; use std::fs::{self}; +use std::sync::mpsc; use windows_sys::w; use windows_sys::Win32::UI::WindowsAndMessaging::{MessageBoxW, MB_ICONERROR}; @@ -16,7 +17,7 @@ use self::account_manager::{ append_to_file, decrypt_lines_from_vec, delete_line_from_file, generate_uuid, read_from_file, }; -use self::backend::{ClientConnection, ServerMaster}; +use self::backend::{ClientConnection, ServerMaster, ConnectionState}; use self::input::keymap; impl eframe::App for backend::TemplateApp { @@ -111,38 +112,64 @@ impl eframe::App for backend::TemplateApp { ui.text_edit_singleline(&mut self.client_ui.send_on_ip); }); - match self.client_connection.client.is_none() { - true => { + match self.client_connection.state { + ConnectionState::Connected => { + if ui + .button(RichText::from("Disconnect").color(Color32::RED)) + .clicked() + { + //Reset client + self.client_connection.client = None; + self.client_ui.incoming_msg = ServerMaster::default(); + self.autosync_should_run + .store(false, std::sync::atomic::Ordering::Relaxed); + + self.client_connection.state = ConnectionState::Disconnected; + } + }, + ConnectionState::Disconnected => { if ui.button("Connect").clicked() { + let ip = self.client_ui.send_on_ip.clone(); - match ClientConnection::connect(format!("http://{}", ip)) { - Ok(ok) => { - self.client_connection = ok; - } - Err(err) => { - std::thread::spawn(move || unsafe { - MessageBoxW( - 0, - str::encode_utf16(err.to_string().as_str()) - .chain(std::iter::once(0)) - .collect::>() - .as_ptr(), - w!("Error"), - MB_ICONERROR, - ); - }); - } - }; + + let sender = self.connection_sender.clone(); + + std::thread::spawn(move || { + match ClientConnection::connect(format!("http://{}", ip)) { + Ok(ok) => { + if let Err(err) = sender.send(ok){ + dbg!(err); + }; + } + Err(err) => { + std::thread::spawn(move || unsafe { + MessageBoxW( + 0, + str::encode_utf16(err.to_string().as_str()) + .chain(std::iter::once(0)) + .collect::>() + .as_ptr(), + w!("Error"), + MB_ICONERROR, + ); + }); + } + }; + }); + self.autosync_should_run .store(true, std::sync::atomic::Ordering::Relaxed); //reset autosync self.autosync_sender = None; + + self.client_connection.state = ConnectionState::Connecting; + } - } - false => { + }, + ConnectionState::Connecting => { if ui - .button(RichText::from("Disconnect").color(Color32::RED)) + .button(RichText::from("Cancel connection").color(Color32::LIGHT_GRAY)) .clicked() { //Reset client @@ -150,10 +177,33 @@ impl eframe::App for backend::TemplateApp { self.client_ui.incoming_msg = ServerMaster::default(); self.autosync_should_run .store(false, std::sync::atomic::Ordering::Relaxed); + + self.client_connection.state = ConnectionState::Disconnected; } + }, + } + + match self.client_connection.client.is_none() { + true => { + + } + false => { + } } + match self.client_connection.state { + ConnectionState::Connected => { + ui.label(RichText::from("Connected").color(Color32::GREEN)); + }, + ConnectionState::Disconnected => { + ui.label(RichText::from("Disconnected").color(Color32::RED)); + }, + ConnectionState::Connecting => { + ui.label(RichText::from("Connecting").color(Color32::LIGHT_GREEN)); + }, + } + ui.allocate_ui(vec2(25., 25.), |ui| { if ui .add(egui::widgets::ImageButton::new(egui::include_image!( @@ -240,5 +290,13 @@ impl eframe::App for backend::TemplateApp { Err(err) => eprintln!("{err}"), }; }); + + //Connection reciver + match self.connection_reciver.try_recv() { + Ok(connection) => self.client_connection = connection, + Err(err) => { + //dbg!(err); + }, + } } } diff --git a/src/app/backend.rs b/src/app/backend.rs index 543158ba..5229f399 100644 --- a/src/app/backend.rs +++ b/src/app/backend.rs @@ -5,7 +5,7 @@ use rand::rngs::ThreadRng; use crate::app::input::Input; use rodio::{OutputStream, OutputStreamHandle, Sink}; use std::collections::BTreeMap; -use std::fmt::Display; +use std::fmt::{Display, Debug}; use std::io; use std::io::{Read, Seek, SeekFrom}; use std::path::PathBuf; @@ -115,6 +115,13 @@ pub struct TemplateApp { #[serde(skip)] pub dtx: mpsc::Sender, + ///Server connection + #[serde(skip)] + pub connection_reciver: mpsc::Receiver, + #[serde(skip)] + pub connection_sender: mpsc::Sender, + + ///Server - client syncing thread #[serde(skip)] pub autosync_sender: Option>, @@ -135,6 +142,7 @@ impl Default for TemplateApp { let (ftx, frx) = mpsc::channel::(); let (itx, irx) = mpsc::channel::(); let (audio_save_tx, audio_save_rx) = mpsc::channel::(); + let (connection_sender, connection_reciver) = mpsc::channel::(); Self { audio_file: Arc::new(Mutex::new(PathBuf::from(format!( "{}\\Matthias\\Client\\voice_record.wav", @@ -196,6 +204,10 @@ impl Default for TemplateApp { rx, tx, + //Server connection + connection_sender, + connection_reciver, + //data sync drx, dtx, @@ -635,6 +647,8 @@ impl ClientMessage { pub struct ClientConnection { #[serde(skip)] pub client: Option>, + #[serde(skip)] + pub state: ConnectionState, } impl ClientConnection { @@ -691,11 +705,38 @@ impl ClientConnection { //Is the client valid? reciver.recv().unwrap() }, + state: ConnectionState::Connected, }) } } -///Used to decide what type fo file i want to send client_actions/actions.rs +///Used to show state of the connection +#[derive(serde::Serialize, serde::Deserialize, Clone)] +pub enum ConnectionState { + Connected, + Disconnected, + Connecting, +} + +impl Default for ConnectionState { + fn default() -> Self { + Self::Disconnected + } +} + +impl Debug for ConnectionState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str( + match self { + ConnectionState::Connected => "Connected", + ConnectionState::Disconnected => "Disconnected", + ConnectionState::Connecting => "Connecting", + } + ) + } +} + +///Used to decide what type fo file i want to send client_actions/actions.rs TODO: include this in main pub enum ClientSendType { File, Message, diff --git a/src/app/server.rs b/src/app/server.rs index 0b947d95..f4849df1 100644 --- a/src/app/server.rs +++ b/src/app/server.rs @@ -261,7 +261,6 @@ pub async fn server_main( let messages = &msg_service.messages.lock().unwrap().to_vec(); Server::builder() - .http2_keepalive_interval(Some(Duration::from_secs(10))) .add_service(MessageServer::new(msg_service)) .serve(addr) .await?; diff --git a/src/app/ui/client_ui/client_actions/actions.rs b/src/app/ui/client_ui/client_actions/actions.rs index 546cb08f..32ed678a 100644 --- a/src/app/ui/client_ui/client_actions/actions.rs +++ b/src/app/ui/client_ui/client_actions/actions.rs @@ -37,7 +37,6 @@ impl TemplateApp { #[inline] pub fn send_file(&mut self, file: std::path::PathBuf) { let passw = self.client_ui.client_password.clone(); - let ip = self.client_ui.send_on_ip.clone(); let author = self.login_username.clone(); let replying_to = self.client_ui.replying_to; diff --git a/src/app/ui/client_ui/message_instances/audio.rs b/src/app/ui/client_ui/message_instances/audio.rs index c0df9634..28c682cf 100644 --- a/src/app/ui/client_ui/message_instances/audio.rs +++ b/src/app/ui/client_ui/message_instances/audio.rs @@ -180,7 +180,6 @@ impl TemplateApp { //We dont have file on our local system so we have to ask the server to provide it let passw = self.client_ui.client_password.clone(); let author = self.login_username.clone(); - let send_on_ip = self.client_ui.send_on_ip.clone(); let sender = self.audio_save_tx.clone(); let message = ClientMessage::construct_audio_request_msg( diff --git a/src/app/ui/client_ui/message_instances/file.rs b/src/app/ui/client_ui/message_instances/file.rs index 9c1ba93a..3bbcf974 100644 --- a/src/app/ui/client_ui/message_instances/file.rs +++ b/src/app/ui/client_ui/message_instances/file.rs @@ -17,7 +17,6 @@ impl TemplateApp { { let passw = self.client_ui.client_password.clone(); let author = self.login_username.clone(); - let send_on_ip = self.client_ui.send_on_ip.clone(); let sender = self.ftx.clone(); let message = ClientMessage::construct_file_request_msg(file.index, passw, author); diff --git a/src/app/ui/client_ui/message_instances/image.rs b/src/app/ui/client_ui/message_instances/image.rs index 5bfc6dfb..97d7f033 100644 --- a/src/app/ui/client_ui/message_instances/image.rs +++ b/src/app/ui/client_ui/message_instances/image.rs @@ -137,7 +137,6 @@ impl TemplateApp { //We dont have file on our local system so we have to ask the server to provide it let passw = self.client_ui.client_password.clone(); let author = self.login_username.clone(); - let send_on_ip = self.client_ui.send_on_ip.clone(); let sender = self.itx.clone(); let message = ClientMessage::construct_image_request_msg( diff --git a/src/app/ui/client_ui/widgets/message_tray/message_tray_main.rs b/src/app/ui/client_ui/widgets/message_tray/message_tray_main.rs index 84568d3d..116cbb41 100644 --- a/src/app/ui/client_ui/widgets/message_tray/message_tray_main.rs +++ b/src/app/ui/client_ui/widgets/message_tray/message_tray_main.rs @@ -92,7 +92,7 @@ impl TemplateApp { true => self.client_ui.client_password.clone(), false => "".into(), }; - let temp_ip = self.client_ui.send_on_ip.clone(); + let replying_to = self.client_ui.replying_to; let connection = self.client_connection.clone();