clin-rs 0.8.30

Encrypted terminal note-taking app inspired by Obsidian
use ratatui::style::Color;

use super::{Background, Theme, ThemeColors};

struct ThemePalette {
    nodes: [[u8; 3]; 8],
    chrome: [u8; 3],
    title: [u8; 3],
    text: [u8; 3],
    fg: [u8; 3],
    grid: [u8; 3],
    bg: [u8; 3],
}

impl ThemePalette {
    const fn rgb(c: [u8; 3]) -> Color {
        Color::Rgb(c[0], c[1], c[2])
    }

    fn build(&self, background: Background) -> ThemeColors {
        ThemeColors {
            node_colors: self.nodes.map(Self::rgb).to_vec(),
            edge_color: Self::rgb(self.chrome),
            border_color: Self::rgb(self.chrome),
            title_color: Self::rgb(self.title),
            label_color: Self::rgb(self.text),
            legend_text_color: Self::rgb(self.text),
            legend_border_color: Self::rgb(self.chrome),
            selected_indicator_color: Self::rgb(self.fg),
            grid_color: Self::rgb(self.grid),
            background_color: match background {
                Background::Transparent => None,
                Background::Solid => Some(Self::rgb(self.bg)),
            },
            status_bar_color: Self::rgb(self.chrome),
            minimap_border_color: Self::rgb(self.chrome),
            minimap_viewport_color: Self::rgb(self.fg),
            minimap_bg_color: Some(Self::rgb(self.bg)),
        }
    }
}

const PALETTES: [ThemePalette; 10] = [
    ThemePalette {
        nodes: [
            [122, 162, 247],
            [187, 154, 247],
            [125, 207, 255],
            [224, 175, 104],
            [158, 206, 106],
            [247, 118, 142],
            [148, 226, 213],
            [255, 158, 100],
        ],
        chrome: [86, 95, 137],
        title: [187, 154, 247],
        text: [203, 206, 215],
        fg: [255, 255, 255],
        grid: [56, 62, 95],
        bg: [26, 27, 38],
    },
    ThemePalette {
        nodes: [
            [137, 180, 250],
            [203, 166, 247],
            [116, 199, 236],
            [249, 226, 175],
            [166, 227, 161],
            [245, 189, 220],
            [242, 205, 205],
            [250, 179, 135],
        ],
        chrome: [108, 112, 134],
        title: [205, 214, 244],
        text: [205, 214, 244],
        fg: [205, 214, 244],
        grid: [49, 50, 68],
        bg: [30, 30, 46],
    },
    ThemePalette {
        nodes: [
            [97, 175, 239],
            [198, 120, 221],
            [86, 182, 194],
            [229, 192, 123],
            [152, 195, 121],
            [224, 108, 117],
            [224, 150, 108],
            [171, 178, 191],
        ],
        chrome: [92, 99, 112],
        title: [171, 178, 191],
        text: [171, 178, 191],
        fg: [220, 223, 228],
        grid: [56, 63, 76],
        bg: [40, 44, 52],
    },
    ThemePalette {
        nodes: [
            [184, 187, 38],
            [215, 153, 33],
            [204, 94, 74],
            [214, 93, 14],
            [104, 157, 106],
            [131, 165, 152],
            [146, 131, 116],
            [254, 128, 25],
        ],
        chrome: [102, 92, 84],
        title: [235, 219, 178],
        text: [235, 219, 178],
        fg: [251, 241, 199],
        grid: [60, 56, 54],
        bg: [40, 40, 40],
    },
    ThemePalette {
        nodes: [
            [139, 233, 253],
            [189, 147, 249],
            [139, 233, 253],
            [255, 184, 108],
            [80, 250, 123],
            [255, 121, 198],
            [255, 139, 127],
            [255, 255, 150],
        ],
        chrome: [98, 114, 164],
        title: [248, 248, 242],
        text: [248, 248, 242],
        fg: [255, 255, 255],
        grid: [68, 71, 90],
        bg: [40, 42, 54],
    },
    ThemePalette {
        nodes: [
            [136, 192, 208],
            [143, 188, 187],
            [163, 190, 140],
            [235, 219, 178],
            [214, 140, 140],
            [216, 170, 133],
            [200, 200, 200],
            [163, 190, 140],
        ],
        chrome: [67, 76, 94],
        title: [216, 222, 233],
        text: [216, 222, 233],
        fg: [236, 239, 244],
        grid: [59, 66, 82],
        bg: [46, 52, 64],
    },
    ThemePalette {
        nodes: [
            [180, 142, 173],
            [234, 154, 151],
            [156, 207, 216],
            [246, 193, 119],
            [155, 138, 221],
            [235, 111, 146],
            [159, 188, 198],
            [209, 193, 168],
        ],
        chrome: [102, 110, 129],
        title: [87, 82, 121],
        text: [87, 82, 121],
        fg: [87, 82, 121],
        grid: [57, 53, 82],
        bg: [40, 37, 61],
    },
    ThemePalette {
        nodes: [
            [255, 215, 89],
            [255, 143, 105],
            [129, 204, 165],
            [100, 200, 218],
            [150, 205, 255],
            [220, 150, 255],
            [255, 180, 120],
            [200, 230, 150],
        ],
        chrome: [95, 120, 102],
        title: [60, 76, 67],
        text: [60, 76, 67],
        fg: [60, 76, 67],
        grid: [40, 50, 45],
        bg: [30, 38, 34],
    },
    ThemePalette {
        nodes: [
            [147, 191, 254],
            [255, 158, 181],
            [203, 166, 247],
            [137, 180, 130],
            [247, 234, 168],
            [255, 173, 130],
            [125, 196, 228],
            [242, 205, 205],
        ],
        chrome: [95, 115, 135],
        title: [98, 114, 164],
        text: [98, 114, 164],
        fg: [98, 114, 164],
        grid: [34, 40, 62],
        bg: [26, 30, 48],
    },
    ThemePalette {
        nodes: [
            [181, 137, 0],
            [203, 75, 22],
            [220, 50, 47],
            [211, 54, 130],
            [108, 113, 196],
            [38, 139, 210],
            [42, 161, 152],
            [133, 153, 0],
        ],
        chrome: [147, 161, 161],
        title: [131, 148, 150],
        text: [131, 148, 150],
        fg: [253, 246, 227],
        grid: [0, 74, 94],
        bg: [0, 43, 54],
    },
];

