🔒 Repository is read-only – file editing is disabled.

luna/apps/luna-demo/src/app.rs main

131 lines Raw ← Back
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
//! Pełne, interaktywne demo Ustawień Luny — to samo, które widać na obrazach
//! `docs/images/demo-step-*.png` (sidebar, motywy, akcenty, język, zakładki,
//! pliki, popovery, powiadomienia i dolny panel).
//!
//! Wspólne dla binarek `luna-demo` i `luna-showcase` („Luna — widgety”), żeby
//! instalowana aplikacja pokazywała **cały** zestaw widgetów, a nie uproszczony mockup.

use std::error::Error;

use crate::ui::{self, Demo};
use libluna_core::ThemeSettings;
use libluna_i18n::{set_locale, Locale};
use libluna_platform::{run as run_app, AppConfig, Frame};

/// Otwiera okno pełnego demo i uruchamia pętlę zdarzeń (start: „Wygląd”).
pub fn run() -> Result<(), Box<dyn Error>> {
    run_with_start(None)
}

/// Otwiera demo od razu na stronie „Widgety” (galeria komponentów).
pub fn run_widgets() -> Result<(), Box<dyn Error>> {
    run_with_start(Some(ui::WIDGETS_NAV))
}

fn run_with_start(start_nav: Option<usize>) -> Result<(), Box<dyn Error>> {
    set_locale(Locale::from_env());
    // Doładuj języki ze standardowych katalogów (nadpisują wbudowane).
    libluna_i18n::load_catalogs_from_dirs();

    // Ustawienia wyglądu wczytane z dysku (jeśli są).
    let settings = ThemeSettings::load();
    // Tryb systemowy: prosty przełącznik przez zmienną środowiskową (docelowo portal).
    let system_dark = std::env::var("LUNA_SYSTEM_DARK")
        .map(|v| !v.is_empty() && v != "0")
        .unwrap_or(false);

    let config = AppConfig::new("Aplikacja")
        .app_id("eu.paganlinux.Luna.Settings")
        .initial_size(1200, 1028)
        .settings(settings)
        .system_dark(system_dark);

    let mut demo = Demo::default();
    if let Some(i) = start_nav {
        demo.nav_selected = Some(i);
    }

    run_app(config, move |frame: &mut Frame| {
        let mut settings = frame.settings();

        // Motyw (z ewentualnym stylem z pliku) do obsługi zdarzeń.
        let theme = settings.resolve_themed(frame.system_dark());
        ui::handle_events(
            &mut settings,
            frame.events,
            frame.size,
            &theme,
            frame.text,
            &mut demo,
        );

        // Akcje okna zgłoszone przez HeaderBar (kontrolki).
        if demo.pending_close {
            if std::env::var("LUNA_DEBUG_INPUT").is_ok() {
                eprintln!("demo: frame.close()");
            }
            frame.close();
            demo.pending_close = false;
        }
        if demo.pending_minimize {
            frame.minimize();
            demo.pending_minimize = false;
        }
        if demo.pending_maximize {
            frame.toggle_maximize();
            demo.pending_maximize = false;
        }
        // Przeciąganie okna za pasek tytułu (CSD) — ruch wykonuje kompozytor.
        if demo.pending_move {
            if std::env::var("LUNA_DEBUG_INPUT").is_ok() {
                eprintln!("demo: frame.begin_move()");
            }
            frame.begin_move();
            demo.pending_move = false;
        }

        if settings.preference() != frame.preference() {
            frame.set_preference(settings.preference());
        }
        if settings.accent() != frame.accent() {
            frame.set_accent(settings.accent());
        }
        if settings.style() != frame.style() {
            frame.set_style(settings.style().map(str::to_owned));
        }

        // Animacja powiadomienia: krok i prośba o kolejną klatkę, dopóki trwa.
        if demo.toast.is_animating() {
            demo.toast.advance(frame.delta_time(), 0.3);
            frame.request_frame();
        }

        // Animacja przejścia zakładek (`Stack` slide).
        if demo.tab_stack.is_animating() {
            demo.tab_stack.advance(frame.delta_time(), 0.25);
            frame.request_frame();
        }

        // Animacja dolnego panelu (wysuwanie) i przyciągania karuzeli.
        if demo.sheet.is_animating() {
            demo.sheet.advance(frame.delta_time(), 0.3);
            frame.request_frame();
        }
        if demo.pager.is_animating() {
            demo.pager.advance(frame.delta_time(), 0.3);
            frame.request_frame();
        }

        // Motyw po zmianach (np. wybór stylu) — klatka od razu poprawna.
        let theme = settings.resolve_themed(frame.system_dark());
        ui::build_scene(
            frame.scene,
            &theme,
            frame.text,
            frame.size,
            &demo,
            settings.preference(),
            settings.accent(),
        );
    })
}