Skip to content

Commit

Permalink
Merge pull request #145 from squidowl/fix/better-whois-routing
Browse files Browse the repository at this point in the history
Route whois on last sent buffer
  • Loading branch information
tarkah authored Jul 12, 2023
2 parents caa024d + bb28a31 commit 883812b
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 52 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Fixed:

- Changes done in the config file are now properly applied to the old buffers
- Text and colors on light themes will no longer appear washed out
- All WHOIS responses are now properly routed to the buffer where the request was made (text input or via context menu)

# 2023.2 (2023-07-07)

Expand Down
91 changes: 70 additions & 21 deletions data/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ pub enum Brodcast {
#[derive(Debug)]
pub enum Event {
Single(message::Encoded, Nick),
WithSource(message::Encoded, Nick, message::Source),
Brodcast(Brodcast),
Whois(message::Encoded, Nick, Option<Buffer>),
}

#[derive(Debug)]
Expand All @@ -56,6 +56,7 @@ pub struct Connection {
users: HashMap<String, Vec<User>>,
labels: HashMap<String, Context>,
batches: HashMap<String, Batch>,
reroute_responses_to: Option<Buffer>,
supports_labels: bool,
}

Expand All @@ -68,6 +69,7 @@ impl Connection {
users: HashMap::new(),
labels: HashMap::new(),
batches: HashMap::new(),
reroute_responses_to: None,
supports_labels: false,
}
}
Expand Down Expand Up @@ -95,6 +97,8 @@ impl Connection {
message.tags = Some(vec![Tag("label".to_string(), Some(label))]);
}

self.reroute_responses_to = start_reroute(&message.command).then(|| buffer.clone());

if let Err(e) = self.client.send(message) {
log::warn!("Error sending message: {e}");
}
Expand All @@ -103,7 +107,15 @@ impl Connection {
fn receive(&mut self, message: message::Encoded) -> Vec<Event> {
log::trace!("Message received => {:?}", *message);

self.handle(message, None).unwrap_or_default()
let stop_reroute = stop_reroute(&message.command);

let events = self.handle(message, None).unwrap_or_default();

if stop_reroute {
self.reroute_responses_to = None;
}

events
}

fn handle(
Expand Down Expand Up @@ -170,6 +182,33 @@ impl Connection {
return Some(events);
}
}
// Label context whois
_ if context.as_ref().map(Context::is_whois).unwrap_or_default() => {
if let Some(source) = context
.map(Context::buffer)
.map(Buffer::server_message_source)
{
return Some(vec![Event::WithSource(
message,
self.nickname().to_owned(),
source,
)]);
}
}
// Reroute responses
Command::Response(..) | Command::Raw(..) if self.reroute_responses_to.is_some() => {
if let Some(source) = self
.reroute_responses_to
.clone()
.map(Buffer::server_message_source)
{
return Some(vec![Event::WithSource(
message,
self.nickname().to_owned(),
source,
)]);
}
}
Command::CAP(_, CapSubCommand::ACK, a, b) => {
let cap_str = if b.is_none() { a.as_ref() } else { b.as_ref() }?;
let caps = cap_str.split(' ').collect::<Vec<_>>();
Expand Down Expand Up @@ -208,25 +247,6 @@ impl Connection {
self.resolved_nick = Some(nick.to_string());
}
}
// WHOIS
_ if context.as_ref().map(Context::is_whois).unwrap_or_default() => {
return Some(vec![Event::Whois(
message,
self.nickname().to_owned(),
context.map(Context::buffer),
)]);
}
Command::Response(
RPL_WHOISCERTFP | RPL_WHOISCHANNELS | RPL_WHOISIDLE | RPL_WHOISKEYVALUE
| RPL_WHOISOPERATOR | RPL_WHOISSERVER | RPL_WHOISUSER | RPL_ENDOFWHOIS,
_,
) => {
return Some(vec![Event::Whois(
message,
self.nickname().to_owned(),
context.map(Context::buffer),
)])
}
// QUIT
Command::QUIT(comment) => {
let user = message.user()?;
Expand Down Expand Up @@ -445,3 +465,32 @@ fn remove_tag(key: &str, tags: Option<&mut Vec<irc::proto::message::Tag>>) -> Op

tags.remove(tags.iter().position(|tag| tag.0 == key)?).1
}

fn start_reroute(command: &irc::proto::Command) -> bool {
use irc::proto::Command;

matches!(
command,
Command::WHO(..) | Command::WHOIS(..) | Command::WHOWAS(..)
)
}

fn stop_reroute(command: &irc::proto::Command) -> bool {
use irc::proto::Command;
use irc::proto::Response::*;

matches!(
command,
Command::Response(
RPL_ENDOFWHO
| RPL_ENDOFWHOIS
| RPL_ENDOFWHOWAS
| ERR_NOSUCHNICK
| ERR_NOSUCHSERVER
| ERR_NONICKNAMEGIVEN
| ERR_WASNOSUCHNICK
| ERR_NEEDMOREPARAMS,
_
)
)
}
4 changes: 4 additions & 0 deletions data/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ impl Message {
text,
})
}

pub fn with_source(self, source: Source) -> Self {
Self { source, ..self }
}
}

fn source(message: Encoded, our_nick: &Nick) -> Option<Source> {
Expand Down
5 changes: 3 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,11 +345,12 @@ impl Application for Halloy {
dashboard.record_message(&server, message);
}
}
data::client::Event::Whois(encoded, our_nick, buffer) => {
data::client::Event::WithSource(encoded, our_nick, source) => {
if let Some(message) =
data::Message::received(encoded, our_nick)
{
dashboard.record_whois(&server, message, buffer);
dashboard
.record_message(&server, message.with_source(source));
}
}
data::client::Event::Brodcast(brodcast) => match brodcast {
Expand Down
30 changes: 1 addition & 29 deletions src/screen/dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::time::{Duration, Instant};

use data::history::manager::Broadcast;
use data::user::Nick;
use data::{history, message, Config, Server, User};
use data::{history, Config, Server, User};
use iced::widget::pane_grid::{self, PaneGrid};
use iced::widget::{container, row};
use iced::{clipboard, window, Command, Length, Subscription};
Expand Down Expand Up @@ -499,29 +499,6 @@ impl Dashboard {
self.history.record_message(server, message);
}

pub fn record_whois(
&mut self,
server: &Server,
mut message: data::Message,
buffer: Option<data::Buffer>,
) {
// If server supports labels, we should receive the buffer sent from. Otherwise
// fallback to the focused buffer for the server.
let buffer = buffer.or_else(|| {
self.get_focused().and_then(|pane| {
pane.buffer
.data()
.and_then(|buffer| (buffer.server() == server).then_some(buffer))
})
});

message.source = buffer
.map(|buffer| buffer.server_message_source())
.unwrap_or(message::Source::Server);

self.history.record_message(server, message);
}

pub fn broadcast_quit(
&mut self,
server: &Server,
Expand Down Expand Up @@ -580,11 +557,6 @@ impl Dashboard {
.broadcast(server, Broadcast::ConnectionFailed { error });
}

fn get_focused(&mut self) -> Option<&Pane> {
let pane = self.focus?;
self.panes.get(&pane)
}

fn get_focused_mut(&mut self) -> Option<(pane_grid::Pane, &mut Pane)> {
let pane = self.focus?;
self.panes.get_mut(&pane).map(|state| (pane, state))
Expand Down

0 comments on commit 883812b

Please sign in to comment.