mirror of
https://github.com/Xithrius/twitch-tui.git
synced 2024-09-11 05:35:26 +03:00
Data builder payload converted to string type
This commit is contained in:
parent
76dd136b28
commit
4ddaf5b733
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -1367,14 +1367,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"parking_lot 0.12.1",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.42.0",
|
||||
|
@ -15,7 +15,7 @@ categories = ["command-line-utilities"]
|
||||
[dependencies]
|
||||
crossterm = "0.25.0"
|
||||
tui = { version = "0.19.0", default-features = false, features = [ "crossterm" ] }
|
||||
tokio = { version = "1.23.0", features = [ "full" ] }
|
||||
tokio = { version = "1.23.0", features = [ "rt", "macros", "rt-multi-thread" ] }
|
||||
clap = { version = "4.0.29", features = [ "derive", "cargo" ] }
|
||||
serde = { version = "1.0.149", features = [ "derive" ] }
|
||||
serde_json = "1.0.89"
|
||||
|
@ -21,60 +21,24 @@ lazy_static! {
|
||||
pub static ref FUZZY_FINDER: SkimMatcherV2 = SkimMatcherV2::default();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PayLoad {
|
||||
Message(String),
|
||||
Err(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct DataBuilder<'conf> {
|
||||
pub date_format: &'conf str,
|
||||
}
|
||||
|
||||
impl<'conf> DataBuilder<'conf> {
|
||||
pub const fn new(date_format: &'conf str) -> Self {
|
||||
DataBuilder { date_format }
|
||||
}
|
||||
|
||||
pub fn user(user: String, message: String) -> Data {
|
||||
Data {
|
||||
time_sent: Local::now(),
|
||||
author: user,
|
||||
system: false,
|
||||
payload: PayLoad::Message(message),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn system(self, message: String) -> Data {
|
||||
Data {
|
||||
time_sent: Local::now(),
|
||||
author: "System".to_string(),
|
||||
system: true,
|
||||
payload: PayLoad::Message(message),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn twitch(self, message: String) -> Data {
|
||||
Data {
|
||||
time_sent: Local::now(),
|
||||
author: "Twitch".to_string(),
|
||||
system: true,
|
||||
payload: PayLoad::Message(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Data {
|
||||
pub time_sent: DateTime<Local>,
|
||||
pub author: String,
|
||||
pub system: bool,
|
||||
pub payload: PayLoad,
|
||||
pub payload: String,
|
||||
}
|
||||
|
||||
impl Data {
|
||||
pub fn new(author: String, system: bool, payload: String) -> Self {
|
||||
Self {
|
||||
time_sent: Local::now(),
|
||||
author,
|
||||
system,
|
||||
payload,
|
||||
}
|
||||
}
|
||||
|
||||
fn hash_username(&self, palette: &Palette) -> Color {
|
||||
let hash = f64::from(
|
||||
self.author
|
||||
@ -104,11 +68,7 @@ impl Data {
|
||||
username_highlight: Option<String>,
|
||||
theme_style: Style,
|
||||
) -> (Vec<Row>, u32) {
|
||||
let message = if let PayLoad::Message(m) = &self.payload {
|
||||
textwrap::fill(m.as_str(), limit)
|
||||
} else {
|
||||
panic!("Data.to_row() can only take an enum of PayLoad::Message.");
|
||||
};
|
||||
let message = textwrap::fill(self.payload.as_str(), limit);
|
||||
|
||||
let username_highlight_style = username_highlight.map_or_else(Style::default, |username| {
|
||||
if Regex::new(format!("^.*{username}.*$").as_str())
|
||||
@ -216,6 +176,29 @@ impl Data {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct DataBuilder<'conf> {
|
||||
pub date_format: &'conf str,
|
||||
}
|
||||
|
||||
impl<'conf> DataBuilder<'conf> {
|
||||
pub const fn new(date_format: &'conf str) -> Self {
|
||||
DataBuilder { date_format }
|
||||
}
|
||||
|
||||
pub fn user(user: String, payload: String) -> Data {
|
||||
Data::new(user, false, payload)
|
||||
}
|
||||
|
||||
pub fn system(self, payload: String) -> Data {
|
||||
Data::new("System".to_string(), true, payload)
|
||||
}
|
||||
|
||||
pub fn twitch(self, payload: String) -> Data {
|
||||
Data::new("Twitch".to_string(), true, payload)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -223,13 +206,8 @@ mod tests {
|
||||
#[test]
|
||||
fn test_username_hash() {
|
||||
assert_eq!(
|
||||
Data {
|
||||
time_sent: Local::now(),
|
||||
author: "human".to_string(),
|
||||
system: false,
|
||||
payload: PayLoad::Message("beep boop".to_string()),
|
||||
}
|
||||
.hash_username(&Palette::Pastel),
|
||||
Data::new("human".to_string(), false, "beep boop".to_string())
|
||||
.hash_username(&Palette::Pastel),
|
||||
Rgb(159, 223, 221)
|
||||
);
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ impl Filters {
|
||||
self.enabled = !self.enabled;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const fn reversed(&self) -> bool {
|
||||
self.reversed
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ use tui::{backend::CrosstermBackend, Terminal};
|
||||
|
||||
use crate::{
|
||||
handlers::{
|
||||
app::{App, State},
|
||||
app::App,
|
||||
config::{CompleteConfig, CursorType},
|
||||
data::{Data, DataBuilder, PayLoad},
|
||||
data::Data,
|
||||
user_input::{
|
||||
events::{Config, Events, Key},
|
||||
input::{handle_stateful_user_input, TerminalAction},
|
||||
@ -114,21 +114,9 @@ pub async fn ui_driver(
|
||||
|
||||
terminal.clear().unwrap();
|
||||
|
||||
let date_format = config.frontend.date_format.clone();
|
||||
let data_builder = DataBuilder::new(&date_format);
|
||||
|
||||
loop {
|
||||
if let Ok(info) = rx.try_recv() {
|
||||
match info.payload {
|
||||
PayLoad::Message(_) => app.messages.push_front(info),
|
||||
|
||||
// If something such as a keypress failed, fallback to the normal state of the application.
|
||||
PayLoad::Err(err) => {
|
||||
app.state = State::Normal;
|
||||
|
||||
app.messages.push_front(data_builder.system(err));
|
||||
}
|
||||
}
|
||||
app.messages.push_front(info);
|
||||
|
||||
// If scrolling is enabled, pad for more messages.
|
||||
if app.scroll_offset > 0 {
|
||||
|
@ -16,7 +16,6 @@ use crate::{
|
||||
handlers::{
|
||||
app::{App, State},
|
||||
config::CompleteConfig,
|
||||
data::PayLoad,
|
||||
},
|
||||
utils::{
|
||||
styles,
|
||||
@ -144,10 +143,8 @@ pub fn draw_ui<T: Backend>(frame: &mut Frame<T>, app: &mut App, config: &Complet
|
||||
|
||||
let mut total_num_search_results = 0;
|
||||
'outer: for data in &app.messages {
|
||||
if let PayLoad::Message(msg) = data.payload.clone() {
|
||||
if app.filters.contaminated(msg.as_str()) {
|
||||
continue;
|
||||
}
|
||||
if app.filters.contaminated(data.payload.clone().as_str()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Offsetting of messages for scrolling through said messages
|
||||
@ -215,7 +212,11 @@ pub fn draw_ui<T: Backend>(frame: &mut Frame<T>, app: &mut App, config: &Complet
|
||||
TitleStyle::Combined("Time", ¤t_time),
|
||||
TitleStyle::Combined("Channel", config.twitch.channel.as_str()),
|
||||
TitleStyle::Custom(Span::styled(
|
||||
"Filter",
|
||||
if app.filters.reversed() {
|
||||
"retliF"
|
||||
} else {
|
||||
"Filter"
|
||||
},
|
||||
Style::default()
|
||||
.add_modifier(Modifier::BOLD)
|
||||
.fg(if app.filters.enabled() {
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::vec::IntoIter;
|
||||
|
||||
use rustyline::line_buffer::LineBuffer;
|
||||
use textwrap::core::display_width;
|
||||
use tui::{style::Style, text::Span};
|
||||
@ -35,31 +33,6 @@ pub fn align_text(text: &str, alignment: Alignment, maximum_length: u16) -> Stri
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn vector_column_max<T>(v: &[Vec<T>]) -> IntoIter<u16>
|
||||
where
|
||||
T: AsRef<str>,
|
||||
{
|
||||
assert!(
|
||||
!v.is_empty(),
|
||||
"Vector length should be greater than or equal to 1."
|
||||
);
|
||||
|
||||
let column_max = |vec: &[Vec<T>], index: usize| -> u16 {
|
||||
vec.iter().map(|v| v[index].as_ref().len()).max().unwrap() as u16
|
||||
};
|
||||
|
||||
let column_amount = v[0].len();
|
||||
|
||||
let mut column_max_lengths: Vec<u16> = vec![];
|
||||
|
||||
for i in 0..column_amount {
|
||||
column_max_lengths.push(column_max(v, i));
|
||||
}
|
||||
|
||||
column_max_lengths.into_iter()
|
||||
}
|
||||
|
||||
/// Acquiring the horizontal position of the cursor so it can be rendered visually.
|
||||
pub fn get_cursor_position(line_buffer: &LineBuffer) -> usize {
|
||||
line_buffer
|
||||
@ -158,37 +131,6 @@ mod tests {
|
||||
assert_eq!(align_text("👑123", Alignment::Center, 7), " 👑123 ");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Vector length should be greater than or equal to 1.")]
|
||||
fn test_vector_column_max_empty_vector() {
|
||||
let vec: Vec<Vec<String>> = vec![];
|
||||
|
||||
vector_column_max(&vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vector_column_max_reference_strings() {
|
||||
let vec = vec![vec!["", "s"], vec!["longer string", "lll"]];
|
||||
|
||||
let mut output_vec_all = vector_column_max(&vec);
|
||||
|
||||
assert_eq!(output_vec_all.next(), Some(13));
|
||||
assert_eq!(output_vec_all.next(), Some(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vector_column_max_strings() {
|
||||
let vec = vec![
|
||||
vec![String::new(), "another".to_string()],
|
||||
vec![String::new(), "the last string".to_string()],
|
||||
];
|
||||
|
||||
let mut output_vec_all = vector_column_max(&vec);
|
||||
|
||||
assert_eq!(output_vec_all.next(), Some(0));
|
||||
assert_eq!(output_vec_all.next(), Some(15));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_cursor_position_with_single_byte_graphemes() {
|
||||
let text = "never gonna give you up";
|
||||
|
Loading…
Reference in New Issue
Block a user