diff --git a/src/com/raw.rs b/src/com/raw.rs index 4e8d3de..b94af89 100644 --- a/src/com/raw.rs +++ b/src/com/raw.rs @@ -60,6 +60,7 @@ impl Com for ComRawImpl { Ok(()) => Ok(buf.len()), Err(ref e) => { if e.kind() == io::ErrorKind::WouldBlock { + println!("sleep1"); std::thread::sleep(Duration::from_millis(100)); return self.send(buf); } diff --git a/src/com/telnet.rs b/src/com/telnet.rs index 7032c80..c01d1c2 100644 --- a/src/com/telnet.rs +++ b/src/com/telnet.rs @@ -307,6 +307,7 @@ mod telnet_option { impl ComTelnetImpl { pub fn connect(connection_data: &super::OpenConnectionData) -> TermComResult { let tcp_stream = TcpStream::connect(&connection_data.address)?; + tcp_stream.set_nonblocking(true)?; tcp_stream.set_write_timeout(Some(Duration::from_millis(2000)))?; tcp_stream.set_read_timeout(Some(Duration::from_millis(2000)))?; Ok(Self { @@ -482,15 +483,9 @@ impl Com for ComTelnetImpl { } fn read_data(&mut self) -> TermComResult>> { - let mut buf = [0; 1024 * 256]; - if self.tcp_stream.peek(&mut buf)? == 0 { - return Ok(None); - } - + let mut buf = [0; 1024 * 8]; match self.tcp_stream.read(&mut buf) { Ok(size) => { - self.tcp_stream.set_nonblocking(true)?; - if self.use_raw_transfer { Ok(Some(buf[0..size].to_vec())) } else { @@ -498,7 +493,6 @@ impl Com for ComTelnetImpl { } } Err(ref e) => { - self.tcp_stream.set_nonblocking(true)?; if e.kind() == io::ErrorKind::WouldBlock { return Ok(None); } @@ -526,6 +520,8 @@ impl Com for ComTelnetImpl { Ok(()) => Ok(buf.len()), Err(ref e) => { if e.kind() == io::ErrorKind::WouldBlock { + println!("sleep2"); + std::thread::sleep(Duration::from_millis(100)); return self.send(buf); } diff --git a/src/features/auto_login.rs b/src/features/auto_login.rs index d31e3cf..b3a69fa 100644 --- a/src/features/auto_login.rs +++ b/src/features/auto_login.rs @@ -3,7 +3,7 @@ use web_time::Instant; use crate::{ ui::connect::{Connection, DataConnection}, util::PatternRecognizer, - Address, Options, TerminalResult, + Address, TerminalResult, }; use std::time::Duration; @@ -22,10 +22,19 @@ pub struct AutoLogin { got_name: bool, name_recognizer: PatternRecognizer, login_recognizer: PatternRecognizer, + + user_name: String, + password: String, } impl AutoLogin { - pub fn new(login_expr: &str) -> Self { + pub fn new(login_expr: &str, adr: &Address) -> Self { + let (user_name, password) = if adr.override_iemsi_settings { + (adr.iemsi_user.clone(), adr.iemsi_password.clone()) + } else { + (adr.user_name.clone(), adr.password.clone()) + }; + Self { logged_in: false, disabled: false, @@ -38,6 +47,8 @@ impl AutoLogin { got_name: false, name_recognizer: PatternRecognizer::from(b"NAME", true), login_recognizer: PatternRecognizer::from(b"LOGIN:", true), + user_name, + password, } } @@ -107,11 +118,11 @@ impl AutoLogin { Ok(true) } - pub fn try_login(&mut self, connection: &mut Connection, adr: &Address, ch: u8, options: &Options) -> TerminalResult<()> { + pub fn try_login(&mut self, connection: &mut Connection, ch: u8) -> TerminalResult<()> { if self.logged_in || self.disabled { return Ok(()); } - if adr.user_name.is_empty() || adr.password.is_empty() { + if self.user_name.is_empty() || self.password.is_empty() { self.logged_in = true; return Ok(()); } @@ -123,7 +134,7 @@ impl AutoLogin { self.last_char_recv = Instant::now(); self.got_name |= self.name_recognizer.push_ch(ch) | self.login_recognizer.push_ch(ch); - self.logged_in |= self.iemsi.try_login(connection, adr, ch, options)?; + self.logged_in |= self.iemsi.try_login(connection, &self.user_name, &self.password, ch)?; Ok(()) } diff --git a/src/features/iemsi_com.rs b/src/features/iemsi_com.rs index f72bb08..f2c06ba 100644 --- a/src/features/iemsi_com.rs +++ b/src/features/iemsi_com.rs @@ -6,9 +6,8 @@ use std::fmt; use icy_engine::{get_crc16, get_crc32, update_crc32}; use crate::{ - addresses::Address, ui::connect::{Connection, DataConnection}, - Options, TerminalResult, VERSION, + IEMSISettings, TerminalResult, VERSION, }; /// EMSI Inquiry is transmitted by the calling system to identify it as @@ -399,6 +398,7 @@ pub struct IEmsi { pub got_invalid_isi: bool, isi_data: Vec, + pub settings: IEMSISettings, pub aborted: bool, logged_in: bool, } @@ -513,11 +513,11 @@ impl IEmsi { Ok(false) } - pub fn try_login(&mut self, con: &mut Connection, adr: &Address, ch: u8, options: &Options) -> TerminalResult { + pub fn try_login(&mut self, con: &mut Connection, user_name: &str, password: &str, ch: u8) -> TerminalResult { if self.aborted { return Ok(false); } - if let Some(data) = self.advance_char(adr, ch, options)? { + if let Some(data) = self.advance_char(user_name, password, ch)? { if con.is_connected() { con.send(data)?; } @@ -525,7 +525,7 @@ impl IEmsi { Ok(self.logged_in) } - pub fn advance_char(&mut self, adr: &Address, ch: u8, options: &Options) -> TerminalResult>> { + pub fn advance_char(&mut self, user_name: &str, password: &str, ch: u8) -> TerminalResult>> { if self.aborted { return Ok(None); } @@ -533,7 +533,7 @@ impl IEmsi { if self.irq_requested { self.irq_requested = false; // self.log_file.push("Starting IEMSI negotiation…".to_string()); - let data = create_iemsi_ici(adr, options); + let data = create_iemsi_ici(user_name, password, &self.settings); return Ok(Some(data.encode()?)); } else if let Some(_isi) = &self.isi { // self.log_file.push("Receiving valid IEMSI server info…".to_string()); @@ -551,7 +551,7 @@ impl IEmsi { self.nak_requested = false; if self.retries < 2 { // self.log_file.push("IEMSI retry…".to_string()); - let data = create_iemsi_ici(adr, options); + let data = create_iemsi_ici(user_name, password, &self.settings); self.retries += 1; return Ok(Some(data.encode()?)); } @@ -572,20 +572,15 @@ impl IEmsi { } } -fn create_iemsi_ici(adr: &Address, options: &Options) -> EmsiICI { +fn create_iemsi_ici(user_name: &str, password: &str, settings: &IEMSISettings) -> EmsiICI { let mut data = EmsiICI::new(); - if adr.override_iemsi_settings { - data.name = adr.iemsi_user.clone(); - data.password = adr.iemsi_password.clone(); - } else { - data.name = adr.user_name.clone(); - data.password = adr.password.clone(); - } - data.location = options.iemsi.location.clone(); - data.alias = options.iemsi.alias.clone(); - data.data_telephone = options.iemsi.data_phone.clone(); - data.voice_telephone = options.iemsi.voice_phone.clone(); - data.birthdate = options.iemsi.birth_date.clone(); + data.name = user_name.to_string(); + data.password = password.to_string(); + data.location = settings.location.clone(); + data.alias = settings.alias.clone(); + data.data_telephone = settings.data_phone.clone(); + data.voice_telephone = settings.voice_phone.clone(); + data.birthdate = settings.birth_date.clone(); data } @@ -690,6 +685,8 @@ fn encode_emsi(data: &[&str]) -> TerminalResult> { #[cfg(test)] mod tests { #![allow(clippy::field_reassign_with_default)] + use crate::{Address, Options}; + use super::*; #[test] @@ -808,7 +805,7 @@ mod tests { let mut back_data = Vec::new(); for b in EMSI_IRQ { - if let Some(data) = state.advance_char(&adr, *b, &opt).unwrap() { + if let Some(data) = state.advance_char(&adr.user_name, &adr.password, *b).unwrap() { back_data = data; } } diff --git a/src/ui/app.rs b/src/ui/app.rs index 2629c77..b558577 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -7,10 +7,11 @@ use directories::UserDirs; use eframe::egui::{self}; use egui::{mutex::Mutex, FontId}; use icy_engine::Position; +use web_time::Instant; use crate::{ check_error, - features::{AutoFileTransfer, AutoLogin}, + features::AutoFileTransfer, ui::{ buffer_update_thread::BufferUpdateThread, dialogs::{self}, @@ -68,6 +69,11 @@ impl MainWindow { connection: Arc::new(Mutex::new(Some(Box::new(connection)))), buffer_view: buffer_update_view.clone(), capture_dialog: dialogs::capture_dialog::DialogState::default(), + last_update: Instant::now(), + auto_file_transfer: AutoFileTransfer::default(), + auto_transfer: None, + auto_login: None, + sound_thread: Arc::new(eframe::epaint::mutex::Mutex::new(SoundThread::new())), })); crate::ui::buffer_update_thread::run_update_thread(&cc.egui_ctx, buffer_update_thread.clone()); @@ -77,13 +83,10 @@ impl MainWindow { //address_list: HoverList::new(), state: MainWindowState { options, ..Default::default() }, initial_upload_directory, - auto_login: AutoLogin::new(""), - auto_file_transfer: AutoFileTransfer::default(), screen_mode: ScreenMode::default(), current_file_transfer: None, #[cfg(target_arch = "wasm32")] poll_thread, - sound_thread: SoundThread::new(), is_fullscreen_mode, export_dialog: dialogs::export_dialog::DialogState::default(), upload_dialog: dialogs::upload_dialog::DialogState::default(), @@ -160,19 +163,19 @@ impl eframe::App for MainWindow { match self.get_mode() { MainWindowMode::ShowTerminal => { - let res = self.update_state(ctx); + let res = self.update_state(); self.handle_terminal_key_binds(ctx, frame); self.update_terminal_window(ctx, frame, false); check_error!(self, res, false); ctx.request_repaint_after(Duration::from_millis(150)); } MainWindowMode::ShowDialingDirectory => { - let res = self.update_state(ctx); + let res = self.update_state(); self.update_terminal_window(ctx, frame, true); check_error!(self, res, false); } MainWindowMode::ShowSettings => { - let res = self.update_state(ctx); + let res = self.update_state(); self.update_terminal_window(ctx, frame, false); check_error!(self, res, false); self.state.show_settings(ctx, frame); @@ -218,7 +221,7 @@ impl eframe::App for MainWindow { ctx.request_repaint_after(Duration::from_millis(150)); } MainWindowMode::ShowCaptureDialog => { - let res = self.update_state(ctx); + let res = self.update_state(); self.update_terminal_window(ctx, frame, false); check_error!(self, res, false); if !self.buffer_update_thread.lock().capture_dialog.show_caputure_dialog(ctx) { @@ -227,21 +230,21 @@ impl eframe::App for MainWindow { ctx.request_repaint_after(Duration::from_millis(150)); } MainWindowMode::ShowExportDialog => { - let res = self.update_state(ctx); + let res = self.update_state(); self.update_terminal_window(ctx, frame, false); check_error!(self, res, false); self.show_export_dialog(ctx); ctx.request_repaint_after(Duration::from_millis(150)); } MainWindowMode::ShowUploadDialog => { - let res = self.update_state(ctx); + let res = self.update_state(); self.update_terminal_window(ctx, frame, false); check_error!(self, res, false); self.show_upload_dialog(ctx); ctx.request_repaint_after(Duration::from_millis(150)); } MainWindowMode::ShowIEMSI => { - let res = self.update_state(ctx); + let res = self.update_state(); self.update_terminal_window(ctx, frame, false); check_error!(self, res, false); dialogs::show_iemsi::show_iemsi(self, ctx); diff --git a/src/ui/buffer_update_thread.rs b/src/ui/buffer_update_thread.rs index b983632..9bd61ea 100644 --- a/src/ui/buffer_update_thread.rs +++ b/src/ui/buffer_update_thread.rs @@ -1,8 +1,13 @@ -use crate::TerminalResult; +use crate::{ + features::{AutoFileTransfer, AutoLogin}, + protocol::TransferType, + util::SoundThread, + TerminalResult, +}; use egui::mutex::Mutex; use icy_engine_egui::BufferView; use std::{collections::VecDeque, sync::Arc, thread}; -use web_time::Duration; +use web_time::{Duration, Instant}; use super::{ connect::{Connection, DataConnection}, @@ -14,14 +19,24 @@ pub struct BufferUpdateThread { pub buffer_view: Arc>, pub connection: Arc>>>, + + pub last_update: Instant, + pub auto_file_transfer: AutoFileTransfer, + pub auto_login: Option, + pub sound_thread: Arc>, + + pub auto_transfer: Option<(TransferType, bool)>, } impl BufferUpdateThread { - pub fn update_state(&mut self, ctx: &egui::Context) -> TerminalResult<()> { + pub fn update_state(&mut self, ctx: &egui::Context) -> TerminalResult { + let r: Result<_, _> = self.sound_thread.lock().update_state(); + // check_error!(self, r, false); + let data = if let Some(con) = self.connection.lock().as_mut() { - con.update_state(); + con.update_state()?; if con.is_disconnected() { - return Ok(()); + return Ok(false); } if con.is_data_available()? { con.read_buffer() @@ -29,50 +44,47 @@ impl BufferUpdateThread { VecDeque::new() } } else { - thread::sleep(Duration::from_millis(100)); - return Ok(()); + return Ok(false); }; - - self.update_buffer(ctx, data); - - Ok(()) + Ok(self.update_buffer(ctx, data)) } - fn update_buffer(&mut self, ctx: &egui::Context, mut data: std::collections::VecDeque) { + fn update_buffer(&mut self, ctx: &egui::Context, mut data: std::collections::VecDeque) -> bool { self.capture_dialog.append_data(&mut data); let has_data = !data.is_empty(); let mut set_buffer_dirty = false; + if !data.is_empty() { + println!("data : {}", self.last_update.elapsed().as_millis()); + } + let buffer_view = &mut self.buffer_view.lock(); + while !data.is_empty() { let ch = data.pop_front().unwrap(); - /* if self.get_options().iemsi.autologin && self.connection().is_connected() { - if let Some(adr) = self.dialing_directory_dialog.addresses.addresses.get(self.dialing_directory_dialog.cur_addr) { - if let Some(con) = &mut self.buffer_update_thread.lock().connection { - if let Err(err) = self.auto_login.try_login(con, adr, ch, &self.state.options) { - log::error!("{err}"); - } + if let Some(autologin) = &mut self.auto_login { + if let Some(con) = self.connection.lock().as_mut() { + if let Err(err) = autologin.try_login(con, ch) { + log::error!("{err}"); + } + if autologin.logged_in { + self.auto_login = None; } } - }*/ + } - if self.print_char(Some(ctx), ch) { + if self.print_char(buffer_view, ch) { set_buffer_dirty = true; } - /* if let Some((protocol_type, download)) = self.auto_file_transfer.try_transfer(ch) { - self.initiate_file_transfer(protocol_type, download); - return Ok(()); - }*/ - } - - if set_buffer_dirty { - println!("set_buffer_dirty"); - self.buffer_view.lock().get_edit_state_mut().is_buffer_dirty = true; + self.auto_transfer = Some((protocol_type, download)); + } } - if has_data { - self.buffer_view.lock().get_buffer_mut().update_hyperlinks(); - } else { - thread::sleep(Duration::from_millis(10)); + buffer_view.get_buffer_mut().update_hyperlinks(); + } + if set_buffer_dirty { + self.last_update = Instant::now(); + buffer_view.get_edit_state_mut().is_buffer_dirty = true; + return false; } /* if self.get_options().iemsi.autologin { @@ -103,10 +115,12 @@ impl BufferUpdateThread { } } }*/ + + true } - pub fn print_char(&self, ctx: Option<&egui::Context>, c: u8) -> bool { - let result = self.buffer_view.lock().print_char(unsafe { char::from_u32_unchecked(c as u32) }); + pub fn print_char(&self, buffer_view: &mut BufferView, c: u8) -> bool { + let result = buffer_view.print_char(c as char); match result { Ok(icy_engine::CallbackAction::SendString(result)) => { if let Some(con) = self.connection.lock().as_mut() { @@ -117,14 +131,12 @@ impl BufferUpdateThread { } } Ok(icy_engine::CallbackAction::PlayMusic(music)) => { - // let r = self.sound_thread.play_music(music); + let r = self.sound_thread.lock().play_music(music); // check_error!(self, r, false); } Ok(icy_engine::CallbackAction::Beep) => { - /* if self.get_options().console_beep { - let r = self.sound_thread.beep(); - // check_error!(self, r, false); - }*/ + let r = self.sound_thread.lock().beep(); + // check_error!(self, r, false); } Ok(icy_engine::CallbackAction::ChangeBaudEmulation(baud_emulation)) => { if let Some(con) = self.connection.lock().as_mut() { @@ -133,7 +145,7 @@ impl BufferUpdateThread { } } Ok(icy_engine::CallbackAction::ResizeTerminal(_, _)) => { - self.buffer_view.lock().redraw_view(); + buffer_view.redraw_view(); } Ok(icy_engine::CallbackAction::NoUpdate) => { @@ -155,8 +167,15 @@ impl BufferUpdateThread { pub fn run_update_thread(ctx: &egui::Context, update_thread: Arc>) { let ctx = ctx.clone(); thread::spawn(move || loop { - if let Err(err) = update_thread.lock().update_state(&ctx) { - log::error!("{err}"); + match update_thread.lock().update_state(&ctx) { + Err(err) => { + log::error!("{err}"); + } + Ok(sleep) => { + if sleep { + thread::sleep(Duration::from_millis(10)); + } + } } }); } diff --git a/src/ui/com_thread.rs b/src/ui/com_thread.rs index 13c039f..871ecfe 100644 --- a/src/ui/com_thread.rs +++ b/src/ui/com_thread.rs @@ -162,9 +162,13 @@ impl MainWindow { while data.thread_is_running { if data.is_connected { if !data.read_data() { + println!("sleep5"); + std::thread::sleep(Duration::from_millis(25)); } } else { + println!("sleep6"); + std::thread::sleep(Duration::from_millis(100)); } data.handle_receive(); diff --git a/src/ui/connect.rs b/src/ui/connect.rs index 8359c0b..bb2f72c 100644 --- a/src/ui/connect.rs +++ b/src/ui/connect.rs @@ -35,6 +35,8 @@ impl DataConnection for Connection { fn read_u8(&mut self) -> TerminalResult { while !self.is_data_available()? { + println!("sleep7"); + std::thread::sleep(Duration::from_millis(10)); } Ok(self.buf.pop_front().unwrap()) @@ -43,6 +45,8 @@ impl DataConnection for Connection { fn read_exact(&mut self, size: usize) -> TerminalResult> { while self.buf.len() < size { self.fill_buffer()?; + println!("sleep8"); + std::thread::sleep(Duration::from_millis(10)); } diff --git a/src/ui/dialogs/capture_dialog.rs b/src/ui/dialogs/capture_dialog.rs index d8812f6..063b7b6 100644 --- a/src/ui/dialogs/capture_dialog.rs +++ b/src/ui/dialogs/capture_dialog.rs @@ -1,7 +1,6 @@ use std::collections::VecDeque; use std::io::Write; -use crate::ui::MainWindowState; use eframe::egui::{self, RichText}; use egui::TextEdit; use egui::{Frame, Layout}; @@ -9,8 +8,6 @@ use egui_file::FileDialog; use i18n_embed_fl::fl; use std::path::Path; -use crate::{ui::MainWindowMode, Options}; - #[derive(Default)] pub struct DialogState { open_file_dialog: Option, diff --git a/src/ui/dialogs/show_iemsi.rs b/src/ui/dialogs/show_iemsi.rs index 50f9e1f..7e5e47e 100644 --- a/src/ui/dialogs/show_iemsi.rs +++ b/src/ui/dialogs/show_iemsi.rs @@ -13,7 +13,17 @@ pub fn show_iemsi(window: &mut MainWindow, ctx: &egui::Context) { open = false; } let window_frame = Frame::window(&ctx.style()); - let iemsi = window.auto_login.iemsi.isi.as_ref().unwrap().clone(); + let iemsi = window + .buffer_update_thread + .lock() + .auto_login + .as_ref() + .unwrap() + .iemsi + .isi + .as_ref() + .unwrap() + .clone(); egui::Window::new("") .open(&mut open) diff --git a/src/ui/mod.rs b/src/ui/mod.rs index a597baa..f4cfef0 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -97,19 +97,14 @@ impl MainWindowState { pub struct MainWindow { buffer_view: Arc>, - sound_thread: SoundThread, - pub state: MainWindowState, screen_mode: ScreenMode, - auto_login: AutoLogin, is_fullscreen_mode: bool, drag_start: Option, last_pos: Position, shift_pressed_during_selection: bool, - auto_file_transfer: AutoFileTransfer, - buffer_update_thread: Arc>, pub initial_upload_directory: Option, @@ -161,7 +156,7 @@ impl MainWindow { } if !print { - self.print_char(None, translated_char as u8); + self.print_char(translated_char as u8); } } @@ -180,17 +175,18 @@ impl MainWindow { print = false; } } - if !print { + if print { for ch in str.chars() { let translated_char = self.buffer_view.lock().get_parser().convert_from_unicode(ch, 0); - self.print_char(None, translated_char as u8); + self.print_char(translated_char as u8); } } } - pub fn print_char(&self, ctx: Option<&egui::Context>, c: u8) -> bool { - self.buffer_view.lock().get_edit_state_mut().is_buffer_dirty = true; - self.buffer_update_thread.lock().print_char(ctx, c) + pub fn print_char(&self, c: u8) -> bool { + let buffer_view = &mut self.buffer_view.lock(); + buffer_view.get_edit_state_mut().is_buffer_dirty = true; + self.buffer_update_thread.lock().print_char(buffer_view, c) } #[cfg(target_arch = "wasm32")] @@ -268,8 +264,8 @@ impl MainWindow { address.number_of_calls += 1; address.last_call = Some(Utc::now()); - self.auto_login = AutoLogin::new(&cloned_addr.auto_login); - self.auto_file_transfer.reset(); + self.buffer_update_thread.lock().auto_login = Some(AutoLogin::new(&cloned_addr.auto_login, address)); + self.buffer_update_thread.lock().auto_file_transfer.reset(); self.buffer_view.lock().get_buffer_mut().layers[0].clear(); self.buffer_view.lock().get_buffer_mut().stop_sixel_threads(); self.dialing_directory_dialog.cur_addr = i; @@ -296,15 +292,18 @@ impl MainWindow { } } - pub fn update_state(&mut self, ctx: &egui::Context) -> TerminalResult<()> { + pub fn update_state(&mut self) -> TerminalResult<()> { #[cfg(target_arch = "wasm32")] self.poll_thread.poll(); if let Some(con) = self.buffer_update_thread.lock().connection.lock().as_mut() { let r = con.update_state(); check_error!(self, r, false); } - let r = self.sound_thread.update_state(); - check_error!(self, r, false); + + let take = self.buffer_update_thread.lock().auto_transfer.take(); + if let Some((protocol_type, download)) = take { + self.initiate_file_transfer(protocol_type, download); + } Ok(()) } @@ -312,7 +311,7 @@ impl MainWindow { if let Some(con) = self.buffer_update_thread.lock().connection.lock().as_mut() { check_error!(self, con.disconnect(), false); } - self.sound_thread.clear(); + self.buffer_update_thread.lock().sound_thread.lock().clear(); self.set_mode(MainWindowMode::ShowDialingDirectory); } diff --git a/src/ui/terminal_window.rs b/src/ui/terminal_window.rs index c9e69ef..109ba13 100644 --- a/src/ui/terminal_window.rs +++ b/src/ui/terminal_window.rs @@ -1,9 +1,9 @@ #![allow(clippy::float_cmp)] use eframe::{ - egui::{self, CursorIcon, PointerButton, RichText}, - epaint::{FontFamily, FontId, Vec2}, + egui::{self, CursorIcon, PointerButton}, + epaint::Vec2, }; -use egui::Button; +use egui::{Button, FontFamily, FontId, RichText}; use i18n_embed_fl::fl; use icy_engine::{Position, Selection, TextPane}; @@ -27,146 +27,157 @@ impl MainWindow { let enable_ui = matches!(self.get_mode(), MainWindowMode::ShowTerminal); - /* - if !self.is_fullscreen_mode { - egui::TopBottomPanel::top("button_bar").frame(button_frame).show(ctx, |ui| { - let img_size = 20.0; - if !enable_ui { - ui.set_enabled(false); - } - ui.horizontal(|ui| { - let r = ui - .add(Button::new(RichText::new("⬆").font(FontId::new(img_size, FontFamily::Proportional)))) - .on_hover_ui(|ui| { - ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-upload")).small()); - }); + if !self.is_fullscreen_mode { + egui::TopBottomPanel::top("button_bar").frame(button_frame).show(ctx, |ui| { + let img_size = 20.0; + if !enable_ui { + ui.set_enabled(false); + } + ui.horizontal(|ui| { + let r = ui + .add(Button::new(RichText::new("⬆").font(FontId::new(img_size, FontFamily::Proportional)))) + .on_hover_ui(|ui| { + ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-upload")).small()); + }); - if r.clicked() { - self.set_mode(MainWindowMode::SelectProtocol(false)); - } + if r.clicked() { + self.set_mode(MainWindowMode::SelectProtocol(false)); + } + let r = ui + .button(RichText::new("⬇").font(FontId::new(img_size, FontFamily::Proportional))) + .on_hover_ui(|ui| { + ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-download")).small()); + }); + + if r.clicked() { + self.set_mode(MainWindowMode::SelectProtocol(true)); + } + let mut send_login = false; + if let Some(auto_login) = &mut self.buffer_update_thread.lock().auto_login { + if !auto_login.logged_in { let r = ui - .button(RichText::new("⬇").font(FontId::new(img_size, FontFamily::Proportional))) + .button(RichText::new("🔑").font(FontId::new(img_size, FontFamily::Monospace))) .on_hover_ui(|ui| { - ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-download")).small()); + ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-autologin")).small()); }); if r.clicked() { - self.set_mode(MainWindowMode::SelectProtocol(true)); - } - - if !self.auto_login.logged_in { - let r = ui - .button(RichText::new("🔑").font(FontId::new(img_size, FontFamily::Monospace))) - .on_hover_ui(|ui| { - ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-autologin")).small()); - }); - - if r.clicked() { - self.send_login(); - self.auto_login.logged_in = true; - } + send_login = true; + auto_login.logged_in = true; } + } + } + if send_login { + self.send_login(); + } - let r: egui::Response = ui - .add(egui::Button::new(RichText::new("📞").font(FontId::new(img_size, FontFamily::Monospace)))) - .on_hover_ui(|ui| { - ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-dialing_directory")).small()); - }); - - if r.clicked() { - self.show_dialing_directory(); - } + let r: egui::Response = ui + .add(egui::Button::new(RichText::new("📞").font(FontId::new(img_size, FontFamily::Monospace)))) + .on_hover_ui(|ui| { + ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-dialing_directory")).small()); + }); - if self.auto_login.iemsi.isi.is_some() { - if self.get_mode() == MainWindowMode::ShowIEMSI { - let r: egui::Response = ui.add(egui::Button::new(RichText::new(fl!(crate::LANGUAGE_LOADER, "toolbar-hide-iemsi")))); + if r.clicked() { + self.show_dialing_directory(); + } - if r.clicked() { - self.set_mode(MainWindowMode::ShowTerminal); - } - } else { - let r: egui::Response = ui.add(egui::Button::new(RichText::new(fl!(crate::LANGUAGE_LOADER, "toolbar-show-iemsi")))); + let mut mode = None; + if let Some(auto_login) = &mut self.buffer_update_thread.lock().auto_login { + if auto_login.iemsi.isi.is_some() { + if self.get_mode() == MainWindowMode::ShowIEMSI { + let r: egui::Response = ui.add(egui::Button::new(RichText::new(fl!(crate::LANGUAGE_LOADER, "toolbar-hide-iemsi")))); - if r.clicked() { - self.set_mode(MainWindowMode::ShowIEMSI); - } + if r.clicked() { + mode = Some(MainWindowMode::ShowTerminal); } - } - if self.sound_thread.is_playing() { - let button_text = match self.sound_thread.stop_button { - 0 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing1"), - 1 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing2"), - 2 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing3"), - 3 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing4"), - 4 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing5"), - _ => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing6"), - }; + } else { + let r: egui::Response = ui.add(egui::Button::new(RichText::new(fl!(crate::LANGUAGE_LOADER, "toolbar-show-iemsi")))); - let r: egui::Response = ui.add(egui::Button::new(RichText::new(button_text))); if r.clicked() { - self.sound_thread.clear(); + mode = Some(MainWindowMode::ShowIEMSI); } } + } + } - if self.buffer_update_thread.lock().capture_dialog.capture_session { - let r: egui::Response = ui.add(egui::Button::new(RichText::new(fl!(crate::LANGUAGE_LOADER, "toolbar-stop-capture")))); + if let Some(mode) = mode { + self.set_mode(mode); + } - if r.clicked() { - self.buffer_update_thread.lock().capture_dialog.capture_session = false; - } - } + if self.buffer_update_thread.lock().sound_thread.lock().is_playing() { + let button_text = match self.buffer_update_thread.lock().sound_thread.lock().stop_button { + 0 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing1"), + 1 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing2"), + 2 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing3"), + 3 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing4"), + 4 => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing5"), + _ => fl!(crate::LANGUAGE_LOADER, "toolbar-stop-playing6"), + }; - let size = ui.available_size_before_wrap(); - ui.add_space(size.x - 70.0); + let r: egui::Response = ui.add(egui::Button::new(RichText::new(button_text))); + if r.clicked() { + self.buffer_update_thread.lock().sound_thread.lock().clear(); + } + } - let r = ui - .button(RichText::new("☎").font(FontId::new(img_size, FontFamily::Monospace))) - .on_hover_ui(|ui| { - ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-hangup")).small()); - }); - if r.clicked() { - self.hangup(); - } + if self.buffer_update_thread.lock().capture_dialog.capture_session { + let r: egui::Response = ui.add(egui::Button::new(RichText::new(fl!(crate::LANGUAGE_LOADER, "toolbar-stop-capture")))); - ui.menu_button(RichText::new("☰").font(FontId::new(img_size + 6., FontFamily::Proportional)), |ui| { - let r = ui.hyperlink_to( - fl!(crate::LANGUAGE_LOADER, "menu-item-discuss"), - "https://github.com/mkrueger/icy_term/discussions", - ); - if r.clicked() { - ui.close_menu(); - } - let r = ui.hyperlink_to( - fl!(crate::LANGUAGE_LOADER, "menu-item-report-bug"), - "https://github.com/mkrueger/icy_term/issues/new", - ); - if r.clicked() { - ui.close_menu(); - } - let r = ui.hyperlink_to( - fl!(crate::LANGUAGE_LOADER, "menu-item-check-releases"), - "https://github.com/mkrueger/icy_term/releases/latest", - ); - if r.clicked() { - ui.close_menu(); - } - ui.separator(); - #[cfg(not(target_arch = "wasm32"))] - if ui.button(fl!(crate::LANGUAGE_LOADER, "menu-item-capture-dialog")).clicked() { - self.set_mode(MainWindowMode::ShowCaptureDialog); - ui.close_menu(); - } + if r.clicked() { + self.buffer_update_thread.lock().capture_dialog.capture_session = false; + } + } - if ui.button(fl!(crate::LANGUAGE_LOADER, "menu-item-settings")).clicked() { - self.set_mode(MainWindowMode::ShowSettings); - ui.close_menu(); - } - }); + let size = ui.available_size_before_wrap(); + ui.add_space(size.x - 70.0); + + let r = ui + .button(RichText::new("☎").font(FontId::new(img_size, FontFamily::Monospace))) + .on_hover_ui(|ui| { + ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "terminal-hangup")).small()); }); + if r.clicked() { + self.hangup(); + } + + ui.menu_button(RichText::new("☰").font(FontId::new(img_size + 6., FontFamily::Proportional)), |ui| { + let r = ui.hyperlink_to( + fl!(crate::LANGUAGE_LOADER, "menu-item-discuss"), + "https://github.com/mkrueger/icy_term/discussions", + ); + if r.clicked() { + ui.close_menu(); + } + let r = ui.hyperlink_to( + fl!(crate::LANGUAGE_LOADER, "menu-item-report-bug"), + "https://github.com/mkrueger/icy_term/issues/new", + ); + if r.clicked() { + ui.close_menu(); + } + let r = ui.hyperlink_to( + fl!(crate::LANGUAGE_LOADER, "menu-item-check-releases"), + "https://github.com/mkrueger/icy_term/releases/latest", + ); + if r.clicked() { + ui.close_menu(); + } + ui.separator(); + #[cfg(not(target_arch = "wasm32"))] + if ui.button(fl!(crate::LANGUAGE_LOADER, "menu-item-capture-dialog")).clicked() { + self.set_mode(MainWindowMode::ShowCaptureDialog); + ui.close_menu(); + } + + if ui.button(fl!(crate::LANGUAGE_LOADER, "menu-item-settings")).clicked() { + self.set_mode(MainWindowMode::ShowSettings); + ui.close_menu(); + } }); - } - */ + }); + }); + } let frame_no_margins = egui::containers::Frame::none() .outer_margin(egui::style::Margin::same(0.0)) .inner_margin(egui::style::Margin::same(0.0)); @@ -386,7 +397,7 @@ impl MainWindow { } if print { for c in *m { - self.print_char(None, *c); + self.print_char(*c); } } response.request_focus();