koibumi 0.0.10

An experimental Bitmessage client
use ::log::Level;
use iced::{
    widget::{scrollable, Column, Text},
    Color, Element, Length,
};

use crate::{config::Config as GuiConfig, gui};

#[derive(Clone, Debug)]
pub(crate) struct Entry {
    level: Level,
    message: String,
}

impl Entry {
    pub(crate) fn new(level: Level, message: String) -> Self {
        Self { level, message }
    }
}

#[derive(Clone, Debug, Default)]
pub(crate) struct Tab {
    entries: Vec<Entry>,
}

fn log_color(level: Level) -> Color {
    match level {
        Level::Error => Color {
            r: 1.0,
            g: 0.0,
            b: 0.0,
            a: 1.0,
        },
        Level::Info => Color {
            r: 0.0,
            g: 0.75,
            b: 0.0,
            a: 1.0,
        },
        _ => Color {
            r: 0.0,
            g: 0.0,
            b: 0.0,
            a: 1.0,
        },
    }
}

impl Tab {
    pub(crate) fn log(&mut self, level: Level, message: String) {
        self.entries.push(Entry { level, message });
    }

    pub(crate) fn view(&self, config: &GuiConfig) -> Element<gui::Message> {
        let text_size = config.text_size();

        let mut list = Column::new();
        for entry in &self.entries {
            list = list.push(
                Text::new(&entry.message)
                    .size(text_size)
                    .style(log_color(entry.level)),
            );
        }
        let list = scrollable(list).height(Length::Fill);

        Column::new().spacing(text_size / 4).push(list).into()
    }
}

#[derive(Clone, Debug, Default)]
pub(crate) struct Bar {
    entry: Option<Entry>,
}

impl Bar {
    pub(crate) fn log(&mut self, level: Level, message: String) {
        self.entry = Some(Entry { level, message });
    }

    pub(crate) fn view(&self, config: &GuiConfig) -> Element<gui::Message> {
        let text_size = config.text_size();

        let color = if let Some(entry) = &self.entry {
            log_color(entry.level)
        } else {
            log_color(Level::Trace)
        };

        if let Some(entry) = &self.entry {
            let line = Text::new(&entry.message).size(text_size).style(color);
            Column::new().spacing(text_size / 4).push(line).into()
        } else {
            Column::new().spacing(text_size / 4).into()
        }
    }
}

#[derive(Clone, Debug, Default)]
pub(crate) struct Logger {
    pub(crate) tab: Tab,
    pub(crate) bar: Bar,
}

impl Logger {
    pub(crate) fn log(&mut self, level: Level, message: &str) {
        let message = message.to_string();
        self.tab.log(level, message.clone());
        self.bar.log(level, message);
    }

    pub(crate) fn error(&mut self, message: &str) {
        self.log(Level::Error, message);
    }

    pub(crate) fn info(&mut self, message: &str) {
        self.log(Level::Info, message);
    }
}