diff --git a/Cargo.lock b/Cargo.lock index ec6c6ed..3d86a8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -308,13 +308,14 @@ dependencies = [ [[package]] name = "euphoxide" version = "0.2.0" -source = "git+https://github.com/Garmelon/euphoxide.git?tag=v0.2.0#58e39fa5bc4d5de4fcc0d467a123823760381b51" +source = "git+https://github.com/Garmelon/euphoxide.git?rev=c15c05a64e82c7c5f7af0539745855c0f6821869#c15c05a64e82c7c5f7af0539745855c0f6821869" dependencies = [ - "futures", + "futures-util", "serde", "serde_json", "time", "tokio", + "tokio-stream", "tokio-tungstenite", ] @@ -354,42 +355,12 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futures" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" -dependencies = [ - "futures-core", - "futures-sink", -] - [[package]] name = "futures-core" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" -[[package]] -name = "futures-io" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" - [[package]] name = "futures-sink" version = "0.3.25" @@ -408,12 +379,9 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ - "futures-channel", "futures-core", - "futures-io", "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", "slab", @@ -1208,6 +1176,17 @@ dependencies = [ "webpki", ] +[[package]] +name = "tokio-stream" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-tungstenite" version = "0.18.0" diff --git a/Cargo.toml b/Cargo.toml index a8fdbe7..7394fa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ features = ["rustls-tls-native-roots"] [dependencies.euphoxide] git = "https://github.com/Garmelon/euphoxide.git" -tag = "v0.2.0" +rev = "c15c05a64e82c7c5f7af0539745855c0f6821869" # [patch."https://github.com/Garmelon/euphoxide.git"] # euphoxide = { path = "../euphoxide/" } diff --git a/src/euph/room.rs b/src/euph/room.rs index ca25c4c..39207a9 100644 --- a/src/euph/room.rs +++ b/src/euph/room.rs @@ -9,7 +9,7 @@ use euphoxide::api::packet::ParsedPacket; use euphoxide::api::{ Auth, AuthOption, Data, Log, Login, Logout, MessageId, Nick, Send, Time, UserId, }; -use euphoxide::conn::{ConnRx, ConnTx, Joining, Status}; +use euphoxide::conn::{Conn, ConnTx, Joining, State as ConnState}; use log::{error, info, warn}; use parking_lot::Mutex; use tokio::sync::{mpsc, oneshot}; @@ -44,7 +44,7 @@ enum Event { Disconnected, Packet(Box), // Commands - Status(oneshot::Sender>), + Status(oneshot::Sender>), // TODO Rename to State RequestLogs, Auth(String), Nick(String), @@ -116,7 +116,7 @@ impl State { info!("e&{}: connected", name); event_tx.send(Event::Connected(conn_tx))?; - while let Some(packet) = conn_rx.recv().await { + while let Ok(packet) = conn_rx.recv().await { event_tx.send(Event::Packet(Box::new(packet)))?; } @@ -161,19 +161,17 @@ impl State { vault.set_cookies(cookie_jar); } - async fn connect( - vault: &EuphRoomVault, - name: &str, - ) -> anyhow::Result> { + // TODO Simplify return type, remove ConnTx + async fn connect(vault: &EuphRoomVault, name: &str) -> anyhow::Result> { // TODO Set user agent? let cookies = Self::get_cookies(vault.vault()).await; let cookies = HeaderValue::from_str(&cookies).expect("valid cookies"); - match euphoxide::connect("euphoria.io", name, true, Some(cookies), TIMEOUT).await { - Ok((tx, rx, set_cookies)) => { + match Conn::connect("euphoria.io", name, true, Some(cookies), TIMEOUT).await { + Ok((rx, set_cookies)) => { Self::update_cookies(vault.vault(), &set_cookies); - Ok(Some((tx, rx))) + Ok(Some((rx.tx().clone(), rx))) } Err(tungstenite::Error::Http(resp)) if resp.status().is_client_error() => { bail!("room {name} doesn't exist"); @@ -251,9 +249,9 @@ impl State { } async fn own_user_id(&self) -> Option { - Some(match self.conn_tx.as_ref()?.status().await.ok()? { - Status::Joining(Joining { hello, .. }) => hello?.session.id, - Status::Joined(joined) => joined.session.id, + Some(match self.conn_tx.as_ref()?.state().await.ok()? { + ConnState::Joining(Joining { hello, .. }) => hello?.session.id, + ConnState::Joined(joined) => joined.session.id, }) } @@ -341,9 +339,10 @@ impl State { Ok(()) } - async fn on_status(&self, reply_tx: oneshot::Sender>) { + // TODO Rename to on_state + async fn on_status(&self, reply_tx: oneshot::Sender>) { let status = if let Some(conn_tx) = &self.conn_tx { - conn_tx.status().await.ok() + conn_tx.state().await.ok() } else { None }; @@ -506,7 +505,8 @@ impl Room { self.event_tx.is_closed() } - pub async fn status(&self) -> Result, Error> { + // TODO Rename to state + pub async fn status(&self) -> Result, Error> { let (tx, rx) = oneshot::channel(); self.event_tx .send(Event::Status(tx)) diff --git a/src/euph/util.rs b/src/euph/util.rs index 05eb467..cf05c76 100644 --- a/src/euph/util.rs +++ b/src/euph/util.rs @@ -33,7 +33,8 @@ fn hsl_to_rgb(h: f32, s: f32, l: f32) -> (u8, u8, u8) { } pub fn nick_color(nick: &str) -> (u8, u8, u8) { - let hue = euphoxide::nick_hue(nick) as f32; + // TODO Use nick hue with emoji (lazy init emoji?) + let hue = euphoxide::nick_hue_without_removing_emoji(nick) as f32; hsl_to_rgb(hue, 1.0, 0.72) } diff --git a/src/ui/euph/account.rs b/src/ui/euph/account.rs index 0a22479..6fee35e 100644 --- a/src/ui/euph/account.rs +++ b/src/ui/euph/account.rs @@ -1,6 +1,6 @@ use crossterm::style::{ContentStyle, Stylize}; use euphoxide::api::PersonalAccountView; -use euphoxide::conn::Status; +use euphoxide::conn::State as ConnState; use toss::terminal::Terminal; use crate::euph::Room; @@ -98,7 +98,7 @@ impl AccountUiState { /// Returns `false` if the account UI should not be displayed any longer. pub fn stabilize(&mut self, status: &RoomStatus) -> bool { - if let RoomStatus::Connected(Status::Joined(status)) = status { + if let RoomStatus::Connected(ConnState::Joined(status)) = status { match (&self, &status.account) { (Self::LoggedOut(_), Some(view)) => *self = Self::LoggedIn(LoggedIn(view.clone())), (Self::LoggedIn(_), None) => *self = Self::LoggedOut(LoggedOut::new()), diff --git a/src/ui/euph/room.rs b/src/ui/euph/room.rs index c8e1b52..882fcd1 100644 --- a/src/ui/euph/room.rs +++ b/src/ui/euph/room.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use crossterm::style::{ContentStyle, Stylize}; use euphoxide::api::{Data, Message, MessageId, PacketType, SessionId}; -use euphoxide::conn::{Joined, Joining, SessionInfo, Status}; +use euphoxide::conn::{Joined, Joining, SessionInfo, State as ConnState}; use parking_lot::FairMutex; use tokio::sync::oneshot::error::TryRecvError; use tokio::sync::{mpsc, oneshot}; @@ -53,7 +53,7 @@ pub enum RoomStatus { NoRoom, Stopped, Connecting, - Connected(Status), + Connected(ConnState), } impl RoomStatus { @@ -192,7 +192,7 @@ impl EuphRoom { fn stabilize_focus(&mut self, status: &RoomStatus) { match status { - RoomStatus::Connected(Status::Joined(_)) => {} + RoomStatus::Connected(ConnState::Joined(_)) => {} _ => self.focus = Focus::Chat, // There is no nick list to focus on } } @@ -202,7 +202,7 @@ impl EuphRoom { State::Auth(_) if !matches!( status, - RoomStatus::Connected(Status::Joining(Joining { + RoomStatus::Connected(ConnState::Joining(Joining { bounce: Some(_), .. })) @@ -210,7 +210,7 @@ impl EuphRoom { { self.state = State::Normal } - State::Nick(_) if !matches!(status, RoomStatus::Connected(Status::Joined(_))) => { + State::Nick(_) if !matches!(status, RoomStatus::Connected(ConnState::Joined(_))) => { self.state = State::Normal } State::Account(account) => { @@ -232,7 +232,7 @@ impl EuphRoom { let status = self.status().await; self.stabilize(&status).await; - let chat = if let RoomStatus::Connected(Status::Joined(joined)) = &status { + let chat = if let RoomStatus::Connected(ConnState::Joined(joined)) = &status { self.widget_with_nick_list(&status, joined).await } else { self.widget_without_nick_list(&status).await @@ -300,11 +300,11 @@ impl EuphRoom { info = match status { RoomStatus::NoRoom | RoomStatus::Stopped => info.then_plain(", archive"), RoomStatus::Connecting => info.then_plain(", connecting..."), - RoomStatus::Connected(Status::Joining(j)) if j.bounce.is_some() => { + RoomStatus::Connected(ConnState::Joining(j)) if j.bounce.is_some() => { info.then_plain(", auth required") } - RoomStatus::Connected(Status::Joining(_)) => info.then_plain(", joining..."), - RoomStatus::Connected(Status::Joined(j)) => { + RoomStatus::Connected(ConnState::Joining(_)) => info.then_plain(", joining..."), + RoomStatus::Connected(ConnState::Joined(j)) => { let nick = &j.session.name; if nick.is_empty() { info.then_plain(", present without nick") @@ -327,7 +327,7 @@ impl EuphRoom { } async fn list_chat_key_bindings(&self, bindings: &mut KeyBindingsList, status: &RoomStatus) { - let can_compose = matches!(status, RoomStatus::Connected(Status::Joined(_))); + let can_compose = matches!(status, RoomStatus::Connected(ConnState::Joined(_))); self.chat.list_key_bindings(bindings, can_compose).await; } @@ -338,7 +338,7 @@ impl EuphRoom { event: &InputEvent, status: &RoomStatus, ) -> bool { - let can_compose = matches!(status, RoomStatus::Connected(Status::Joined(_))); + let can_compose = matches!(status, RoomStatus::Connected(ConnState::Joined(_))); match self .chat @@ -371,14 +371,14 @@ impl EuphRoom { fn list_room_key_bindings(&self, bindings: &mut KeyBindingsList, status: &RoomStatus) { match status { // Authenticating - RoomStatus::Connected(Status::Joining(Joining { + RoomStatus::Connected(ConnState::Joining(Joining { bounce: Some(_), .. })) => { bindings.binding("a", "authenticate"); } // Connected - RoomStatus::Connected(Status::Joined(_)) => { + RoomStatus::Connected(ConnState::Joined(_)) => { bindings.binding("n", "change nick"); bindings.binding("m", "download more messages"); bindings.binding("A", "show account ui"); @@ -397,7 +397,7 @@ impl EuphRoom { async fn handle_room_input_event(&mut self, event: &InputEvent, status: &RoomStatus) -> bool { match status { // Authenticating - RoomStatus::Connected(Status::Joining(Joining { + RoomStatus::Connected(ConnState::Joining(Joining { bounce: Some(_), .. })) => { if let key!('a') = event { @@ -407,7 +407,7 @@ impl EuphRoom { } // Joined - RoomStatus::Connected(Status::Joined(joined)) => match event { + RoomStatus::Connected(ConnState::Joined(joined)) => match event { key!('n') | key!('N') => { self.state = State::Nick(nick::new(joined.clone())); return true; @@ -512,7 +512,7 @@ impl EuphRoom { } if let key!('i') = event { - if let RoomStatus::Connected(Status::Joined(joined)) = status { + if let RoomStatus::Connected(ConnState::Joined(joined)) = status { if let Some(id) = self.nick_list.cursor() { if id == joined.session.session_id { self.state = @@ -536,7 +536,7 @@ impl EuphRoom { match self.focus { Focus::Chat => { - if let RoomStatus::Connected(Status::Joined(_)) = status { + if let RoomStatus::Connected(ConnState::Joined(_)) = status { bindings.binding("tab", "focus on nick list"); } @@ -570,7 +570,7 @@ impl EuphRoom { return true; } - if let RoomStatus::Connected(Status::Joined(_)) = status { + if let RoomStatus::Connected(ConnState::Joined(_)) = status { if let key!(Tab) = event { self.focus = Focus::NickList; return true; diff --git a/src/ui/rooms.rs b/src/ui/rooms.rs index f79cb1e..c0261be 100644 --- a/src/ui/rooms.rs +++ b/src/ui/rooms.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use crossterm::style::{ContentStyle, Stylize}; use euphoxide::api::SessionType; -use euphoxide::conn::{Joined, Status}; +use euphoxide::conn::{Joined, State as ConnState}; use parking_lot::FairMutex; use tokio::sync::mpsc; use toss::styled::Styled; @@ -240,11 +240,11 @@ impl Rooms { match status { RoomStatus::NoRoom | RoomStatus::Stopped => None, RoomStatus::Connecting => Some("connecting".to_string()), - RoomStatus::Connected(Status::Joining(j)) if j.bounce.is_some() => { + RoomStatus::Connected(ConnState::Joining(j)) if j.bounce.is_some() => { Some("auth required".to_string()) } - RoomStatus::Connected(Status::Joining(_)) => Some("joining".to_string()), - RoomStatus::Connected(Status::Joined(joined)) => Some(Self::format_pbln(&joined)), + RoomStatus::Connected(ConnState::Joining(_)) => Some("joining".to_string()), + RoomStatus::Connected(ConnState::Joined(joined)) => Some(Self::format_pbln(&joined)), } }