diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..726eb15 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "theming" +version = "0.1.0" +edition = "2024" + +[dependencies] +makepad-widgets = { path = "../../../../makepad/widgets" } diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..c0cc733 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,103 @@ +pub use makepad_widgets; +pub mod streem_theme +pub mod streem_i18n + +use makepad_widgets::*; +use std::sync::atomic::{AtomicU8, Ordering}; + +app_main!(App); +static CURRENT_THEME: AtomicU8 = AtomicU8::new(0); // 0 = light, 1 = dark +static CURRENT_I18N: AtomicU8 = AtomicU8::new(0); // 0 = light, 1 = dark + + +script_mod! { + use mod.prelude.widgets.* + use mod.widgets.* + + let app = startup() do #(App::script_component(vm)){ + ui: Root{ main_window := Window{ window.title: "Runtime theme swap" + body +: { + width: Fill height: Fill flow: Down padding: 24.0 spacing: 16.0 + View{ width: Fill height: Fit flow: Right spacing: 16.0 align: Align{y: 0.5} + toggle_theme := Button{text: "Toggle theme"} + status_label := Label{ + text: "Current: light | reapply: 0" + draw_text.text_style: theme.font_bold{font_size: 12.0} + draw_text.color: s_themes.color_primary + } + } + View{ width: Fill height: Fit flow: Right spacing: 24.0 + View{ width: Fill height: Fit flow: Down spacing: 8.0 + Label{text: "Markdown" draw_text.text_style: theme.font_bold{font_size: 10.0} draw_text.color: s_themes.color_primary} + Markdown{ width: Fill height: Fit + body: "# Tasks\n\n| Task | Status | Owner |\n|---|---|---|\n| **API** | *WIP* | Alice |\n| ~~Legacy~~ | *Done* | Bob |\n| UI | **Blocked** | Carol |" + } + } + View{ width: Fill height: Fit flow: Down spacing: 8.0 + Label{text: "HTML" draw_text.text_style: theme.font_bold{font_size: 10.0} draw_text.color: s_themes.color_primary} + Html{ width: Fill height: Fit + body: "

Tasks

