use fission::i18n::Locale;
use fission::prelude::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ThemeMode {
Light,
Dark,
}
#[derive(Debug, Clone)]
pub struct SettingsState {
pub theme_mode: ThemeMode,
pub locale: Locale,
}
impl Default for SettingsState {
fn default() -> Self {
Self {
theme_mode: ThemeMode::Light,
locale: Locale("en-US".into()),
}
}
}
impl GlobalState for SettingsState {}
settings.title: "Settings"
settings.theme: "Theme"
settings.locale: "Language"
settings.theme.light: "Light"
settings.theme.dark: "Dark"
settings.title: "Configuracion"
settings.theme: "Tema"
settings.locale: "Idioma"
settings.theme.light: "Claro"
settings.theme.dark: "Oscuro"
use std::collections::HashMap;
use fission::i18n::{Locale, TranslationBundle};
use fission::prelude::*;
fn load_bundle(locale: &str, raw_yaml: &str) -> TranslationBundle {
let messages: HashMap<String, String> =
serde_yaml::from_str(raw_yaml).expect("valid translation yaml");
TranslationBundle {
locale: Locale(locale.to_string()),
messages,
}
}
fn create_env() -> Env {
let mut env = Env::default();
env.i18n.add_bundle(load_bundle(
"en-US",
include_str!("../i18n/en-US.yaml"),
));
env.i18n.add_bundle(load_bundle(
"es-ES",
include_str!("../i18n/es-ES.yaml"),
));
env
}
fn main() -> anyhow::Result<()> {
DesktopApp::new(SettingsApp)
.with_env(create_env())
.with_sync_env(|state: &SettingsState, env: &mut Env| {
env.locale = state.locale.clone();
env.theme = match state.theme_mode {
ThemeMode::Light => Theme::default(),
ThemeMode::Dark => Theme::dark(),
};
})
.run()
}
#[fission_action]
pub struct SetLightTheme;
#[fission_action]
pub struct SetDarkTheme;
#[fission_action]
pub struct SetEnglish;
#[fission_action]
pub struct SetSpanish;
fn on_set_light_theme(
state: &mut SettingsState,
_action: SetLightTheme,
_ctx: &mut ReducerContext<SettingsState>,
) {
state.theme_mode = ThemeMode::Light;
}
fn on_set_dark_theme(
state: &mut SettingsState,
_action: SetDarkTheme,
_ctx: &mut ReducerContext<SettingsState>,
) {
state.theme_mode = ThemeMode::Dark;
}
fn on_set_english(
state: &mut SettingsState,
_action: SetEnglish,
_ctx: &mut ReducerContext<SettingsState>,
) {
state.locale = Locale("en-US".into());
}
fn on_set_spanish(
state: &mut SettingsState,
_action: SetSpanish,
_ctx: &mut ReducerContext<SettingsState>,
) {
state.locale = Locale("es-ES".into());
}
pub struct SettingsApp;
impl From<SettingsApp> for Widget {
fn from(component: SettingsApp) -> Self {
let (ctx, view) = fission::build::current::<SettingsState>();
let light = ctx.bind(
SetLightTheme,
reduce_with!(on_set_light_theme),
);
let dark = ctx.bind(
SetDarkTheme,
reduce_with!(on_set_dark_theme),
);
let english = ctx.bind(
SetEnglish,
reduce_with!(on_set_english),
);
let spanish = ctx.bind(
SetSpanish,
reduce_with!(on_set_spanish),
);
Column {
gap: Some(12.0),
children: vec![
Text::new(TextContent::Key("settings.title".into())).into(),
Text::new(TextContent::Key("settings.theme".into())).into(),
Row {
children: vec![
Button {
on_press: Some(light),
child: Some(
Text::new(TextContent::Key("settings.theme.light".into()))
.into(),
),
..Default::default()
}
.into(),
Button {
on_press: Some(dark),
child: Some(
Text::new(TextContent::Key("settings.theme.dark".into()))
.into(),
),
..Default::default()
}
.into(),
],
..Default::default()
}
.into(),
Text::new(TextContent::Key("settings.locale".into())).into(),
Row {
children: vec![
Button {
on_press: Some(english),
child: Some(Text::new("English").into()),
..Default::default()
}
.into(),
Button {
on_press: Some(spanish),
child: Some(Text::new("Español").into()),
..Default::default()
}
.into(),
],
..Default::default()
}
.into(),
],
..Default::default()
}
.into()
}
}
Check | Expected result |
|---|---|
Build | cargo check or the relevant fission command finishes without target-specific configuration errors. |
Behavior | The screen, package, server route, or test flow described by the recipe is visible and responds to input. |
Failure path | At least one denied, missing, invalid, or empty case renders a useful message instead of silently doing nothing. |
Next link | The reference page linked from the recipe explains the exact fields, commands, or types used here. |