gitkraft 0.6.1

GitKraft — Git IDE desktop application (Iced GUI)
Documentation
//! Top toolbar / header bar for the GitKraft main layout.
//!
//! Shows: repo name │ branch name │ fetch button │ refresh button │ toggle sidebar.

use iced::widget::{button, container, row, text, Space};
use iced::{Alignment, Element, Length};

use crate::features::theme::view::theme_selector;
use crate::icons;
use crate::message::Message;
use crate::state::GitKraft;
use crate::theme;
use crate::view_utils;

/// Render the top toolbar row.
pub fn view(state: &GitKraft) -> Element<'_, Message> {
    let tab = state.active_tab();
    let c = state.colors();

    // ── Repo name ─────────────────────────────────────────────────────────
    let repo_icon = icon!(icons::FOLDER_OPEN, 14, c.accent);

    let repo_name = text(state.repo_display_name())
        .size(14)
        .color(c.text_primary);

    let separator = || text("|").size(14).color(c.border);

    // ── Branch indicator ──────────────────────────────────────────────────
    let branch_icon = icon!(icons::GIT_BRANCH, 14, c.green);

    let branch_name_str = tab.current_branch.as_deref().unwrap_or("(detached)");

    let branch_label = text(branch_name_str).size(14).color(c.text_primary);

    // ── Repo state badge (if not clean) ───────────────────────────────────
    let state_badge: Element<'_, Message> = if let Some(ref info) = tab.repo_info {
        if info.state != gitkraft_core::RepoState::Clean {
            text(format!(" [{}]", info.state))
                .size(12)
                .color(c.yellow)
                .into()
        } else {
            Space::with_width(0).into()
        }
    } else {
        Space::with_width(0).into()
    };

    // ── Fetch button ──────────────────────────────────────────────────────
    let fetch_icon = icon!(icons::CLOUD_ARROW_DOWN, 14, c.accent);

    let fetch_msg = (!tab.remotes.is_empty()).then_some(Message::Fetch);
    let fetch_btn = crate::view_utils::on_press_maybe(
        button(
            row![fetch_icon, Space::with_width(4), text("Fetch").size(12)]
                .align_y(Alignment::Center),
        )
        .padding([4, 10])
        .style(theme::toolbar_button),
        fetch_msg,
    );

    // ── Refresh button ────────────────────────────────────────────────────
    let refresh_icon = icon!(icons::ARROW_REPEAT, 14, c.accent);

    let refresh_btn = view_utils::toolbar_btn(refresh_icon, "Refresh", Message::RefreshRepo);

    // ── Open another repo button ──────────────────────────────────────────
    let open_icon = icon!(icons::FOLDER_OPEN, 14, c.text_secondary);

    let open_btn = view_utils::toolbar_btn(open_icon, "Open", Message::OpenRepo);

    // ── Close repo button (return to welcome screen) ──────────────────────
    let close_icon = icon!(icons::X_CIRCLE, 14, c.text_secondary);

    let close_btn = view_utils::toolbar_btn(close_icon, "Close", Message::CloseRepo);

    // ── Toggle sidebar ────────────────────────────────────────────────────
    let sidebar_icon_char = if state.sidebar_expanded {
        icons::CHEVRON_LEFT
    } else {
        icons::CHEVRON_RIGHT
    };
    let sidebar_icon = icon!(sidebar_icon_char, 14, c.text_secondary);

    let sidebar_btn = button(sidebar_icon)
        .padding([4, 8])
        .style(theme::icon_button)
        .on_press(Message::ToggleSidebar);

    // ── Loading indicator ─────────────────────────────────────────────────
    let loading_indicator: Element<'_, Message> = if tab.is_loading {
        text("⟳ Loading…").size(12).color(c.yellow).into()
    } else {
        Space::with_width(0).into()
    };

    // ── Assemble ──────────────────────────────────────────────────────────
    let toolbar = row![
        sidebar_btn,
        Space::with_width(8),
        repo_icon,
        Space::with_width(6),
        repo_name,
        Space::with_width(10),
        separator(),
        Space::with_width(10),
        branch_icon,
        Space::with_width(6),
        branch_label,
        state_badge,
        Space::with_width(10),
        separator(),
        Space::with_width(10),
        loading_indicator,
        Space::with_width(Length::Fill),
        theme_selector(state.current_theme_index),
        Space::with_width(8),
        fetch_btn,
        Space::with_width(4),
        refresh_btn,
        Space::with_width(4),
        open_btn,
        Space::with_width(4),
        close_btn,
    ]
    .align_y(Alignment::Center)
    .padding([6, 12])
    .width(Length::Fill);

    container(toolbar)
        .width(Length::Fill)
        .style(theme::header_style)
        .into()
}