use super::Msg;
use crate::config::Settings;
use std::time::Instant;
use tui_realm_stdlib::{Label, Span, Spinner};
use tuirealm::command::{Cmd, CmdResult};
use tuirealm::event::NoUserEvent;
use tuirealm::props::{
Alignment, AttrValue, Attribute, Color, PropPayload, PropValue, TextModifiers, TextSpan,
};
use tuirealm::tui::layout::Rect;
use tuirealm::{Component, Event, Frame, MockComponent, State};
#[derive(MockComponent)]
pub struct LabelGeneric {
component: Label,
}
impl LabelGeneric {
pub fn new(config: &Settings, text: &str) -> Self {
Self {
component: Label::default()
.text(text)
.alignment(Alignment::Left)
.background(
config
.style_color_symbol
.library_background()
.unwrap_or(Color::Reset),
)
.foreground(
config
.style_color_symbol
.library_highlight()
.unwrap_or(Color::Cyan),
)
.modifiers(TextModifiers::BOLD),
}
}
}
impl Component<Msg, NoUserEvent> for LabelGeneric {
fn on(&mut self, _ev: Event<NoUserEvent>) -> Option<Msg> {
None
}
}
pub struct LabelSpan {
component: Span,
default_span: Vec<TextSpan>,
active_message_start_time: Option<Instant>,
time_out: isize,
}
impl LabelSpan {
pub fn new(config: &Settings, span: &[TextSpan]) -> Self {
Self {
component: Span::default()
.spans(span)
.alignment(Alignment::Left)
.background(
config
.style_color_symbol
.library_background()
.unwrap_or(Color::Reset),
)
.foreground(
config
.style_color_symbol
.library_highlight()
.unwrap_or(Color::Cyan),
)
.modifiers(TextModifiers::BOLD),
default_span: span.to_vec(),
active_message_start_time: None,
time_out: 10,
}
}
}
impl Component<Msg, NoUserEvent> for LabelSpan {
fn on(&mut self, _ev: Event<NoUserEvent>) -> Option<Msg> {
None
}
}
impl MockComponent for LabelSpan {
#[allow(clippy::cast_sign_loss)]
fn view(&mut self, render: &mut Frame<'_>, area: Rect) {
if let Some(start_time) = self.active_message_start_time {
if start_time.elapsed().as_secs() > self.time_out as u64 {
self.attr(
Attribute::Text,
AttrValue::Payload(PropPayload::Vec(
self.default_span
.iter()
.cloned()
.map(PropValue::TextSpan)
.collect(),
)),
);
self.active_message_start_time = None;
self.time_out = 10;
}
}
self.component.view(render, area);
}
fn query(&self, attr: Attribute) -> Option<AttrValue> {
self.component.query(attr)
}
fn attr(&mut self, attr: Attribute, value: AttrValue) {
self.active_message_start_time = Some(Instant::now());
match attr {
Attribute::Value => self.time_out = value.unwrap_number(),
attr => self.component.attr(attr, value),
}
}
fn state(&self) -> State {
self.component.state()
}
fn perform(&mut self, _cmd: Cmd) -> CmdResult {
CmdResult::None
}
}
#[derive(MockComponent)]
pub struct DownloadSpinner {
component: Spinner,
}
impl DownloadSpinner {
pub fn new(config: &Settings) -> Self {
Self {
component: Spinner::default()
.foreground(
config
.style_color_symbol
.library_highlight()
.unwrap_or(Color::LightBlue),
)
.background(
config
.style_color_symbol
.library_background()
.unwrap_or(Color::Reset),
)
.sequence("⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"),
}
}
}
impl Component<Msg, NoUserEvent> for DownloadSpinner {
fn on(&mut self, _: Event<NoUserEvent>) -> Option<Msg> {
None
}
}