TaskStatusOwner
APIWIPAlice
LegacyDoneBob
UIBlockedCarol
" + } + } + } + } + }} + } + app +} + +#[derive(Script, ScriptHook)] +pub struct App { + #[live] ui: WidgetRef, + #[rust] is_dark: bool, + #[rust] n: u32 +} + +impl MatchEvent for App { + fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) { + if self.ui.button(cx, ids!(toggle_theme)).clicked(actions) { + self.is_dark = !self.is_dark; + CURRENT_THEME.store(if self.is_dark { 1 } else { 0 }, Ordering::Relaxed); + // Re-run script_mod (same pipeline as file-based LiveEdit) so widget + // templates rebuild against the new mod.theme, then re-apply the tree. + cx.with_vm(|vm| { + let value = vm.with_reload(|vm| ::script_mod(vm)); + ::script_apply( + self, vm, &Apply::Reload, &mut Scope::empty(), value, + ); + }); + self.n += 1; + let t = if self.is_dark { "dark" } else { "light" }; + self.ui.label(cx, ids!(status_label)) + .set_text(cx, &format!("Current: {} | reapply: {}", t, self.n)); + self.ui.redraw(cx); + } + } +} + +impl AppMain for App { + fn script_mod(vm: &mut ScriptVm) -> ScriptValue { + crate::makepad_widgets::theme_mod(vm); + crate::streem_theme::script_mod(vm); + crate::streem_i18n::script_mod(vm); + + if CURRENT_I18N.load(Ordering::Relaxed) == 1 { + script_eval!(vm, { mod.theme = mod.streem_i18n.en }); + } else { + script_eval!(vm, { mod.theme = mod.streem_i18n.sw }); + } + + if CURRENT_THEME.load(Ordering::Relaxed) == 1 { + script_eval!(vm, { mod.theme = mod.streem_theme.dark }); + } else { + script_eval!(vm, { mod.theme = mod.streem_theme.light }); + } + crate::makepad_widgets::widgets_mod(vm); + self::script_mod(vm) + } + + fn handle_event(&mut self, cx: &mut Cx, event: &Event) { + self.match_event(cx, event); + self.ui.handle_event(cx, event, &mut Scope::empty()); + } +} \ No newline at end of file diff --git a/src/streem_i18n/en.rs b/src/streem_i18n/en.rs new file mode 100644 index 0000000..a6654f9 --- /dev/null +++ b/src/streem_i18n/en.rs @@ -0,0 +1,25 @@ +use makepad_widgets::*; + +script_mod! { + + use mod.prelude.widgets.* + use mod.widgets.* + + mod.widgets.i18n = { + en: { + title_streem: "Streem Video Player" + tab_vehicles: "My Vehicles" + tab_service: "Service" + tab_parts: "Parts" + tab_recalls: "Recalls" + open_workflow: "Open workflow" + grant_permission: "Grant Permission" + cancel: "Cancel" + + // Video Player Strings + player_no_video: "No video selected" + player_skip: "Skip to saved position" + player_local_file: "Local File" + } + } +} \ No newline at end of file diff --git a/src/streem_i18n/mod.rs b/src/streem_i18n/mod.rs new file mode 100644 index 0000000..5704c4f --- /dev/null +++ b/src/streem_i18n/mod.rs @@ -0,0 +1,9 @@ +use makepad_widgets::ScriptVm; + +pub mod en; +pub mod sw; + +pub fn script_mod(vm: &mut ScriptVm) { + en::script_mod(vm); + sw::script_mod(vm); +} \ No newline at end of file diff --git a/src/streem_i18n/sw.rs b/src/streem_i18n/sw.rs new file mode 100644 index 0000000..b50e408 --- /dev/null +++ b/src/streem_i18n/sw.rs @@ -0,0 +1,25 @@ +use makepad_widgets::*; + +script_mod! { + + use mod.prelude.widgets.* + use mod.widgets.* + + mod.widgets.i18n = { + sw: { + title_streem: "Kicheza Video cha Streem" + tab_vehicles: "Magari Yangu" + tab_service: "Huduma" + tab_parts: "Vipuri" + tab_recalls: "Marejesho" + open_workflow: "Fungua mchakato" + grant_permission: "Toa Ruhusa" + cancel: "Ghairi" + + // Video Player Strings + player_no_video: "Hakuna video iliyochaguliwa" + player_skip: "Nenda kwenye nafasi iliyohifadhiwa" + player_local_file: "Faili ya Ndani" + } + } +} \ No newline at end of file diff --git a/src/streem_theme/colors.rs b/src/streem_theme/colors.rs new file mode 100644 index 0000000..d2fb71c --- /dev/null +++ b/src/streem_theme/colors.rs @@ -0,0 +1,22 @@ +use makepad_widgets::*; + +script_mod! { + + use mod.prelude.widgets.* + use mod.widgets.* + + mod.widgets.colors = { + white: #xFFFFFF + white_150: #xFFFFFF26 + white_850: #xFFFFFFD9 + + pink_100: #FFF1F1 + pink_900: #3F2C2C + + gray: #232323 + + green_300: #B8C9B8 + green_900: #2D3B2D + } +} + diff --git a/src/streem_theme/dark.rs b/src/streem_theme/dark.rs new file mode 100644 index 0000000..e904359 --- /dev/null +++ b/src/streem_theme/dark.rs @@ -0,0 +1,16 @@ +// src/dark.rs + +use makepad_widgets::*; + +script_mod! { + + use mod.prelude.widgets.* + use mod.widgets.* + + mod.widgets.streem_themes = { + dark: { + color_primary: mod.widgets.green_900 + } + } + mod.widgets.streem_themes = mod.widgets.streem_themes.dark +} diff --git a/src/streem_theme/light.rs b/src/streem_theme/light.rs new file mode 100644 index 0000000..b7288cf --- /dev/null +++ b/src/streem_theme/light.rs @@ -0,0 +1,15 @@ +// src/light.rs +use makepad_widgets::*; + +script_mod! { + + use mod.prelude.widgets.* + use mod.widgets.* + + mod.widgets.streem_themes = { + light: { + color_primary: mod.widgets.pink_100 + } + } + mod.widgets.streem_themes = mod.widgets.streem_themes.light +} \ No newline at end of file diff --git a/src/streem_theme/mod.rs b/src/streem_theme/mod.rs new file mode 100644 index 0000000..50e2fd3 --- /dev/null +++ b/src/streem_theme/mod.rs @@ -0,0 +1,14 @@ +pub mod dark; +pub mod light; +pub mod colors; +pub mod shapes; +pub mod typography; + + +pub fn script_mod(vm: &mut ScriptVm) { + colors::script_mod(vm); + shapes::script_mod(vm); + typography::script_mod(vm); + dark::script_mod(vm); + light::script_mod(vm); +} \ No newline at end of file diff --git a/src/streem_theme/shapes.rs b/src/streem_theme/shapes.rs new file mode 100644 index 0000000..e6b4d57 --- /dev/null +++ b/src/streem_theme/shapes.rs @@ -0,0 +1,16 @@ +use makepad_widgets::*; + +script_mod! { + + use mod.prelude.widgets.* + use mod.widgets.* + + mod.widgets.shapes = { + small: 4.0 + medium: 24.0 + large: 0.0 + + button_height: 48.0 + input_height: 56.0 + } +} \ No newline at end of file diff --git a/src/streem_theme/typography.rs b/src/streem_theme/typography.rs new file mode 100644 index 0000000..d148d1f --- /dev/null +++ b/src/streem_theme/typography.rs @@ -0,0 +1,44 @@ +use makepad_widgets::*; + +script_mod! { + + use mod.prelude.widgets.* + use mod.widgets.* + + mod.widgets.typography = { + h1: theme.font_bold { + font_size: 18.0 + line_spacing: 1.2 + } + + h2: theme.font_bold { + font_size: 14.0 + line_spacing: 1.2 + } + + subtitle1: theme.font_regular { + font_size: 16.0 + line_spacing: 1.2 + } + + body1: theme.font_regular { + font_size: 14.0 + line_spacing: 1.2 + } + + body2: theme.font_regular { + font_size: 12.0 + line_spacing: 1.2 + } + + button: theme.font_bold { + font_size: 14.0 + line_spacing: 1.0 + } + + caption: theme.font_bold { + font_size: 12.0 + line_spacing: 1.2 + } + } +} \ No newline at end of file