Skip to content

Commit

Permalink
implemented possibility to copy IPs from connection details page
Browse files Browse the repository at this point in the history
  • Loading branch information
GyulyVGC committed Dec 13, 2023
1 parent e9143e0 commit 0ef394c
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 14 deletions.
Binary file modified resources/fonts/subset/icons.ttf
Binary file not shown.
57 changes: 51 additions & 6 deletions src/gui/pages/connection_details_page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::gui::styles::style_constants::{get_font, get_font_headers, FONT_SIZE_
use crate::gui::styles::text::TextType;
use crate::gui::styles::types::gradient_type::GradientType;
use crate::gui::types::message::Message;
use crate::gui::types::timing_events::TimingEvents;
use crate::networking::manage_packets::{get_address_to_lookup, get_traffic_type, is_my_address};
use crate::networking::types::address_port_pair::AddressPortPair;
use crate::networking::types::host::Host;
Expand All @@ -28,6 +29,7 @@ use crate::translations::translations_2::{
fqdn_translation, mac_address_translation, socket_address_translation, source_translation,
transmitted_data_translation,
};
use crate::translations::translations_3::copy_translation;
use crate::utils::formatted_strings::{get_formatted_bytes_string_with_b, get_socket_address};
use crate::utils::types::icon::Icon;
use crate::{Language, Sniffer, StyleType};
Expand All @@ -37,7 +39,11 @@ pub fn connection_details_page(
key: AddressPortPair,
) -> Container<Message, Renderer<StyleType>> {
Container::new(lazy(
sniffer.runtime_data.tot_sent_packets + sniffer.runtime_data.tot_received_packets,
(
sniffer.runtime_data.tot_sent_packets + sniffer.runtime_data.tot_received_packets,
sniffer.timing_events.was_just_copy_ip(&key.address1),
sniffer.timing_events.was_just_copy_ip(&key.address2),
),
move |_| page_content(sniffer, &key),
))
}
Expand Down Expand Up @@ -116,6 +122,7 @@ fn page_content(
&val.mac_address1,
font,
language,
&sniffer.timing_events,
);
let mut dest_col = get_src_or_dest_col(
dest_caption,
Expand All @@ -124,6 +131,7 @@ fn page_content(
&val.mac_address2,
font,
language,
&sniffer.timing_events,
);

if address_to_lookup.eq(&key.address1) {
Expand Down Expand Up @@ -308,6 +316,7 @@ fn get_src_or_dest_col(
mac: &str,
font: Font,
language: Language,
timing_events: &TimingEvents,
) -> Column<'static, Message, Renderer<StyleType>> {
Column::new()
.spacing(4)
Expand All @@ -317,11 +326,17 @@ fn get_src_or_dest_col(
.align_x(Horizontal::Center),
)
.push(Rule::horizontal(10.0))
.push(TextType::highlighted_subtitle_with_desc(
socket_address_translation(language),
&get_socket_address(ip, port),
font,
))
.push(
Row::new()
.spacing(10)
.align_items(Alignment::End)
.push(TextType::highlighted_subtitle_with_desc(
socket_address_translation(language),
&get_socket_address(ip, port),
font,
))
.push(get_button_copy(language, font, ip, timing_events)),
)
.push(TextType::highlighted_subtitle_with_desc(
mac_address_translation(language),
mac,
Expand Down Expand Up @@ -359,3 +374,33 @@ fn assemble_widgets(
.push(vertical_space(Length::FillPortion(1))),
)
}

fn get_button_copy(
language: Language,
font: Font,
string: &String,
timing_events: &TimingEvents,
) -> Tooltip<'static, Message, Renderer<StyleType>> {
let icon = if timing_events.was_just_copy_ip(string) {
Text::new("✔").font(font).size(14)
} else {
Icon::Copy.to_text().size(12)
};

let content = button(
icon.horizontal_alignment(Horizontal::Center)
.vertical_alignment(Vertical::Center),
)
.padding(0)
.height(Length::Fixed(25.0))
.width(Length::Fixed(25.0))
.on_press(Message::CopyIp(string.clone()));

Tooltip::new(
content,
format!("{} (IP)", copy_translation(language)),
Position::Right,
)
.font(font)
.style(ContainerType::Tooltip)
}
2 changes: 2 additions & 0 deletions src/gui/types/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,6 @@ pub enum Message {
// CustomReport(String),
/// Save the configurations of the app and quit
CloseRequested,
/// Copies the given string to clipboard
CopyIp(String),
}
1 change: 1 addition & 0 deletions src/gui/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod message;
pub mod runtime_data;
pub mod sniffer;
pub mod timing_events;
20 changes: 12 additions & 8 deletions src/gui/types/sniffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
use std::collections::{HashSet, VecDeque};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

use iced::{window, Command};
use pcap::Device;
Expand All @@ -16,6 +15,7 @@ use crate::gui::pages::types::running_page::RunningPage;
use crate::gui::pages::types::settings_page::SettingsPage;
use crate::gui::styles::types::custom_palette::{CustomPalette, ExtraStyles};
use crate::gui::types::message::Message;
use crate::gui::types::timing_events::TimingEvents;
use crate::mmdb::asn::ASN_MMDB;
use crate::mmdb::country::COUNTRY_MMDB;
use crate::mmdb::types::mmdb_reader::MmdbReader;
Expand Down Expand Up @@ -75,8 +75,6 @@ pub struct Sniffer {
pub search: SearchParameters,
/// Current page number of inspect search results
pub page_number: usize,
/// Record the timestamp of last window focus
pub last_focus_time: std::time::Instant,
/// Application settings
pub settings: ConfigSettings,
/// Position and size of the app window
Expand All @@ -85,6 +83,8 @@ pub struct Sniffer {
pub country_mmdb_reader: Arc<MmdbReader>,
/// MMDB reader for ASN
pub asn_mmdb_reader: Arc<MmdbReader>,
/// Time-related events
pub timing_events: TimingEvents,
}

impl Sniffer {
Expand All @@ -108,14 +108,14 @@ impl Sniffer {
unread_notifications: 0,
search: SearchParameters::default(),
page_number: 1,
last_focus_time: std::time::Instant::now(),
settings: configs.settings.clone(),
window: configs.window,
country_mmdb_reader: Arc::new(MmdbReader::from(
&configs.settings.mmdb_country,
COUNTRY_MMDB,
)),
asn_mmdb_reader: Arc::new(MmdbReader::from(&configs.settings.mmdb_asn, ASN_MMDB)),
timing_events: TimingEvents::default(),
}
}

Expand Down Expand Up @@ -196,7 +196,7 @@ impl Sniffer {
Message::SwitchPage(next) => {
// To prevent SwitchPage be triggered when using `Alt` + `Tab` to switch back,
// first check if user switch back just now, and ignore the request for a short time.
if self.last_focus_time.elapsed() > Duration::from_millis(200) {
if !self.timing_events.was_just_focus() {
self.switch_page(next);
}
}
Expand Down Expand Up @@ -232,7 +232,7 @@ impl Sniffer {
}
}
}
Message::WindowFocused => self.last_focus_time = std::time::Instant::now(),
Message::WindowFocused => self.timing_events.focus_now(),
Message::GradientsSelection(gradient_type) => {
self.settings.color_gradient = gradient_type;
}
Expand Down Expand Up @@ -263,6 +263,10 @@ impl Sniffer {
self.get_configs().store();
return iced::window::close();
}
Message::CopyIp(string) => {
self.timing_events.copy_ip_now(string.clone());
return iced::clipboard::write(string);
}
_ => {}
}
Command::none()
Expand Down Expand Up @@ -1119,9 +1123,9 @@ mod tests {
}

#[test]
fn test_correctly_switch_running_and_notification_pages() {
fn test_correctly_switch_running_and_settings_pages() {
let mut sniffer = Sniffer::new(&Configs::default(), Arc::new(Mutex::new(None)));
sniffer.last_focus_time = std::time::Instant::now().sub(Duration::from_millis(400));
sniffer.timing_events.focus = std::time::Instant::now().sub(Duration::from_millis(400));

// initial status
assert_eq!(sniffer.settings_page, None);
Expand Down
39 changes: 39 additions & 0 deletions src/gui/types/timing_events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::time::Duration;

pub struct TimingEvents {
/// Timestamp of last window focus
pub focus: std::time::Instant,
/// Timestamp of the last press on Copy IP button, with the related IP address
pub copy_ip: (std::time::Instant, String),
}

impl TimingEvents {
const TIMEOUT_FOCUS: u64 = 200;
const TIMEOUT_COPY_IP: u64 = 1500;

pub fn focus_now(&mut self) {
self.focus = std::time::Instant::now();
}

pub fn was_just_focus(&self) -> bool {
self.focus.elapsed() < Duration::from_millis(TimingEvents::TIMEOUT_FOCUS)
}

pub fn copy_ip_now(&mut self, ip: String) {
self.copy_ip = (std::time::Instant::now(), ip);
}

pub fn was_just_copy_ip(&self, ip: &String) -> bool {
self.copy_ip.0.elapsed() < Duration::from_millis(TimingEvents::TIMEOUT_COPY_IP)
&& self.copy_ip.1.eq(ip)
}
}

impl Default for TimingEvents {
fn default() -> Self {
Self {
focus: std::time::Instant::now(),
copy_ip: (std::time::Instant::now(), String::new()),
}
}
}
8 changes: 8 additions & 0 deletions src/translations/translations_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,11 @@ pub fn custom_style_translation(language: Language) -> &'static str {
_ => "Custom style",
}
}

pub fn copy_translation(language: Language) -> &'static str {
match language {
Language::EN => "Copy",
Language::IT => "Copia",
_ => "Copy",
}
}
2 changes: 2 additions & 0 deletions src/utils/types/icon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub enum Icon {
Bin,
BytesThreshold,
Clock,
Copy,
Dots,
Error,
// File,
Expand Down Expand Up @@ -74,6 +75,7 @@ impl Icon {
Icon::Star => "g",
Icon::Warning => "T",
Icon::Waves => "y",
Icon::Copy => "u",
})
.font(ICONS)
}
Expand Down

0 comments on commit 0ef394c

Please sign in to comment.