fn default_theme_colors(background: Background) -> ThemeColors {
    let gray = Color::Gray;
    let dark_gray = Color::DarkGray;
    let reset = Color::Reset;
    let white = Color::White;
    ThemeColors {
        node_colors: vec![
            Color::Cyan,
            Color::Magenta,
            Color::Blue,
            Color::Yellow,
            Color::Green,
            Color::Red,
            Color::LightCyan,
            Color::LightMagenta,
        ],
        edge_color: dark_gray,
        border_color: dark_gray,
        title_color: gray,
        label_color: gray,
        legend_text_color: gray,
        legend_border_color: dark_gray,
        selected_indicator_color: reset,
        grid_color: dark_gray,
        background_color: match background {
            Background::Transparent => None,
            Background::Solid => Some(Color::Black),
        },
        status_bar_color: dark_gray,
        minimap_border_color: dark_gray,
        minimap_viewport_color: white,
        minimap_bg_color: Some(Color::Black),
    }
}

pub fn theme_colors(theme: &Theme, background: Background) -> ThemeColors {
    match theme {
        Theme::Default => default_theme_colors(background),
        Theme::TokyoNight => PALETTES[0].build(background),
        Theme::CatppuccinMocha => PALETTES[1].build(background),
        Theme::Onedark => PALETTES[2].build(background),
        Theme::Gruvbox => PALETTES[3].build(background),
        Theme::Dracula => PALETTES[4].build(background),
        Theme::Nord => PALETTES[5].build(background),
        Theme::RosePine => PALETTES[6].build(background),
        Theme::Everforest => PALETTES[7].build(background),
        Theme::Kanagawa => PALETTES[8].build(background),
        Theme::Solarized => PALETTES[9].build(background),
    }
}