diff --git a/CHANGELOG.md b/CHANGELOG.md index 590f976..28a8d83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ Procedure when bumping the version number: ## Unreleased +### Added +- Error popups in rooms when something goes wrong + ### Changed - Reduced amount of unnecessary redraws diff --git a/Cargo.lock b/Cargo.lock index 7368637..13fc180 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -290,10 +290,9 @@ checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" [[package]] name = "euphoxide" version = "0.1.0" -source = "git+https://github.com/Garmelon/euphoxide.git?rev=643da74bcc24dc2eeb8746b45fbb986d1d000f0a#643da74bcc24dc2eeb8746b45fbb986d1d000f0a" +source = "git+https://github.com/Garmelon/euphoxide.git?rev=2579a9860da7b0eaa9aded098921c64f8ea2abab#2579a9860da7b0eaa9aded098921c64f8ea2abab" dependencies = [ "futures", - "rand", "serde", "serde_json", "thiserror", @@ -347,7 +346,6 @@ checksum = "ab30e97ab6aacfe635fad58f22c2bb06c8b685f7421eb1e064a729e2a5f481fa" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -370,34 +368,12 @@ version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115" -[[package]] -name = "futures-executor" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d11aa21b5b587a64682c0094c2bdd4df0076c5324961a40cc3abd7f37930528" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - [[package]] name = "futures-io" version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93a66fc6d035a26a3ae255a6d2bca35eda63ae4c5512bef54449113f7a1228e5" -[[package]] -name = "futures-macro" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0db9cce532b0eae2ccf2766ab246f114b56b9cf6d445e00c2549fbc100ca045d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "futures-sink" version = "0.3.23" @@ -419,7 +395,6 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", - "futures-macro", "futures-sink", "futures-task", "memchr", diff --git a/Cargo.toml b/Cargo.toml index a3ea11d..1336a60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ features = ["rustls-tls-native-roots"] [dependencies.euphoxide] git = "https://github.com/Garmelon/euphoxide.git" -rev = "643da74bcc24dc2eeb8746b45fbb986d1d000f0a" +rev = "2579a9860da7b0eaa9aded098921c64f8ea2abab" # [patch."https://github.com/Garmelon/euphoxide.git"] # toss = { path = "../euphoxide/" } diff --git a/src/euph/room.rs b/src/euph/room.rs index 558ba2c..88b3e0c 100644 --- a/src/euph/room.rs +++ b/src/euph/room.rs @@ -5,6 +5,7 @@ use std::time::Duration; use anyhow::bail; use cookie::{Cookie, CookieJar}; +use euphoxide::api::packet::ParsedPacket; use euphoxide::api::{Data, Log, Nick, Send, Snowflake, Time, UserId}; use euphoxide::conn::{ConnRx, ConnTx, Joining, Status}; use log::{error, info, warn}; @@ -28,7 +29,7 @@ pub enum Error { pub enum EuphRoomEvent { Connected, Disconnected, - Data(Box), + Packet(Box), } #[derive(Debug)] @@ -36,7 +37,7 @@ enum Event { // Events Connected(ConnTx), Disconnected, - Data(Box), + Packet(Box), // Commands Status(oneshot::Sender>), RequestLogs, @@ -89,8 +90,8 @@ impl State { info!("e&{}: connected", name); event_tx.send(Event::Connected(conn_tx))?; - while let Ok(data) = conn_rx.recv().await { - event_tx.send(Event::Data(Box::new(data)))?; + while let Some(packet) = conn_rx.recv().await { + event_tx.send(Event::Packet(Box::new(packet)))?; } info!("e&{}: disconnected", name); @@ -170,9 +171,9 @@ impl State { self.last_msg_id = None; let _ = euph_room_event_tx.send(EuphRoomEvent::Disconnected); } - Event::Data(data) => { - self.on_data(&*data).await?; - let _ = euph_room_event_tx.send(EuphRoomEvent::Data(data)); + Event::Packet(packet) => { + self.on_packet(&*packet).await?; + let _ = euph_room_event_tx.send(EuphRoomEvent::Packet(packet)); } Event::Status(reply_tx) => self.on_status(reply_tx).await, Event::RequestLogs => self.on_request_logs(), @@ -190,7 +191,8 @@ impl State { }) } - async fn on_data(&mut self, data: &Data) -> anyhow::Result<()> { + async fn on_packet(&mut self, packet: &ParsedPacket) -> anyhow::Result<()> { + let data = ok_or_return!(&packet.content, Ok(())); match data { Data::BounceEvent(_) => {} Data::DisconnectEvent(d) => { diff --git a/src/ui.rs b/src/ui.rs index 8de77a5..f1b9dea 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -311,7 +311,7 @@ impl Ui { } async fn handle_euph_room_event(&mut self, name: String, event: EuphRoomEvent) -> bool { - // TODO Redirect this to the euph room - true + let handled = self.rooms.handle_euph_room_event(name, event); + handled && self.mode == Mode::Main } } diff --git a/src/ui/euph/room.rs b/src/ui/euph/room.rs index fe05c16..0fa535d 100644 --- a/src/ui/euph/room.rs +++ b/src/ui/euph/room.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use crossterm::event::KeyCode; use crossterm::style::{Color, ContentStyle, Stylize}; -use euphoxide::api::{Data, SessionType, SessionView, Snowflake}; +use euphoxide::api::{Data, PacketType, SessionType, SessionView, Snowflake}; use euphoxide::conn::{Joined, Status}; use parking_lot::FairMutex; use tokio::sync::oneshot::error::TryRecvError; @@ -467,4 +467,64 @@ impl EuphRoom { }, } } + + pub fn handle_euph_room_event(&mut self, event: EuphRoomEvent) -> bool { + match event { + EuphRoomEvent::Connected | EuphRoomEvent::Disconnected => true, + EuphRoomEvent::Packet(packet) => match packet.content { + Ok(data) => self.handle_euph_data(data), + Err(reason) => self.handle_euph_error(packet.r#type, reason), + }, + } + } + + fn handle_euph_data(&mut self, data: Data) -> bool { + // These packets don't result in any noticeable change in the UI. This + // function's main purpose is to prevent pings from causing a redraw. + + #[allow(clippy::match_like_matches_macro)] + match data { + Data::PingEvent(_) | Data::PingReply(_) => { + // Pings are displayed nowhere in the room UI. + false + } + Data::DisconnectEvent(_) => { + // Followed by the server closing the connection, meaning that + // we'll get an `EuphRoomEvent::Disconnected` soon after this. + false + } + _ => true, + } + } + + fn handle_euph_error(&mut self, r#type: PacketType, reason: String) -> bool { + let action = match r#type { + PacketType::AuthReply => "authenticate", + PacketType::NickReply => "set nick", + PacketType::PmInitiateReply => "initiate pm", + PacketType::SendReply => "send message", + PacketType::ChangeEmailReply => "change account email", + PacketType::ChangeNameReply => "change account name", + PacketType::ChangePasswordReply => "change account password", + PacketType::LoginReply => "log in", + PacketType::LogoutReply => "log out", + PacketType::RegisterAccountReply => "register account", + PacketType::ResendVerificationEmailReply => "resend verification email", + PacketType::ResetPasswordReply => "reset account password", + PacketType::BanReply => "ban", + PacketType::EditMessageReply => "edit message", + PacketType::GrantAccessReply => "grant room access", + PacketType::GrantManagerReply => "grant manager permissions", + PacketType::RevokeAccessReply => "revoke room access", + PacketType::RevokeManagerReply => "revoke manager permissions", + PacketType::UnbanReply => "unban", + _ => return false, + }; + let description = format!("Failed to {action}."); + self.popups.push_front(Popup::ServerError { + description, + reason, + }); + true + } } diff --git a/src/ui/rooms.rs b/src/ui/rooms.rs index 290142f..9c78576 100644 --- a/src/ui/rooms.rs +++ b/src/ui/rooms.rs @@ -11,6 +11,7 @@ use tokio::sync::mpsc; use toss::styled::Styled; use toss::terminal::Terminal; +use crate::euph::EuphRoomEvent; use crate::vault::Vault; use super::euph::room::EuphRoom; @@ -365,4 +366,16 @@ impl Rooms { true } + + pub fn handle_euph_room_event(&mut self, name: String, event: EuphRoomEvent) -> bool { + let room_visible = if let State::ShowRoom(n) = &self.state { + *n == name + } else { + true + }; + + let room = self.get_or_insert_room(name); + let handled = room.handle_euph_room_event(event); + handled && room_visible + } }