concord 2.4.4

A terminal user interface client for Discord
Documentation
use super::*;

const DEBUG_LOG_POPUP_TARGET_WIDTH: u16 = 78;

pub(in crate::tui::ui) fn render_debug_log_popup(
    frame: &mut Frame,
    area: Rect,
    state: &DashboardState,
) {
    if !state.is_active_modal_popup(ActiveModalPopupKind::DebugLog) {
        return;
    }

    let popup_width = DEBUG_LOG_POPUP_TARGET_WIDTH
        .min(area.width.saturating_sub(2))
        .max(1);
    let visible_log_lines = usize::from(area.height).saturating_sub(6).max(1);
    let lines = debug_log_popup_lines(
        state.debug_log_lines(),
        state.debug_channel_visibility(),
        visible_log_lines,
        usize::from(popup_width.saturating_sub(2)),
    );
    let popup = debug_log_popup_area(area, lines.len());
    render_modal_paragraph(frame, popup, "Debug logs", lines);
}

pub(in crate::tui::ui) fn debug_log_popup_area(area: Rect, line_count: usize) -> Rect {
    centered_rect(
        area,
        DEBUG_LOG_POPUP_TARGET_WIDTH,
        (line_count as u16).saturating_add(2),
    )
}

pub(in crate::tui::ui) fn debug_log_popup_area_for_state(
    area: Rect,
    state: &DashboardState,
) -> Rect {
    let popup_width = DEBUG_LOG_POPUP_TARGET_WIDTH
        .min(area.width.saturating_sub(2))
        .max(1);
    let visible_log_lines = usize::from(area.height).saturating_sub(6).max(1);
    let lines = debug_log_popup_lines(
        state.debug_log_lines(),
        state.debug_channel_visibility(),
        visible_log_lines,
        usize::from(popup_width.saturating_sub(2)),
    );
    debug_log_popup_area(area, lines.len())
}

pub(in crate::tui::ui) fn debug_log_popup_lines(
    entries: Vec<String>,
    channel_visibility: ChannelVisibilityStats,
    visible_log_lines: usize,
    width: usize,
) -> Vec<Line<'static>> {
    let width = width.max(1);
    let visible_log_lines = visible_log_lines.max(1);
    let mut lines = Vec::new();

    // Header line: visible vs. permission-hidden channels for the active
    // scope. Helps the user diagnose "why is this channel missing" without
    // diving into the logs.
    let visibility_text = format!(
        "Channels: {} visible ยท {} hidden by permissions",
        channel_visibility.visible, channel_visibility.hidden,
    );
    lines.push(Line::from(Span::styled(visibility_text, Style::default())));
    lines.push(Line::from(Span::raw(String::new())));

    if entries.is_empty() {
        lines.push(Line::from(Span::styled(
            "No errors recorded in this process.",
            theme::current().style(theme::HighlightGroup::Placeholder),
        )));
    } else {
        let wrapped = entries
            .into_iter()
            .flat_map(|entry| wrap_text_lines(&entry, width))
            .collect::<Vec<_>>();
        let start = wrapped.len().saturating_sub(visible_log_lines);
        for entry in wrapped.into_iter().skip(start) {
            lines.push(Line::from(Span::styled(
                entry,
                theme::current().style(theme::HighlightGroup::Error),
            )));
        }
    }
    lines
}