1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use clashctl_interactive::RuleSort;
use tui::{
style::{Color, Modifier, Style},
text::{Span, Spans},
widgets::Widget,
};
use crate::{
components::{MovableList, MovableListItem, MovableListState},
define_widget,
model::{Rule, RuleType, Rules},
AsColor,
};
define_widget!(RulePage);
impl<'a> Widget for RulePage<'a> {
fn render(self, area: tui::layout::Rect, buf: &mut tui::buffer::Buffer) {
MovableList::new("Rules", &self.state.rule_state).render(area, buf);
}
}
impl AsColor for RuleType {
fn as_color(&self) -> tui::style::Color {
match self {
RuleType::Domain => Color::Green,
RuleType::DomainSuffix => Color::Green,
RuleType::DomainKeyword => Color::Green,
RuleType::GeoIP => Color::Yellow,
RuleType::IPCIDR => Color::Yellow,
RuleType::SrcIPCIDR => Color::Yellow,
RuleType::SrcPort => Color::Yellow,
RuleType::DstPort => Color::Yellow,
RuleType::Process => Color::Yellow,
RuleType::Match => Color::Blue,
RuleType::Direct => Color::Blue,
RuleType::Reject => Color::Red,
RuleType::Unknown => Color::DarkGray,
}
}
}
impl<'a> From<Rules> for MovableListState<'a, Rule, RuleSort> {
fn from(val: Rules) -> Self {
Self::new_with_sort(val.rules, RuleSort::default())
}
}
impl<'a> MovableListItem<'a> for Rule {
fn to_spans(&self) -> Spans<'a> {
let type_color = self.rule_type.as_color();
let name_color = if self.proxy == "DIRECT" || self.proxy == "REJECT" {
Color::DarkGray
} else {
Color::Yellow
};
let gray = Style::default().fg(Color::DarkGray);
let r_type: &'static str = self.rule_type.into();
let payload = if self.payload.is_empty() {
"*"
} else {
&self.payload
}
.to_owned();
let dash: String = "─".repeat(35_usize.saturating_sub(payload.len()) + 2) + " ";
vec![
Span::styled(format!("{:16}", r_type), Style::default().fg(type_color)),
Span::styled(payload + " ", Style::default().add_modifier(Modifier::BOLD)),
Span::styled(dash, gray),
Span::styled(self.proxy.to_owned(), Style::default().fg(name_color)),
]
.into()
}
}