mirror of
https://github.com/alexpasmantier/television.git
synced 2025-07-29 14:21:43 +00:00
fix(themes): selection_fg
was not applied correctly + code improvements
Fixes #636
This commit is contained in:
parent
1bbda8e62f
commit
fb97f011be
@ -7,7 +7,9 @@ use ratatui::layout::Alignment;
|
|||||||
use ratatui::layout::Rect;
|
use ratatui::layout::Rect;
|
||||||
use ratatui::prelude::{Line, Style};
|
use ratatui::prelude::{Line, Style};
|
||||||
use ratatui::style::Color;
|
use ratatui::style::Color;
|
||||||
use ratatui::widgets::{Block, BorderType, Borders, ListDirection, Padding};
|
use ratatui::widgets::{
|
||||||
|
Block, BorderType, Borders, ListDirection, ListState, Padding,
|
||||||
|
};
|
||||||
use television::channels::prototypes::ChannelPrototype;
|
use television::channels::prototypes::ChannelPrototype;
|
||||||
use television::picker::Movement;
|
use television::picker::Movement;
|
||||||
use television::{
|
use television::{
|
||||||
@ -390,9 +392,7 @@ pub fn draw_results_list(c: &mut Criterion) {
|
|||||||
];
|
];
|
||||||
|
|
||||||
let colorscheme = ResultsColorscheme {
|
let colorscheme = ResultsColorscheme {
|
||||||
result_name_fg: Color::Indexed(222),
|
result_fg: Color::Indexed(222),
|
||||||
result_preview_fg: Color::Indexed(222),
|
|
||||||
result_line_number_fg: Color::Indexed(222),
|
|
||||||
result_selected_fg: Color::Indexed(222),
|
result_selected_fg: Color::Indexed(222),
|
||||||
result_selected_bg: Color::Indexed(222),
|
result_selected_bg: Color::Indexed(222),
|
||||||
match_foreground_color: Color::Indexed(222),
|
match_foreground_color: Color::Indexed(222),
|
||||||
@ -411,6 +411,7 @@ pub fn draw_results_list(c: &mut Criterion) {
|
|||||||
.style(Style::default())
|
.style(Style::default())
|
||||||
.padding(Padding::right(1)),
|
.padding(Padding::right(1)),
|
||||||
&entries,
|
&entries,
|
||||||
|
&ListState::default(),
|
||||||
ListDirection::BottomToTop,
|
ListDirection::BottomToTop,
|
||||||
false,
|
false,
|
||||||
&colorscheme,
|
&colorscheme,
|
||||||
|
@ -477,9 +477,7 @@ impl Into<HelpColorscheme> for &Theme {
|
|||||||
impl Into<ResultsColorscheme> for &Theme {
|
impl Into<ResultsColorscheme> for &Theme {
|
||||||
fn into(self) -> ResultsColorscheme {
|
fn into(self) -> ResultsColorscheme {
|
||||||
ResultsColorscheme {
|
ResultsColorscheme {
|
||||||
result_name_fg: (&self.result_name_fg).into(),
|
result_fg: (&self.result_name_fg).into(),
|
||||||
result_preview_fg: (&self.result_value_fg).into(),
|
|
||||||
result_line_number_fg: (&self.result_line_number_fg).into(),
|
|
||||||
result_selected_bg: (&self.selection_bg).into(),
|
result_selected_bg: (&self.selection_bg).into(),
|
||||||
result_selected_fg: (&self.selection_fg).into(),
|
result_selected_fg: (&self.selection_fg).into(),
|
||||||
match_foreground_color: (&self.match_fg).into(),
|
match_foreground_color: (&self.match_fg).into(),
|
||||||
|
@ -24,9 +24,7 @@ pub struct HelpColorscheme {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
|
||||||
pub struct ResultsColorscheme {
|
pub struct ResultsColorscheme {
|
||||||
pub result_name_fg: Color,
|
pub result_fg: Color,
|
||||||
pub result_preview_fg: Color,
|
|
||||||
pub result_line_number_fg: Color,
|
|
||||||
pub result_selected_bg: Color,
|
pub result_selected_bg: Color,
|
||||||
pub result_selected_fg: Color,
|
pub result_selected_fg: Color,
|
||||||
pub match_foreground_color: Color,
|
pub match_foreground_color: Color,
|
||||||
|
@ -255,6 +255,7 @@ fn draw_rc_channels(
|
|||||||
let channel_list = result_item::build_results_list(
|
let channel_list = result_item::build_results_list(
|
||||||
rc_block,
|
rc_block,
|
||||||
entries,
|
entries,
|
||||||
|
picker_state,
|
||||||
ListDirection::TopToBottom,
|
ListDirection::TopToBottom,
|
||||||
use_nerd_font_icons,
|
use_nerd_font_icons,
|
||||||
&colorscheme.results,
|
&colorscheme.results,
|
||||||
|
@ -13,7 +13,7 @@ use devicons::FileIcon;
|
|||||||
use ratatui::{
|
use ratatui::{
|
||||||
prelude::{Color, Line, Span, Style},
|
prelude::{Color, Line, Span, Style},
|
||||||
style::Stylize,
|
style::Stylize,
|
||||||
widgets::{Block, List, ListDirection},
|
widgets::{Block, List, ListDirection, ListState},
|
||||||
};
|
};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
@ -42,12 +42,17 @@ pub trait ResultItem {
|
|||||||
/// Build a single `Line` for a [`ResultItem`].
|
/// Build a single `Line` for a [`ResultItem`].
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
// TODO: pass the right colors directly as arguments and make the
|
||||||
|
// calling function responsible for the colors used for each line.
|
||||||
pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
||||||
item: &'a T,
|
item: &'a T,
|
||||||
use_icons: bool,
|
use_icons: bool,
|
||||||
colorscheme: &ResultsColorscheme,
|
selection_fg: Color,
|
||||||
|
result_fg: Color,
|
||||||
|
match_fg: Color,
|
||||||
area_width: u16,
|
area_width: u16,
|
||||||
prefix: Option<bool>, // Some(true)=selected ●, Some(false)=unselected, None=no prefix
|
// Some(true)=selected ●, Some(false)=unselected, None=no prefix
|
||||||
|
prefix: Option<bool>,
|
||||||
) -> Line<'a> {
|
) -> Line<'a> {
|
||||||
// PERF: Pre-allocate spans vector with estimated capacity
|
// PERF: Pre-allocate spans vector with estimated capacity
|
||||||
let mut spans = Vec::<Span<'a>>::with_capacity(16);
|
let mut spans = Vec::<Span<'a>>::with_capacity(16);
|
||||||
@ -57,7 +62,7 @@ pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
|||||||
if selected {
|
if selected {
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
SELECTED_SYMBOL,
|
SELECTED_SYMBOL,
|
||||||
Style::default().fg(colorscheme.result_selected_fg),
|
Style::default().fg(selection_fg),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
spans.push(Span::raw(DESELECTED_SYMBOL));
|
spans.push(Span::raw(DESELECTED_SYMBOL));
|
||||||
@ -111,10 +116,7 @@ pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
|||||||
|
|
||||||
// PERF: Early return for empty match ranges - common case optimization
|
// PERF: Early return for empty match ranges - common case optimization
|
||||||
if match_ranges.is_empty() {
|
if match_ranges.is_empty() {
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(entry_name, Style::default().fg(result_fg)));
|
||||||
entry_name,
|
|
||||||
Style::default().fg(colorscheme.result_name_fg),
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
// PERF: Collect chars once to avoid repeated Unicode parsing
|
// PERF: Collect chars once to avoid repeated Unicode parsing
|
||||||
let chars: Vec<char> = entry_name.chars().collect();
|
let chars: Vec<char> = entry_name.chars().collect();
|
||||||
@ -131,7 +133,7 @@ pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
|||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
text,
|
text,
|
||||||
Style::default().fg(colorscheme.result_name_fg),
|
Style::default().fg(result_fg),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,8 +145,7 @@ pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
|||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
text,
|
text,
|
||||||
Style::default()
|
Style::default().fg(match_fg),
|
||||||
.fg(colorscheme.match_foreground_color),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,10 +157,7 @@ pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
|||||||
if last_end < name_len {
|
if last_end < name_len {
|
||||||
let text: String = chars[last_end..].iter().collect();
|
let text: String = chars[last_end..].iter().collect();
|
||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(text, Style::default().fg(result_fg)));
|
||||||
text,
|
|
||||||
Style::default().fg(colorscheme.result_name_fg),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +168,7 @@ pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
|||||||
match binding {
|
match binding {
|
||||||
Binding::SingleKey(k) => spans.push(Span::styled(
|
Binding::SingleKey(k) => spans.push(Span::styled(
|
||||||
k.to_string(),
|
k.to_string(),
|
||||||
Style::default().fg(colorscheme.match_foreground_color),
|
Style::default().fg(match_fg),
|
||||||
)),
|
)),
|
||||||
Binding::MultipleKeys(keys) => {
|
Binding::MultipleKeys(keys) => {
|
||||||
for (i, k) in keys.iter().enumerate() {
|
for (i, k) in keys.iter().enumerate() {
|
||||||
@ -179,8 +177,7 @@ pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
|||||||
}
|
}
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
k.to_string(),
|
k.to_string(),
|
||||||
Style::default()
|
Style::default().fg(match_fg),
|
||||||
.fg(colorscheme.match_foreground_color),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,6 +192,7 @@ pub fn build_result_line<'a, T: ResultItem + ?Sized>(
|
|||||||
pub fn build_results_list<'a, 'b, T, F>(
|
pub fn build_results_list<'a, 'b, T, F>(
|
||||||
block: Block<'b>,
|
block: Block<'b>,
|
||||||
entries: &'a [T],
|
entries: &'a [T],
|
||||||
|
relative_picker_state: &ListState,
|
||||||
list_direction: ListDirection,
|
list_direction: ListDirection,
|
||||||
use_icons: bool,
|
use_icons: bool,
|
||||||
colorscheme: &ResultsColorscheme,
|
colorscheme: &ResultsColorscheme,
|
||||||
@ -206,10 +204,22 @@ where
|
|||||||
T: ResultItem,
|
T: ResultItem,
|
||||||
F: FnMut(&T) -> Option<bool>,
|
F: FnMut(&T) -> Option<bool>,
|
||||||
{
|
{
|
||||||
use ratatui::widgets::List;
|
List::new(entries.iter().enumerate().map(|(i, e)| {
|
||||||
List::new(entries.iter().map(|e| {
|
|
||||||
let prefix = prefix_fn(e);
|
let prefix = prefix_fn(e);
|
||||||
build_result_line(e, use_icons, colorscheme, area_width, prefix)
|
let result_fg = if relative_picker_state.selected() == Some(i) {
|
||||||
|
colorscheme.result_selected_fg
|
||||||
|
} else {
|
||||||
|
colorscheme.result_fg
|
||||||
|
};
|
||||||
|
build_result_line(
|
||||||
|
e,
|
||||||
|
use_icons,
|
||||||
|
colorscheme.result_selected_fg,
|
||||||
|
result_fg,
|
||||||
|
colorscheme.match_foreground_color,
|
||||||
|
area_width,
|
||||||
|
prefix,
|
||||||
|
)
|
||||||
}))
|
}))
|
||||||
.direction(list_direction)
|
.direction(list_direction)
|
||||||
.highlight_style(
|
.highlight_style(
|
||||||
@ -223,7 +233,6 @@ where
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::channels::entry::Entry;
|
use crate::channels::entry::Entry;
|
||||||
use crate::screen::colors::ResultsColorscheme;
|
|
||||||
use ratatui::prelude::{Color, Span};
|
use ratatui::prelude::{Color, Span};
|
||||||
use ratatui::text::Line;
|
use ratatui::text::Line;
|
||||||
|
|
||||||
@ -234,7 +243,9 @@ mod tests {
|
|||||||
let line = build_result_line(
|
let line = build_result_line(
|
||||||
&entry,
|
&entry,
|
||||||
false,
|
false,
|
||||||
&ResultsColorscheme::default(),
|
Color::Reset,
|
||||||
|
Color::Reset,
|
||||||
|
Color::Reset,
|
||||||
200,
|
200,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@ -258,7 +269,9 @@ mod tests {
|
|||||||
let line = build_result_line(
|
let line = build_result_line(
|
||||||
&entry,
|
&entry,
|
||||||
false,
|
false,
|
||||||
&ResultsColorscheme::default(),
|
Color::Reset,
|
||||||
|
Color::Reset,
|
||||||
|
Color::Reset,
|
||||||
20, // small width
|
20, // small width
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -44,6 +44,7 @@ pub fn draw_results_list(
|
|||||||
let results_list = result_item::build_results_list(
|
let results_list = result_item::build_results_list(
|
||||||
results_block,
|
results_block,
|
||||||
entries,
|
entries,
|
||||||
|
relative_picker_state,
|
||||||
list_direction,
|
list_direction,
|
||||||
use_nerd_font_icons,
|
use_nerd_font_icons,
|
||||||
&colorscheme.results,
|
&colorscheme.results,
|
||||||
|
@ -69,7 +69,7 @@ pub fn draw_status_bar(f: &mut Frame<'_>, area: Rect, ctx: &Ctx) {
|
|||||||
// Add channel-specific info in Channel mode
|
// Add channel-specific info in Channel mode
|
||||||
if ctx.tv_state.mode == Mode::Channel {
|
if ctx.tv_state.mode == Mode::Channel {
|
||||||
let name_style = Style::default()
|
let name_style = Style::default()
|
||||||
.fg(ctx.colorscheme.results.result_name_fg)
|
.fg(ctx.colorscheme.results.result_fg)
|
||||||
.add_modifier(Modifier::BOLD);
|
.add_modifier(Modifier::BOLD);
|
||||||
|
|
||||||
// Channel name
|
// Channel name
|
||||||
@ -89,7 +89,7 @@ pub fn draw_status_bar(f: &mut Frame<'_>, area: Rect, ctx: &Ctx) {
|
|||||||
Span::styled(
|
Span::styled(
|
||||||
format!("{} selected", selected_count),
|
format!("{} selected", selected_count),
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(ctx.colorscheme.results.result_name_fg)
|
.fg(ctx.colorscheme.results.result_fg)
|
||||||
.add_modifier(Modifier::ITALIC),
|
.add_modifier(Modifier::ITALIC),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
@ -191,7 +191,7 @@ pub fn draw_status_bar(f: &mut Frame<'_>, area: Rect, ctx: &Ctx) {
|
|||||||
let right_spans = vec![Span::styled(
|
let right_spans = vec![Span::styled(
|
||||||
format!("v{} ", ctx.app_metadata.version),
|
format!("v{} ", ctx.app_metadata.version),
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(ctx.colorscheme.results.result_name_fg)
|
.fg(ctx.colorscheme.results.result_fg)
|
||||||
.add_modifier(Modifier::ITALIC),
|
.add_modifier(Modifier::ITALIC),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
|
@ -20,4 +20,3 @@ channel_mode_fg = '#1e1e2e'
|
|||||||
channel_mode_bg = '#f5c2e7'
|
channel_mode_bg = '#f5c2e7'
|
||||||
remote_control_mode_fg = '#1e1e2e'
|
remote_control_mode_fg = '#1e1e2e'
|
||||||
remote_control_mode_bg = '#a6e3a1'
|
remote_control_mode_bg = '#a6e3a1'
|
||||||
send_to_channel_mode_fg = '#89dceb'
|
|
||||||
|
@ -16,6 +16,8 @@ match_fg = '#FF5555'
|
|||||||
# preview
|
# preview
|
||||||
preview_title_fg = '#50FA7B'
|
preview_title_fg = '#50FA7B'
|
||||||
# modes
|
# modes
|
||||||
channel_mode_fg = '#8BE9FD'
|
channel_mode_fg = '#282A36'
|
||||||
remote_control_mode_fg = '#FFB86C'
|
channel_mode_bg = '#8BE9FD'
|
||||||
|
remote_control_mode_fg = '#282A36'
|
||||||
|
remote_control_mode_bg = '#FFB86C'
|
||||||
send_to_channel_mode_fg = '#FF79C6'
|
send_to_channel_mode_fg = '#FF79C6'
|
||||||
|
@ -20,4 +20,3 @@ channel_mode_fg = '#282828'
|
|||||||
channel_mode_bg = '#b16286'
|
channel_mode_bg = '#b16286'
|
||||||
remote_control_mode_fg = '#282828'
|
remote_control_mode_fg = '#282828'
|
||||||
remote_control_mode_bg = '#8ec07c'
|
remote_control_mode_bg = '#8ec07c'
|
||||||
send_to_channel_mode_fg = '#458588'
|
|
||||||
|
@ -16,7 +16,7 @@ match_fg = '#af3a03'
|
|||||||
# preview
|
# preview
|
||||||
preview_title_fg = '#98971a'
|
preview_title_fg = '#98971a'
|
||||||
# modes
|
# modes
|
||||||
channel_mode_fg = '#d65d0e'
|
channel_mode_fg = '#504945'
|
||||||
remote_control_mode_fg = '#689d6a'
|
channel_mode_bg = '#d65d0e'
|
||||||
send_to_channel_mode_fg = '#458588'
|
remote_control_mode_fg = '#504945'
|
||||||
|
remote_control_mode_bg = '#d79921'
|
||||||
|
@ -16,6 +16,7 @@ match_fg = '#f92672'
|
|||||||
# preview
|
# preview
|
||||||
preview_title_fg = '#fd971f'
|
preview_title_fg = '#fd971f'
|
||||||
# modes
|
# modes
|
||||||
channel_mode_fg = '#fd971f'
|
channel_mode_fg = '#2e2e2e'
|
||||||
remote_control_mode_fg = '#a6e22e'
|
channel_mode_bg = '#fd971f'
|
||||||
send_to_channel_mode_fg = '#66d9ef'
|
remote_control_mode_fg = '#2e2e2e'
|
||||||
|
remote_control_mode_bg = '#a6e22e'
|
||||||
|
@ -16,6 +16,7 @@ match_fg = '#bf616a'
|
|||||||
# preview
|
# preview
|
||||||
preview_title_fg = '#8fbcbb'
|
preview_title_fg = '#8fbcbb'
|
||||||
# modes
|
# modes
|
||||||
channel_mode_fg = '#b48ead'
|
channel_mode_fg = '#2e3440'
|
||||||
remote_control_mode_fg = '#a3be8c'
|
channel_mode_bg = '#b48ead'
|
||||||
send_to_channel_mode_fg = '#d08770'
|
remote_control_mode_fg = '#2e3440'
|
||||||
|
remote_control_mode_bg = '#a3be8c'
|
||||||
|
@ -16,6 +16,7 @@ match_fg = '#e06c75'
|
|||||||
# preview
|
# preview
|
||||||
preview_title_fg = '#61afef'
|
preview_title_fg = '#61afef'
|
||||||
# modes
|
# modes
|
||||||
channel_mode_fg = '#61afef'
|
channel_mode_fg = '#2c323c'
|
||||||
remote_control_mode_fg = '#98c379'
|
channel_mode_bg = '#61afef'
|
||||||
send_to_channel_mode_fg = '#c678dd'
|
remote_control_mode_fg = '#2c323c'
|
||||||
|
remote_control_mode_bg = '#98c379'
|
||||||
|
@ -16,6 +16,7 @@ match_fg = '#cb4b16'
|
|||||||
# preview
|
# preview
|
||||||
preview_title_fg = '#859900'
|
preview_title_fg = '#859900'
|
||||||
# modes
|
# modes
|
||||||
channel_mode_fg = '#2aa198'
|
channel_mode_fg = '#002b36'
|
||||||
remote_control_mode_fg = '#859900'
|
channel_mode_bg = '#2aa198'
|
||||||
send_to_channel_mode_fg = '#dc322f'
|
remote_control_mode_fg = '#002b36'
|
||||||
|
remote_control_mode_bg = '#b58900'
|
||||||
|
@ -16,6 +16,7 @@ match_fg = '#cb4b16'
|
|||||||
# preview
|
# preview
|
||||||
preview_title_fg = '#859900'
|
preview_title_fg = '#859900'
|
||||||
# modes
|
# modes
|
||||||
channel_mode_fg = '#2aa198'
|
channel_mode_fg = '#fdf6e3'
|
||||||
remote_control_mode_fg = '#859900'
|
channel_mode_bg = '#2aa198'
|
||||||
send_to_channel_mode_fg = '#dc322f'
|
remote_control_mode_fg = '#fdf6e3'
|
||||||
|
remote_control_mode_bg = '#859900'
|
||||||
|
@ -17,6 +17,7 @@ match_fg = '#d2788c'
|
|||||||
# preview
|
# preview
|
||||||
preview_title_fg = '#d2a374'
|
preview_title_fg = '#d2a374'
|
||||||
# modes
|
# modes
|
||||||
channel_mode_fg = '#8faf77'
|
channel_mode_fg = '#18191a'
|
||||||
remote_control_mode_fg = '#d2a374'
|
channel_mode_bg = '#8faf77'
|
||||||
send_to_channel_mode_fg = '#d2788c'
|
remote_control_mode_fg = '#18191a'
|
||||||
|
remote_control_mode_bg = '#d2a374'
|
||||||
|
@ -16,7 +16,7 @@ match_fg = '#f7768e'
|
|||||||
# preview
|
# preview
|
||||||
preview_title_fg = '#bb9af7'
|
preview_title_fg = '#bb9af7'
|
||||||
# modes
|
# modes
|
||||||
channel_mode_fg = '#faba4a'
|
channel_mode_fg = '#1a1b26'
|
||||||
remote_control_mode_fg = '#9ece6a'
|
channel_mode_bg = '#faba4a'
|
||||||
send_to_channel_mode_fg = '#a4daff'
|
remote_control_mode_fg = '#1a1b26'
|
||||||
|
remote_control_mode_bg = '#9ece6a'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user