fission-command-ui 0.14.1

Terminal UI application for the fission command
Documentation
use super::title_block;
use crate::actions::{
    set_scrollback_limit, set_scrollback_limit_input, toggle_compact_mode, SetScrollbackLimit,
    SetScrollbackLimitInput, ToggleCompactMode,
};
use crate::components::{ActionButton, ButtonTone, FormTextField, KeyValueRow};
use crate::state::UiState;
use crate::theme::UiPalette;
use fission::prelude::*;

#[derive(Clone)]
pub struct SettingsScreen;

impl From<SettingsScreen> for Widget {
    fn from(_component: SettingsScreen) -> Self {
        let (ctx, view) = fission::build::current::<UiState>();
        let palette = UiPalette::for_mode(view.state().theme_mode);
        let set_limit_input =
            with_reducer!(ctx, SetScrollbackLimitInput, set_scrollback_limit_input);
        let compact = with_reducer!(ctx, ToggleCompactMode, toggle_compact_mode);
        let presets = [10_000usize, 100_000, 500_000, 1_000_000]
            .into_iter()
            .map(|limit| {
                let action = with_reducer!(ctx, SetScrollbackLimit(limit), set_scrollback_limit);
                ActionButton::new(format_scrollback_limit(limit), action)
                    .tone(if view.state().scrollback_limit == limit {
                        ButtonTone::Primary
                    } else {
                        ButtonTone::Neutral
                    })
                    .width(16.0)
                    .into()
            })
            .collect::<Vec<_>>();

        Column {
            gap: Some(1.0),
            children: vec![
                title_block(
                    "Settings",
                    "Tune terminal UI behaviour without changing the project configuration.",
                    palette.accent,
                    palette.muted,
                ),
                KeyValueRow::new(
                    "Density",
                    if view.state().compact_mode {
                        "Compact".to_string()
                    } else {
                        "Comfortable".to_string()
                    },
                )
                .into(),
                ActionButton::new(
                    if view.state().compact_mode {
                        "Use comfortable spacing"
                    } else {
                        "Use compact spacing"
                    },
                    compact,
                )
                .tone(ButtonTone::Neutral)
                .width(28.0)
                .into(),
                KeyValueRow::new(
                    "Scrollback",
                    format!("{} lines", view.state().scrollback_limit),
                )
                .into(),
                FormTextField::new(
                    "cli_ui_scrollback_limit",
                    "Scrollback lines",
                    view.state().scrollback_limit_input.clone(),
                    "100000, 500k, 1m",
                    set_limit_input,
                )
                .width(28.0)
                .into(),
                Row {
                    gap: Some(1.0),
                    children: presets,
                    ..Default::default()
                }
                .into(),
                Text::new(
                    "The UI keeps a bounded ring buffer for command output. Older lines are discarded once the configured limit is reached, which keeps long-running sessions predictable instead of growing memory without limit.",
                )
                .color(palette.muted)
                .into(),
            ],
            ..Default::default()
        }
        .into()
    }
}
fn format_scrollback_limit(limit: usize) -> String {
    if limit >= 1_000_000 && limit % 1_000_000 == 0 {
        format!("{}M", limit / 1_000_000)
    } else if limit >= 1_000 && limit % 1_000 == 0 {
        format!("{}K", limit / 1_000)
    } else {
        limit.to_string()
    }
}