diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 9a393de6f..000000000 --- a/AGENTS.md +++ /dev/null @@ -1,732 +0,0 @@ - -# Makepad Project Guide - -## Important: When Converting Syntax - -**Always search for existing usage patterns in the NEW crates (widgets, code_editor, studio) before making syntax changes.** The old `widgets` and `live_design!` syntax is deprecated. When unsure about the correct syntax for something, grep for similar usage in `widgets/src/` to find the correct pattern. - -```bash -# Example: find how texture declarations work in new system -grep -r "texture_2d" widgets/src/ -``` - -**Critical: Always use `Name: value` syntax, never `Name = value`.** The old `Key = Value` syntax no longer works. For named widget instances, use `name := Type{...}` syntax. - -## Running UI Programs - -```bash -RUST_BACKTRACE=1 cargo run -p makepad-example-splash --release & PID=$!; sleep 15; kill $PID 2>/dev/null; echo "Process $PID killed" -``` - -## Cargo.toml Setup - -```toml -[package] -name = "makepad-example-myapp" -version = "0.1.0" -edition = "2021" - -[dependencies] -makepad-widgets = { path = "../../widgets" } -``` - - -## Widgets DSL (script_mod!) - -The new DSL uses `script_mod!` macro with runtime script evaluation instead of the old `live_design!` compile-time macros. - -### Imports and App Setup - -```rust -use makepad_widgets::*; - -app_main!(App); - -script_mod!{ - use mod.prelude.widgets.* - - load_all_resources() do #(App::script_component(vm)){ - ui: Root{ - main_window := Window{ - window.inner_size: vec2(800, 600) - body +: { - // UI content here - } - } - } - } -} - -impl App { - fn run(vm: &mut ScriptVm) -> Self { - crate::makepad_widgets::script_mod(vm); // Register all widgets - // Platform-specific initialization goes here (e.g., vm.cx().start_stdin_service() for macos) - App::from_script_mod(vm, self::script_mod) - } -} - -#[derive(Script, ScriptHook)] -pub struct App { - #[live] ui: WidgetRef, -} - -impl MatchEvent for App { - fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) { - // Handle widget actions - } -} - -impl AppMain for App { - fn handle_event(&mut self, cx: &mut Cx, event: &Event) { - self.match_event(cx, event); - self.ui.handle_event(cx, event, &mut Scope::empty()); - } -} -``` - -### Available Widgets (widgets/src/lib.rs) - -Core: `View`, `SolidView`, `RoundedView`, `ScrollXView`, `ScrollYView`, `ScrollXYView` -Text: `Label`, `H1`, `H2`, `H3`, `LinkLabel`, `TextInput` -Buttons: `Button`, `ButtonFlat`, `ButtonFlatter` -Toggles: `CheckBox`, `Toggle`, `RadioButton` -Input: `Slider`, `DropDown` -Layout: `Splitter`, `FoldButton`, `FoldHeader`, `Hr` -Lists: `PortalList` -Navigation: `StackNavigation`, `ExpandablePanel` -Overlays: `Modal`, `Tooltip`, `PopupNotification` -Dock: `Dock`, `DockSplitter`, `DockTabs`, `DockTab` -Media: `Image`, `Icon`, `LoadingSpinner` -Special: `FileTree`, `PageFlip`, `CachedWidget` -Window: `Window`, `Root` -Markup: `Html`, `Markdown` (feature-gated) - -### Widget Definition Pattern - -```rust -// Rust struct -#[derive(Script, ScriptHook, Widget)] -pub struct MyWidget { - #[source] source: ScriptObjectRef, // Required for script integration - #[walk] walk: Walk, - #[layout] layout: Layout, - #[redraw] #[live] draw_bg: DrawQuad, - #[live] draw_text: DrawText, - #[rust] my_state: i32, // Runtime-only field -} - -// For widgets with animations, add Animator derive: -#[derive(Script, ScriptHook, Widget, Animator)] -pub struct AnimatedWidget { - #[source] source: ScriptObjectRef, - #[apply_default] animator: Animator, - // ... -} -``` - -### Script Module Structure - -```rust -script_mod!{ - use mod.prelude.widgets_internal.* // For internal widget definitions - use mod.widgets.* // Access other widgets - - // Register base widget (connects Rust struct to script) - mod.widgets.MyWidgetBase = #(MyWidget::register_widget(vm)) - - // Create styled variant with defaults - mod.widgets.MyWidget = set_type_default() do mod.widgets.MyWidgetBase{ - width: Fill - height: Fit - padding: theme.space_2 - - draw_bg +: { - color: theme.color_bg_app - } - } -} -``` - -### Key Syntax Differences (Old vs New) - -| Old (live_design!) | New (script_mod!) | -|-------------------|-------------------| -| `` | `mod.widgets.BaseWidget{ }` | -| `{{StructName}}` | `#(Struct::register_widget(vm))` | -| `(THEME_COLOR_X)` | `theme.color_x` | -| `` | `theme.font_regular` | -| `instance hover: 0.0` | `hover: instance(0.0)` | -| `uniform color: #fff` | `color: uniform(#fff)` | -| `draw_bg: { }` (replace) | `draw_bg +: { }` (merge) | -| `default: off` | `default: @off` | -| `fn pixel(self)` | `pixel: fn()` | -| `item.apply_over(cx, live!{...})` | `script_apply_eval!(cx, item, {...})` | - -### Runtime Property Updates with script_apply_eval! - -Use `script_apply_eval!` macro to dynamically update widget properties at runtime: -```rust -// Old system (live! macro with apply_over) -item.apply_over(cx, live!{ - height: (height) - draw_bg: {is_even: (if is_even {1.0} else {0.0})} -}); - -// New system (script_apply_eval! macro) -script_apply_eval!(cx, item, { - height: #(height) - draw_bg +: {is_even: #(if is_even {1.0} else {0.0})} -}); - -// For colors, use #(color) syntax -let color = self.color_focus; -script_apply_eval!(cx, item, { - draw_bg +: { - color: #(color) - } -}); -``` - -Note: In `script_apply_eval!`, use `#(expr)` for Rust expression interpolation instead of `(expr)`. - -### Theme Access - -Always use `theme.` prefix: -```rust -color: theme.color_bg_app -padding: theme.space_2 -font_size: theme.font_size_p -text_style: theme.font_regular -``` - -### Property Merging with `+:` - -The `+:` operator merges with parent instead of replacing: -```rust -mod.widgets.MyButton = mod.widgets.Button{ - draw_bg +: { - color: #f00 // Only overrides color, keeps other draw_bg properties - } -} -``` - -### Shader Instance vs Uniform - -- `instance(value)` - Per-draw-call value (can vary per widget instance) -- `uniform(value)` - Shared across all instances using same shader - -```rust -draw_bg +: { - hover: instance(0.0) // Each button has its own hover state - color: uniform(theme.color_x) // Shared base color - color_hover: instance(theme.color_y) // Per-instance if color varies -} -``` - -### Animator Definition - -```rust -animator: Animator{ - hover: { - default: @off - off: AnimatorState{ - from: {all: Forward {duration: 0.1}} - apply: { - draw_bg: {hover: 0.0} - draw_text: {hover: 0.0} - } - } - on: AnimatorState{ - from: {all: Snap} // Instant transition - apply: { - draw_bg: {hover: 1.0} - draw_text: {hover: 1.0} - } - } - } -} -``` - -### Shader Functions - -```rust -draw_bg +: { - pixel: fn() { - let sdf = Sdf2d.viewport(self.pos * self.rect_size) - sdf.box(0.0, 0.0, self.rect_size.x, self.rect_size.y, 4.0) - sdf.fill(self.color.mix(self.color_hover, self.hover)) - return sdf.result - } -} -``` - -Note: Use `.method()` not `::method()` in shaders. - -### Color Mixing (Method Chaining) - -```rust -// Old nested style (avoid) -mix(mix(mix(color1, color2, hover), color3, down), color4, focus) - -// New chained style (preferred) -color1.mix(color2, hover).mix(color3, down).mix(color4, focus) -``` - -### App Structure Pattern - -```rust -script_mod!{ - use mod.prelude.widgets.* - - load_all_resources() do #(App::script_component(vm)){ - ui: Root{ - main_window := Window{ - window.inner_size: vec2(1000, 700) - body +: { - // Your UI here - MyWidget{} - } - } - } - } -} - -impl App { - fn run(vm: &mut ScriptVm) -> Self { - crate::makepad_widgets::script_mod(vm); - // Platform-specific initialization (e.g., vm.cx().start_stdin_service() for macos) - App::from_script_mod(vm, self::script_mod) - } -} - -#[derive(Script, ScriptHook)] -pub struct App { - #[live] ui: WidgetRef, -} - -impl MatchEvent for App { - fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) { - if self.ui.button(ids!(my_button)).clicked(actions) { - log!("Button clicked!"); - } - } -} - -impl AppMain for App { - fn handle_event(&mut self, cx: &mut Cx, event: &Event) { - self.match_event(cx, event); - self.ui.handle_event(cx, event, &mut Scope::empty()); - } -} -``` - -### Widget ID References - -Use `:=` for named widget instances: -```rust -// In DSL -my_button := Button{text: "Click"} - -// In Rust code -self.ui.button(ids!(my_button)).clicked(actions) -``` - -### Template Definitions in Dock - -Templates inside Dock are local; use `let` bindings at script level for reusable components: -```rust -script_mod!{ - // Reusable at script level - let MyPanel = SolidView{ - width: Fill - height: Fill - // ... - } - - // Use directly - body +: { - MyPanel{} // Works because it's a let binding - } -} -``` - -### Custom Draw Widget Example - -```rust -#[derive(Script, ScriptHook, Widget)] -pub struct CustomDraw { - #[walk] walk: Walk, - #[layout] layout: Layout, - #[redraw] #[live] draw_quad: DrawQuad, - #[rust] area: Area, -} - -impl Widget for CustomDraw { - fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep { - cx.begin_turtle(walk, self.layout); - let rect = cx.turtle().rect(); - self.draw_quad.draw_abs(cx, rect); - cx.end_turtle_with_area(&mut self.area); - DrawStep::done() - } - - fn handle_event(&mut self, _cx: &mut Cx, _event: &Event, _scope: &mut Scope) {} -} -``` - -### Script Object Storage: map vs vec - -In script objects, properties are stored in two different places: -- **`map`**: Contains `key: value` pairs (regular properties) -- **`vec`**: Contains named template items (via `:=` syntax) - -This distinction is important when working with `on_after_apply` or inspecting script objects directly. - -### Templates in List Widgets (PortalList, FlatList) - -In list widgets, named IDs (using `:=`) define **templates** that are stored in the widget's `templates` HashMap. These are NOT regular properties - they go into the script object's vec and are collected via `on_after_apply`. - -```rust -// In script_mod! - defining templates for a list -my_list := PortalList { - // Regular properties (go into struct fields) - width: Fill - height: Fill - scroll_bar: mod.widgets.ScrollBar {} - - // Templates (named with :=) - stored in templates HashMap, NOT struct fields - Item := View { - height: 40 - title := Label { text: "Default" } - } - Header := View { - draw_bg: { color: #333 } - } -} -``` - -The templates are collected in `on_after_apply`: -```rust -impl ScriptHook for PortalList { - fn on_after_apply(&mut self, vm: &mut ScriptVm, apply: &Apply, scope: &mut Scope, value: ScriptValue) { - if let Some(obj) = value.as_object() { - vm.vec_with(obj, |_vm, vec| { - for kv in vec { - if let Some(id) = kv.key.as_id() { - self.templates.insert(id, kv.value); - } - } - }); - } - } -} -``` - -Then used during drawing: -```rust -while let Some(item_id) = list.next_visible_item(cx) { - let item = list.item(cx, item_id, id!(Item)); - item.label(ids!(title)).set_text(cx, &format!("Item {}", item_id)); - item.draw_all(cx, &mut Scope::empty()); -} -``` - -**Key distinction**: Regular properties like `scroll_bar: mod.widgets.ScrollBar {}` are applied directly to struct fields. Template definitions like `Item := View {...}` are stored separately for dynamic instantiation. - -### PortalList Usage - -```rust -#[derive(Script, ScriptHook, Widget)] -pub struct MyList { - #[deref] view: View, -} - -impl Widget for MyList { - fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { - while let Some(item) = self.view.draw_walk(cx, scope, walk).step() { - if let Some(mut list) = item.borrow_mut::() { - list.set_item_range(cx, 0, 100); // 100 items - - while let Some(item_id) = list.next_visible_item(cx) { - let item = list.item(cx, item_id, id!(Item)); - item.label(ids!(title)).set_text(cx, &format!("Item {}", item_id)); - item.draw_all(cx, &mut Scope::empty()); - } - } - } - DrawStep::done() - } -} -``` - -### FileTree Usage - -```rust -impl Widget for FileTreeDemo { - fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { - while self.file_tree.draw_walk(cx, scope, walk).is_step() { - self.file_tree.set_folder_is_open(cx, live_id!(root), true, Animate::No); - // Draw nodes recursively - self.draw_node(cx, live_id!(root)); - } - DrawStep::done() - } -} -``` - -### Registering Custom Draw Shaders - -For custom draw types with shader fields, use `script_shader`: - -```rust -script_mod!{ - use mod.prelude.widgets_internal.* - - // Register custom draw shader - set_type_default() do #(DrawMyShader::script_shader(vm)){ - ..mod.draw.DrawQuad // Inherit from DrawQuad - } - - // Register widget that uses it - mod.widgets.MyWidgetBase = #(MyWidget::register_widget(vm)) -} - -#[derive(Script, ScriptHook)] -#[repr(C)] -struct DrawMyShader { - #[deref] draw_super: DrawQuad, - #[live] my_param: f32, -} -``` - -### Registering Components (non-Widget) - -For structs that aren't full widgets but need script registration: - -```rust -script_mod!{ - // For components (not widgets) - mod.widgets.MyComponentBase = #(MyComponent::script_component(vm)) - - // For widgets (implements Widget trait) - mod.widgets.MyWidgetBase = #(MyWidget::register_widget(vm)) -} -``` - -### Script Prelude Modules - -Two prelude modules available: -- `mod.prelude.widgets_internal.*` - For internal widget library development -- `mod.prelude.widgets.*` - For app development (includes all widgets) - -```rust -script_mod!{ - // App development - use widgets prelude - use mod.prelude.widgets.* - - // Or for widget library internals - use mod.prelude.widgets_internal.* - use mod.widgets.* -} -``` - -### Default Enum Values - -For enums with a `None` variant that need `Default`, use standard Rust `#[default]` attribute instead of `DefaultNone` derive: - -```rust -// Correct - use #[default] attribute on the None variant -#[derive(Clone, Copy, Debug, PartialEq, Default)] -pub enum MyAction { - SomeAction, - AnotherAction, - #[default] - None, -} - -// Wrong - don't use DefaultNone derive -#[derive(Clone, Copy, Debug, PartialEq, DefaultNone)] // Don't do this -pub enum MyAction { - SomeAction, - None, -} -``` - -### Multi-Module Script Registration Pattern - -When refactoring a multi-file project (like studio) from `live_design!` to `script_mod!`: - -1. **Each widget module** defines its own `script_mod!` that registers to `mod.widgets.*`: -```rust -// In studio_editor.rs -script_mod! { - use mod.prelude.widgets_internal.* - use mod.widgets.* - - mod.widgets.StudioCodeEditorBase = #(StudioCodeEditor::register_widget(vm)) - mod.widgets.StudioCodeEditor = set_type_default() do mod.widgets.StudioCodeEditorBase { - editor := CodeEditor {} - } -} -``` - -2. **The lib.rs** aggregates all widget script_mods: -```rust -pub fn script_mod(vm: &mut ScriptVm) { - crate::module1::script_mod(vm); - crate::module2::script_mod(vm); - // ... all widget modules -} -``` - -3. **The app.rs** calls them in correct order: -```rust -impl App { - fn run(vm: &mut ScriptVm) -> Self { - crate::makepad_widgets::script_mod(vm); // Base widgets first - crate::script_mod(vm); // Your widget modules - crate::app_ui::script_mod(vm); // UI that uses the widgets - App::from_script_mod(vm, self::script_mod) - } -} -``` - -4. **The app_ui.rs** can then use registered widgets: -```rust -script_mod! { - use mod.prelude.widgets.* - // Now StudioCodeEditor is available from mod.widgets - - let EditorContent = View { - editor := StudioCodeEditor {} - } -} -``` - -### Cross-Module Sharing via `mod` Object - -**IMPORTANT**: `use crate.module.*` does NOT work in script_mod. The `crate.` prefix is not available. - -To share definitions between script_mod blocks in different files, store them in the `mod` object: - -```rust -// In app_ui.rs - export to mod.widgets namespace -script_mod! { - use mod.prelude.widgets.* - - // This makes AppUI available as mod.widgets.AppUI - mod.widgets.AppUI = Window{ - // ... - } -} - -// In app.rs - import via mod.widgets -script_mod! { - use mod.prelude.widgets.* - use mod.widgets.* // Now AppUI is in scope - - load_all_resources() do #(App::script_component(vm)){ - ui: Root{ AppUI{} } - } -} -``` - -The `mod` object is the only way to share data between script_mod blocks. - -### Prelude Alias Syntax - -When defining a prelude, use `name:mod.path` to create an alias: -```rust -mod.prelude.widgets = { - ..mod.std, // Spread all of mod.std into scope - theme:mod.theme, // Create 'theme' as alias for mod.theme - draw:mod.draw, // Create 'draw' as alias for mod.draw -} -``` - -Without the alias (just `mod.theme,`), the module is included but has no name - you can't access it! - -### Let Bindings are Local - -`let` bindings in script_mod are LOCAL to that script_mod block. They cannot be: -- Accessed from other script_mod blocks -- Used as property values directly (e.g., `content +: MyLetBinding` won't work) - -To use a `let` binding, instantiate it: `MyLetBinding{}` or store it in `mod.*` for cross-module access. - -### Debug Logging with `~` - -Use `~expression` to log the value of an expression during script evaluation: -```rust -script_mod! { - ~mod.theme // Logs the theme object - ~mod.prelude.widgets // Logs what's in the prelude - ~some_variable // Logs a variable's value (or "not found" error) -} -``` - -### Common Pitfalls - -**Widget ID references**: Named widget instances use `:=` in the DSL and plain names in Rust id macros: -- DSL defines `code_block := View { ... }` → Rust uses `id!(code_block)` -- DSL defines `my_button := Button { ... }` → Rust uses `ids!(my_button)` - -1. **Missing `#[source]`**: All Script-derived structs need `#[source] source: ScriptObjectRef` - -2. **Template scope**: Templates defined inside Dock aren't available outside; use `let` at script level - -3. **Uniform vs Instance**: Use `instance()` for per-widget varying colors (like hover states on backgrounds) - -4. **Forgot `+:`**: Without `+:`, you replace the entire property instead of merging - -5. **Theme access**: Always `theme.color_x`, never `THEME_COLOR_X` or `(theme.color_x)` - -6. **Missing widget registration**: Call `crate::makepad_widgets::script_mod(vm)` in `App::run()` before your own `script_mod`. Note: the old `live_design!` system and its crates are archived under `old/` - -7. **Draw shader repr**: Custom draw shaders need `#[repr(C)]` for correct memory layout - -8. **DefaultNone derive**: Don't use `DefaultNone` derive - use standard `#[derive(Default)]` with `#[default]` attribute on the `None` variant - -9. **Script_mod call order**: Widget modules must be registered BEFORE UI modules that use them. Always call `lib.rs::script_mod` before `app_ui::script_mod` - -10. **`pub` keyword invalid in script_mod**: Don't use `pub mod.widgets.X = ...`, just use `mod.widgets.X = ...`. Visibility is controlled by the Rust module system, not script_mod. - -11. **Syntax for Inset/Align/Walk**: Use constructor syntax - `margin: Inset{left: 10}` not `margin: {left: 10}`, `align: Align{x: 0.5 y: 0.5}` not `align: {x: 0.5, y: 0.5}` - -12. **Cursor values**: Use `cursor: MouseCursor.Hand` not `cursor: Hand` or `cursor: @Hand` - -13. **Resource paths**: Use `crate_resource("self://path")` not `dep("crate://self/path")` - -14. **Texture declarations in shaders**: Use `tex: texture_2d(float)` not `tex: texture2d` - -15. **Enums not exposed to script**: Some Rust enums like `PopupMenuPosition::BelowInput` may not be exposed to script. If you get "not found" errors on enum variants, just remove the property and use the default - -17. **Shader `mod` vs `modf`**: The Makepad shader language uses `modf(a, b)` for float modulo, NOT `mod(a, b)`. Similarly, use `atan2(y, x)` not `atan(y, x)` for two-argument arctangent. `atan(x)` (single arg) is also available. `fract(x)` works as expected. - -16. **Draw shader struct field ordering**: In `#[repr(C)]` draw shader structs that extend another draw shader via `#[deref]`, NEVER place `#[rust]` or other non-instance data AFTER `DrawVars` and the instance fields. The system uses an unsafe pointer trick in `DrawVars::as_slice()` that reads contiguously past the end of `dyn_instances` into the subsequent `#[live]` fields. Any non-instance data between `DrawVars` and the instance fields will corrupt the GPU instance buffer. Put all extra data (like `#[rust]`, `#[live]` non-instance fields such as resource handles, booleans, etc.) BEFORE the `#[deref]` field, and only `#[live]` instance fields (the ones that map to shader inputs) AFTER. - ```rust - // CORRECT - non-instance data before deref, instance fields after - #[derive(Script, ScriptHook)] - #[repr(C)] - pub struct MyDrawShader { - #[live] pub svg: Option, // non-instance, BEFORE deref - #[rust] my_state: bool, // non-instance, BEFORE deref - #[deref] pub draw_super: DrawVector, // contains DrawVars + base instance fields - #[live] pub tint: Vec4f, // instance field, AFTER deref - OK - } - - // WRONG - rust data after instance fields breaks the memory layout - #[derive(Script, ScriptHook)] - #[repr(C)] - pub struct MyDrawShader { - #[deref] pub draw_super: DrawVector, - #[live] pub tint: Vec4f, // instance field - #[rust] my_state: bool, // BAD: sits between tint and the next shader's fields - } - ``` - -18. **Don't put comments or blank lines before the first real code in `script!`/`script_mod!`**: Rust's proc macro token stream strips comments entirely — they produce no tokens. This shifts error column/line info because the span tracking starts from the first actual token. Always start with real code (e.g., `use mod.std.assert`) immediately after the opening brace. - -19. **WARNING: Hex colors containing the letter `e` in `script_mod!`**: The Rust tokenizer interprets `e` or `E` in hex color literals as a scientific notation exponent, causing parse errors like `expected at least one digit in exponent`. For example, `#2ecc71` fails because `2e` looks like the start of `2e`. **Use the `#x` prefix** to escape this: write `#x2ecc71` instead of `#x2ecc71`. This applies to any hex color where a digit is immediately followed by `e`/`E` (e.g., `#1e1e2e`, `#4466ee`, `#7799ee`, `#bb99ee`). Colors without `e` (like `#ff4444`, `#44cc44`) work fine with plain `#`. - -20. **Shader enums**: Prefer `match` on enum values with `_ =>` as the catch-all arm, not `if/else` chains over integer-like values. If enum `match` fails in shader compilation, treat it as a compiler bug: add or extend a `platform/script/test` case and fix the shader compiler path instead of rewriting shader logic to `if/else`. \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index ff7277b67..c615b8cb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ version = 4 [[package]] name = "ab_glyph_rasterizer" version = "0.1.8" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" [[package]] name = "accessory" @@ -66,7 +66,7 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] @@ -230,15 +230,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbc3a507a82b17ba0d98f6ce8fd6954ea0c8152e98009d36a40d8dcc8ce078a" -[[package]] -name = "ash" -version = "0.38.0+1.3.281" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" -dependencies = [ - "libloading", -] - [[package]] name = "askar-crypto" version = "0.3.7" @@ -491,7 +482,7 @@ dependencies = [ "hyper-util", "itoa", "matchit", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "mime", "percent-encoding", "pin-project-lite", @@ -569,7 +560,7 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "cexpr", "clang-sys", "itertools 0.13.0", @@ -578,25 +569,16 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash 2.1.1", + "rustc-hash", "shlex", "syn 2.0.106", ] [[package]] -name = "bit-set" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.8.0" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" @@ -607,11 +589,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "bitflags" -version = "2.10.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - [[package]] name = "bitmaps" version = "3.2.1" @@ -727,8 +704,9 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.25.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] name = "byteorder" @@ -736,11 +714,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "byteorder" -version = "1.5.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - [[package]] name = "bytes" version = "1.11.1" @@ -937,15 +910,6 @@ dependencies = [ "cc", ] -[[package]] -name = "codespan-reporting" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" -dependencies = [ - "unicode-width", -] - [[package]] name = "colorchoice" version = "1.0.4" @@ -959,7 +923,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] @@ -970,7 +934,7 @@ checksum = "485abf41ac0c8047c07c87c72c8fb3eb5197f6e9d7ded615dfd1a00ae00a0f64" dependencies = [ "compression-core", "flate2", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] @@ -1021,7 +985,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" dependencies = [ - "unicode-segmentation 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", ] [[package]] @@ -1056,7 +1020,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" dependencies = [ - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] @@ -1273,6 +1237,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +[[package]] +name = "data-url" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" + [[package]] name = "date_header" version = "1.0.5" @@ -1468,7 +1438,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "objc2", ] @@ -1483,6 +1453,15 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -1605,7 +1584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1619,6 +1598,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "euclid" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +dependencies = [ + "num-traits", +] + [[package]] name = "event-listener" version = "5.4.1" @@ -1677,7 +1665,7 @@ dependencies = [ "futures-core", "imbl", "pin-project-lite", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", ] [[package]] @@ -1710,6 +1698,15 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + [[package]] name = "ff" version = "0.13.1" @@ -1742,6 +1739,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" + [[package]] name = "flume" version = "0.11.1" @@ -1918,7 +1921,7 @@ dependencies = [ "futures-macro", "futures-sink", "futures-task", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -1936,9 +1939,10 @@ dependencies = [ [[package]] name = "fxhash" version = "0.2.1" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" dependencies = [ - "byteorder 1.5.0 (git+https://github.com/makepad/makepad?branch=dev)", + "byteorder", ] [[package]] @@ -2084,7 +2088,6 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", - "num-traits", "zerocopy", ] @@ -2167,12 +2170,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - [[package]] name = "hilog-sys" version = "0.1.6" @@ -2244,7 +2241,7 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d347c0de239be20ba0982e4822de3124404281e119ae3e11f5d7425a414e1935" dependencies = [ - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "pastey", ] @@ -2265,7 +2262,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "150fa4a9462ef926824cf4519c84ed652ca8f4fbae34cb8af045b5cbcaf98822" dependencies = [ - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] @@ -2330,7 +2327,7 @@ dependencies = [ "itoa", "pin-project-lite", "pin-utils", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "tokio", "want", ] @@ -2456,7 +2453,7 @@ dependencies = [ "icu_normalizer_data", "icu_properties", "icu_provider", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "zerovec", ] @@ -2518,7 +2515,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "utf8_iter", ] @@ -2532,6 +2529,12 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "imagesize" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" + [[package]] name = "imbl" version = "6.1.0" @@ -2637,7 +2640,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" dependencies = [ - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "serde", ] @@ -2772,6 +2775,17 @@ dependencies = [ "typewit", ] +[[package]] +name = "kurbo" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62" +dependencies = [ + "arrayvec", + "euclid", + "smallvec", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -2815,7 +2829,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "libc", "redox_syscall", ] @@ -2837,7 +2851,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dfa36d52c581e9ec783a7ce2a5e0143da6237be5811a0b3153fedfdbe9f780" dependencies = [ - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] @@ -2951,38 +2965,34 @@ dependencies = [ ] [[package]] -name = "makepad-apple-sys" +name = "makepad-code-editor" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "makepad-objc-sys", + "makepad-widgets", ] [[package]] -name = "makepad-byteorder-lite" -version = "0.1.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - -[[package]] -name = "makepad-code-editor" -version = "2.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +name = "makepad-derive-live" +version = "1.0.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "makepad-widgets", + "makepad-live-id", + "makepad-micro-proc-macro", ] [[package]] name = "makepad-derive-wasm-bridge" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-micro-proc-macro", ] [[package]] name = "makepad-derive-widget" -version = "2.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "1.0.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-live-id", "makepad-micro-proc-macro", @@ -2990,57 +3000,99 @@ dependencies = [ [[package]] name = "makepad-draw" -version = "2.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "1.0.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "ab_glyph_rasterizer", "fxhash", + "makepad-html", "makepad-live-id", - "makepad-math", "makepad-platform", - "makepad-svg", - "makepad-webp", - "makepad-zune-jpeg", - "makepad-zune-png", - "rustybuzz", + "makepad-rustybuzz", + "makepad-vector", + "png", "sdfer", "serde", - "unicode-bidi 0.3.18 (git+https://github.com/makepad/makepad?branch=dev)", + "ttf-parser", + "unicode-bidi", "unicode-linebreak", - "unicode-segmentation 1.12.0 (git+https://github.com/makepad/makepad?branch=dev)", + "unicode-segmentation", ] [[package]] name = "makepad-error-log" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-micro-serde", ] [[package]] -name = "makepad-filesystem-watcher" -version = "0.1.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +name = "makepad-fonts-chinese-bold" +version = "1.0.1" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" +dependencies = [ + "makepad-platform", +] + +[[package]] +name = "makepad-fonts-chinese-bold-2" +version = "1.0.1" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" +dependencies = [ + "makepad-platform", +] + +[[package]] +name = "makepad-fonts-chinese-regular" +version = "1.0.1" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" +dependencies = [ + "makepad-platform", +] + +[[package]] +name = "makepad-fonts-chinese-regular-2" +version = "1.0.1" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" +dependencies = [ + "makepad-platform", +] + +[[package]] +name = "makepad-fonts-emoji" +version = "1.0.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" +dependencies = [ + "makepad-platform", +] [[package]] name = "makepad-futures" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" [[package]] name = "makepad-futures-legacy" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" [[package]] name = "makepad-html" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-live-id", ] +[[package]] +name = "makepad-http" +version = "1.0.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" +dependencies = [ + "makepad-script", +] + [[package]] name = "makepad-jni-sys" version = "0.4.0" @@ -3048,17 +3100,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9775cbec5fa0647500c3e5de7c850280a88335d1d2d770e5aa2332b801ba7064" [[package]] -name = "makepad-latex-math" -version = "0.1.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +name = "makepad-live-compiler" +version = "1.0.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "ttf-parser", + "makepad-derive-live", + "makepad-live-tokenizer", + "makepad-math", ] [[package]] name = "makepad-live-id" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-live-id-macros", "serde", @@ -3067,23 +3121,25 @@ dependencies = [ [[package]] name = "makepad-live-id-macros" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-micro-proc-macro", ] [[package]] -name = "makepad-live-reload-core" -version = "0.1.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +name = "makepad-live-tokenizer" +version = "1.0.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "makepad-filesystem-watcher", + "makepad-live-id", + "makepad-math", + "makepad-micro-serde", ] [[package]] name = "makepad-math" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-micro-serde", ] @@ -3091,12 +3147,12 @@ dependencies = [ [[package]] name = "makepad-micro-proc-macro" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" [[package]] name = "makepad-micro-serde" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-live-id", "makepad-micro-serde-derive", @@ -3105,187 +3161,153 @@ dependencies = [ [[package]] name = "makepad-micro-serde-derive" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-micro-proc-macro", ] -[[package]] -name = "makepad-network" -version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "makepad-apple-sys", - "makepad-error-log", - "makepad-futures-legacy", - "makepad-live-id", - "makepad-micro-serde", - "makepad-script", - "windows 0.62.2", -] - [[package]] name = "makepad-objc-sys" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" [[package]] name = "makepad-platform" -version = "2.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "1.0.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "ash", - "bitflags 2.10.0 (git+https://github.com/makepad/makepad?branch=dev)", + "bitflags 2.10.0", "hilog-sys", "makepad-android-state", - "makepad-apple-sys", + "makepad-error-log", "makepad-futures", "makepad-futures-legacy", + "makepad-http", "makepad-jni-sys", - "makepad-live-reload-core", - "makepad-network", "makepad-objc-sys", - "makepad-script", - "makepad-script-std", - "makepad-shared-bytes", - "makepad-studio-protocol", + "makepad-shader-compiler", "makepad-wasm-bridge", - "makepad-zune-png", - "naga", "napi-derive-ohos", "napi-ohos", "ohos-sys", - "smallvec 1.15.1 (git+https://github.com/makepad/makepad?branch=dev)", + "smallvec", "wayland-client", "wayland-egl", "wayland-protocols", - "windows 0.62.2", - "windows-core 0.62.2", + "windows 0.56.0", + "windows-core 0.56.0", "windows-targets 0.52.6", ] [[package]] -name = "makepad-regex" -version = "0.1.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +name = "makepad-rustybuzz" +version = "0.8.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" +dependencies = [ + "bitflags 1.3.2", + "bytemuck", + "makepad-ttf-parser", + "smallvec", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-properties", + "unicode-script", +] [[package]] name = "makepad-script" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-error-log", - "makepad-html", "makepad-live-id", "makepad-math", - "makepad-regex", "makepad-script-derive", - "smallvec 1.15.1 (git+https://github.com/makepad/makepad?branch=dev)", + "smallvec", ] [[package]] name = "makepad-script-derive" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-micro-proc-macro", ] [[package]] -name = "makepad-script-std" +name = "makepad-shader-compiler" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "makepad-network", - "makepad-script", + "makepad-live-compiler", ] [[package]] -name = "makepad-shared-bytes" -version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - -[[package]] -name = "makepad-studio-protocol" -version = "0.1.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "bitflags 2.10.0 (git+https://github.com/makepad/makepad?branch=dev)", - "makepad-error-log", - "makepad-live-id", - "makepad-micro-serde", - "makepad-script", -] +name = "makepad-ttf-parser" +version = "0.21.1" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" [[package]] -name = "makepad-svg" +name = "makepad-vector" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "makepad-html", - "makepad-live-id", + "makepad-ttf-parser", + "resvg", ] [[package]] name = "makepad-wasm-bridge" version = "1.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-derive-wasm-bridge", "makepad-live-id", ] -[[package]] -name = "makepad-webp" -version = "0.2.4" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "makepad-byteorder-lite", -] - [[package]] name = "makepad-widgets" -version = "2.0.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "1.0.0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-derive-widget", "makepad-draw", + "makepad-fonts-chinese-bold", + "makepad-fonts-chinese-bold-2", + "makepad-fonts-chinese-regular", + "makepad-fonts-chinese-regular-2", + "makepad-fonts-emoji", "makepad-html", - "makepad-latex-math", + "makepad-zune-jpeg", + "makepad-zune-png", "pulldown-cmark 0.12.2", "serde", - "ttf-parser", - "unicode-segmentation 1.12.0 (git+https://github.com/makepad/makepad?branch=dev)", + "unicode-segmentation", ] [[package]] name = "makepad-zune-core" -version = "0.5.1" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - -[[package]] -name = "makepad-zune-inflate" -version = "0.2.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.2.14" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "simd-adler32", + "bitflags 2.10.0", ] [[package]] name = "makepad-zune-jpeg" -version = "0.5.12" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.3.17" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ "makepad-zune-core", ] [[package]] name = "makepad-zune-png" -version = "0.5.1" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.4.10" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" dependencies = [ - "makepad-zune-core", - "makepad-zune-inflate", + "zune-core", + "zune-inflate", ] [[package]] @@ -3420,7 +3442,7 @@ source = "git+https://github.com/matrix-org/matrix-rust-sdk?branch=main#d64c9906 dependencies = [ "as_variant", "async-trait", - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "decancer", "eyeball", "eyeball-im", @@ -3473,7 +3495,7 @@ dependencies = [ "as_variant", "async-trait", "bs58", - "byteorder 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", "cfg-if", "ctr", "eyeball", @@ -3590,7 +3612,7 @@ dependencies = [ "async-rx", "async-stream", "async_cell", - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "chrono", "emojis", "eyeball", @@ -3617,7 +3639,7 @@ dependencies = [ "tokio-stream", "tracing", "unicode-normalization", - "unicode-segmentation 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", ] [[package]] @@ -3637,7 +3659,7 @@ dependencies = [ "sealed", "serde", "serde-wasm-bindgen", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "thiserror 2.0.17", "tokio", "wasm-bindgen", @@ -3675,11 +3697,6 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" -[[package]] -name = "memchr" -version = "2.7.6" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - [[package]] name = "mime" version = "0.3.17" @@ -3705,6 +3722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -3728,32 +3746,6 @@ dependencies = [ "unsigned-varint", ] -[[package]] -name = "naga" -version = "27.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" -dependencies = [ - "arrayvec", - "bit-set", - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if", - "cfg_aliases", - "codespan-reporting", - "half", - "hashbrown 0.16.1", - "hexf-parse", - "indexmap 2.13.0", - "libm", - "log", - "num-traits", - "once_cell", - "rustc-hash 1.1.0", - "spirv", - "thiserror 2.0.17", - "unicode-ident", -] - [[package]] name = "napi-derive-backend-ohos" version = "0.0.7" @@ -3788,7 +3780,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad5a3bbb2ae61f345b8c11776f2e79fc2bb71d1901af9a5f81f03c9238a05d86" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "ctor", "napi-sys-ohos", "once_cell", @@ -3838,7 +3830,7 @@ version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "minimal-lexical", ] @@ -3863,7 +3855,7 @@ dependencies = [ "num-iter", "num-traits", "rand 0.8.5", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "zeroize", ] @@ -3948,7 +3940,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "objc2", "objc2-foundation", ] @@ -3959,7 +3951,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "dispatch2", "objc2", ] @@ -3986,7 +3978,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "objc2", "objc2-core-foundation", ] @@ -3997,7 +3989,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "block2", "objc2", "objc2-foundation", @@ -4033,7 +4025,7 @@ version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "cfg-if", "foreign-types", "libc", @@ -4126,7 +4118,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "windows-targets 0.52.6", ] @@ -4234,6 +4226,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -4273,6 +4271,19 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "poly1305" version = "0.8.0" @@ -4410,11 +4421,13 @@ dependencies = [ [[package]] name = "pulldown-cmark" version = "0.12.2" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" dependencies = [ - "bitflags 2.10.0 (git+https://github.com/makepad/makepad?branch=dev)", - "memchr 2.7.6 (git+https://github.com/makepad/makepad?branch=dev)", - "unicase 2.9.0", + "bitflags 2.10.0", + "memchr", + "pulldown-cmark-escape", + "unicase", ] [[package]] @@ -4423,10 +4436,10 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", + "memchr", "pulldown-cmark-escape", - "unicase 2.8.1", + "unicase", ] [[package]] @@ -4435,6 +4448,15 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + [[package]] name = "quinn" version = "0.11.9" @@ -4446,7 +4468,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.1", + "rustc-hash", "rustls", "socket2", "thiserror 2.0.17", @@ -4467,7 +4489,7 @@ dependencies = [ "lru-slab", "rand 0.9.2", "ring", - "rustc-hash 2.1.1", + "rustc-hash", "rustls", "rustls-pki-types", "slab", @@ -4601,7 +4623,7 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", ] [[package]] @@ -4642,7 +4664,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "regex-automata", "regex-syntax", ] @@ -4654,7 +4676,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "regex-syntax", ] @@ -4712,6 +4734,20 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "resvg" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "944d052815156ac8fa77eaac055220e95ba0b01fa8887108ca710c03805d9051" +dependencies = [ + "log", + "pico-args", + "rgb", + "svgtypes", + "tiny-skia", + "usvg", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -4722,6 +4758,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "rgb" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" +dependencies = [ + "bytemuck", +] + [[package]] name = "ring" version = "0.17.14" @@ -4742,7 +4787,7 @@ version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" dependencies = [ - "byteorder 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", "num-traits", "paste", ] @@ -4753,7 +4798,7 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" dependencies = [ - "byteorder 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", "rmp", "serde", ] @@ -4826,7 +4871,7 @@ version = "0.0.1-pre-alpha-4" dependencies = [ "anyhow", "aws-lc-rs", - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "blurhash", "bytesize", "chrono", @@ -4864,10 +4909,16 @@ dependencies = [ "tokio", "tracing-subscriber", "tsp_sdk", - "unicode-segmentation 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", "url", ] +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + [[package]] name = "rsa" version = "0.9.10" @@ -5062,20 +5113,14 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "fallible-iterator", "fallible-streaming-iterator", "hashlink", "libsqlite3-sys", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", ] -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -5097,11 +5142,11 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5169,22 +5214,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "rustybuzz" -version = "0.18.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "bitflags 2.10.0 (git+https://github.com/makepad/makepad?branch=dev)", - "bytemuck", - "makepad-error-log", - "smallvec 1.15.1 (git+https://github.com/makepad/makepad?branch=dev)", - "ttf-parser", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties 0.1.4", - "unicode-script", -] - [[package]] name = "ryu" version = "1.0.20" @@ -5272,7 +5301,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sdfer" version = "0.2.1" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "git+https://github.com/makepad/makepad?branch=dev#2898fb1367a95385df79141cd765bf8cf0719b8d" [[package]] name = "sealed" @@ -5304,7 +5333,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -5317,7 +5346,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc198e42d9b7510827939c9a15f5062a0c913f3371d765977e586d2fe6c16f4a" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -5420,7 +5449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "serde", "serde_core", "zmij", @@ -5570,8 +5599,18 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.8" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simplecss" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9c6883ca9c3c7c90e888de77b7a5c849c779d25d74a1269b0218b14e8b136c" +dependencies = [ + "log", +] [[package]] name = "siphasher" @@ -5594,11 +5633,6 @@ dependencies = [ "serde", ] -[[package]] -name = "smallvec" -version = "1.15.1" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - [[package]] name = "socket2" version = "0.6.0" @@ -5618,15 +5652,6 @@ dependencies = [ "lock_api", ] -[[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" -dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "spki" version = "0.7.3" @@ -5669,13 +5694,13 @@ dependencies = [ "hashlink", "indexmap 2.13.0", "log", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "once_cell", "percent-encoding", "serde", "serde_json", "sha2 0.10.9", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "thiserror 2.0.17", "tokio", "tokio-stream", @@ -5726,8 +5751,8 @@ source = "git+https://github.com/project-robius/sqlx.git?branch=update_libsqlite dependencies = [ "atoi", "base64", - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", + "byteorder", "bytes", "chrono", "crc", @@ -5745,7 +5770,7 @@ dependencies = [ "itoa", "log", "md-5", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "once_cell", "percent-encoding", "rand 0.8.5", @@ -5753,7 +5778,7 @@ dependencies = [ "serde", "sha1", "sha2 0.10.9", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "sqlx-core", "stringprep", "thiserror 2.0.17", @@ -5768,8 +5793,8 @@ source = "git+https://github.com/project-robius/sqlx.git?branch=update_libsqlite dependencies = [ "atoi", "base64", - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", + "byteorder", "chrono", "crc", "dotenvy", @@ -5784,13 +5809,13 @@ dependencies = [ "itoa", "log", "md-5", - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", "once_cell", "rand 0.8.5", "serde", "serde_json", "sha2 0.10.9", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "sqlx-core", "stringprep", "thiserror 2.0.17", @@ -5828,6 +5853,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +dependencies = [ + "float-cmp", +] + [[package]] name = "string_cache" version = "0.8.9" @@ -5859,9 +5893,9 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "unicode-bidi 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi", "unicode-normalization", - "unicode-properties 0.1.3", + "unicode-properties", ] [[package]] @@ -5876,6 +5910,16 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "svgtypes" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c7541fff44b35860c1a7a47a7cadf3e4a304c457b58f9870d9706ece028afc" +dependencies = [ + "kurbo", + "siphasher", +] + [[package]] name = "syn" version = "1.0.109" @@ -5924,7 +5968,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -5949,7 +5993,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6043,6 +6087,32 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + [[package]] name = "tinystr" version = "0.8.1" @@ -6222,7 +6292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "async-compression", - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "bytes", "futures-core", "futures-util", @@ -6305,7 +6375,7 @@ dependencies = [ "once_cell", "regex-automata", "sharded-slab", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "thread_local", "tracing", "tracing-core", @@ -6362,8 +6432,9 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.24.1" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" [[package]] name = "tungstenite" @@ -6421,31 +6492,23 @@ version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" -[[package]] -name = "unicase" -version = "2.9.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - [[package]] name = "unicode-bidi" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - [[package]] name = "unicode-bidi-mirroring" -version = "0.3.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694" [[package]] name = "unicode-ccc" -version = "0.3.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" [[package]] name = "unicode-ident" @@ -6456,7 +6519,8 @@ checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-linebreak" version = "0.1.5" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" @@ -6473,32 +6537,17 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" -[[package]] -name = "unicode-properties" -version = "0.1.4" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - [[package]] name = "unicode-script" -version = "0.5.8" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" [[package]] name = "unicode-segmentation" version = "1.12.0" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - -[[package]] -name = "unicode-width" -version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-xid" @@ -6552,6 +6601,28 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "usvg" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84ea542ae85c715f07b082438a4231c3760539d902e11d093847a0b22963032" +dependencies = [ + "base64", + "data-url", + "flate2", + "imagesize", + "kurbo", + "log", + "pico-args", + "roxmltree", + "simplecss", + "siphasher", + "strict-num", + "svgtypes", + "tiny-skia-path", + "xmlwriter", +] + [[package]] name = "utf-8" version = "0.7.6" @@ -6763,7 +6834,7 @@ dependencies = [ "fancy_constructor", "futures-core", "js-sys", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "tokio", "wasm-bindgen", "web-sys", @@ -6771,30 +6842,35 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.12" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" dependencies = [ + "cc", "downcast-rs", - "libc", + "rustix", "scoped-tls", - "smallvec 1.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec", "wayland-sys", ] [[package]] name = "wayland-client" -version = "0.31.12" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc", + "bitflags 2.10.0", + "rustix", "wayland-backend", + "wayland-scanner", ] [[package]] name = "wayland-egl" -version = "0.32.9" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.32.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36232ee23ba3ea34a6835d68ca1af91d3ca3d6eddcf9c7147c4e0e66901b9fd" dependencies = [ "wayland-backend", "wayland-sys", @@ -6802,19 +6878,34 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.10" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.32.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" dependencies = [ - "bitflags 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.10.0", "wayland-backend", "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", ] [[package]] name = "wayland-sys" -version = "0.31.8" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" dependencies = [ + "dlib", "log", "pkg-config", ] @@ -6902,23 +6993,13 @@ version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-collections 0.2.0", + "windows-collections", "windows-core 0.61.2", - "windows-future 0.2.1", + "windows-future", "windows-link 0.1.3", "windows-numerics", ] -[[package]] -name = "windows" -version = "0.62.2" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "windows-collections 0.3.2", - "windows-core 0.62.2", - "windows-future 0.3.2", -] - [[package]] name = "windows-collections" version = "0.2.0" @@ -6928,14 +7009,6 @@ dependencies = [ "windows-core 0.61.2", ] -[[package]] -name = "windows-collections" -version = "0.3.2" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "windows-core 0.62.2", -] - [[package]] name = "windows-core" version = "0.56.0" @@ -6958,17 +7031,7 @@ dependencies = [ "windows-interface 0.59.2", "windows-link 0.1.3", "windows-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", + "windows-strings", ] [[package]] @@ -6982,14 +7045,6 @@ dependencies = [ "windows-threading", ] -[[package]] -name = "windows-future" -version = "0.3.2" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "windows-core 0.62.2", -] - [[package]] name = "windows-implement" version = "0.56.0" @@ -7046,11 +7101,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" -[[package]] -name = "windows-link" -version = "0.2.1" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" - [[package]] name = "windows-numerics" version = "0.2.0" @@ -7069,7 +7119,7 @@ checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ "windows-link 0.1.3", "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-strings", ] [[package]] @@ -7090,14 +7140,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-result" -version = "0.4.1" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows-strings" version = "0.4.2" @@ -7107,14 +7149,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "git+https://github.com/makepad/makepad?branch=dev#84ec5394bab142fc58431d5ef7bdff65ac03feb0" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -7427,7 +7461,7 @@ version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ - "memchr 2.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] @@ -7454,6 +7488,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + [[package]] name = "xxhash-rust" version = "0.8.15" @@ -7583,3 +7623,18 @@ name = "zmij" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd8f3f50b848df28f887acb68e41201b5aea6bc8a8dacc00fb40635ff9a72fea" + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] diff --git a/Cargo.toml b/Cargo.toml index 505f9d570..770905156 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,17 @@ [package] name = "robrix" -authors = ["Kevin Boos ", "Robius Project Maintainers"] +authors = [ + "Kevin Boos ", + "Robius Project Maintainers", +] description = "A Matrix chat client written using Makepad + Robius app dev framework in Rust." documentation = "https://docs.rs/robrix" -edition = "2024" ## mostly just to allow let-chains +edition = "2024" ## mostly just to allow let-chains homepage = "https://robius.rs/" keywords = ["matrix", "chat", "client", "robius", "makepad"] license = "MIT" readme = "README.md" -categories = ["gui"] +categories = [ "gui" ] repository = "https://github.com/project-robius/robrix" version = "0.0.1-pre-alpha-4" metadata.makepad-auto-version = "zqpv-Yj-K7WNVK2I8h5Okhho46Q=" @@ -18,7 +21,6 @@ makepad-widgets = { git = "https://github.com/makepad/makepad", branch = "dev", makepad-code-editor = { git = "https://github.com/makepad/makepad", branch = "dev" } - ## Including this crate automatically configures all `robius-*` crates to work with Makepad. robius-use-makepad = "0.1.1" robius-open = { git = "https://github.com/project-robius/robius" } @@ -34,9 +36,9 @@ chrono = "0.4" clap = { version = "4.0.16", features = ["derive"] } crossbeam-channel = "0.5.10" crossbeam-queue = "0.3.8" -eyeball = { version = "0.8.8", features = ["tracing"] } # same as matrix-sdk-ui -eyeball-im = { version = "0.8.0", features = [ "tracing" ] } # same as matrix-sdk-ui -imbl = { version = "6.1.0", features = ["serde"] } # same as matrix-sdk-ui +eyeball = { version = "0.8.8", features = ["tracing"] } # same as matrix-sdk-ui +eyeball-im = { version = "0.8.0", features = ["tracing"] } # same as matrix-sdk-ui +imbl = { version = "6.1.0", features = ["serde"] } # same as matrix-sdk-ui futures-util = "0.3" hashbrown = { version = "0.16", features = ["raw-entry"] } htmlize = "1.0.5" @@ -44,27 +46,14 @@ indexmap = "2.6.0" imghdr = "0.7.0" linkify = "0.10.0" matrix-sdk-base = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "main" } -matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "main", default-features = false, features = [ - "e2e-encryption", - "automatic-room-key-forwarding", - "markdown", - "sqlite", - "rustls-tls", - "bundled-sqlite", - "sso-login", -] } -matrix-sdk-ui = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "main", default-features = false, features = [ - "rustls-tls", -] } +matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "main", default-features = false, features = [ "e2e-encryption", "automatic-room-key-forwarding", "markdown", "sqlite", "rustls-tls", "bundled-sqlite", "sso-login" ] } +matrix-sdk-ui = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "main", default-features = false, features = [ "rustls-tls" ] } ## Use the same ruma version as what's specified in matrix-sdk's Cargo.toml. ## Enable a few extra features: ## * "compat-optional" feature to allow missing body field in m.room.tombstone event. ## * "compat-unset-avatar" feature to allow deleting the user's avatar to work properly. ## * Note: we need a feature like "compat-unset-display-name" to unset display names, but that doesn't exist yet. -ruma = { version = "0.14.1", features = [ - "compat-optional", - "compat-unset-avatar", -] } +ruma = { version = "0.14.1", features = ["compat-optional", "compat-unset-avatar"] } rand = "0.8.5" rangemap = "1.5.0" sanitize-filename = "0.6" @@ -81,10 +70,7 @@ url = "2.5.0" ## Commit "f0bc4625dcd729e07e4a36257df2f1d94c81cef4" is the most recent one without the invalid change to pin serde to 1.0.219. ## See my issue here: . ## However, that commit doesn't build.... yikes. So we have to use a slightly older commit in the "rev" field below. -tsp_sdk = { git = "https://github.com/openwallet-foundation-labs/tsp.git", rev = "1cd0cc9442e144ad7c01ccd30daffbb3a52c0f20", optional = true, features = [ - "async", - "resolve", -] } +tsp_sdk = { git = "https://github.com/openwallet-foundation-labs/tsp.git", rev = "1cd0cc9442e144ad7c01ccd30daffbb3a52c0f20", optional = true, features = ["async", "resolve"] } quinn = { version = "0.11", default-features = false, optional = true } ## We only include this such that we can specify the prebuilt-nasm features, ## which is required to build this on Windows x86_64 without having to install NASM separately. @@ -151,7 +137,7 @@ askar-storage = { git = "https://github.com/openwallet-foundation/askar.git" } ## and then we won't need to patch ruma-events anymore. ## But that is a significant amount of work, so for now we just patch ruma-events. ## -ruma = { git = "https://github.com/project-robius/ruma.git", branch = "tsp" } +ruma = { git = "https://github.com/project-robius/ruma.git", branch = "tsp"} [package.metadata.docs.rs] @@ -185,15 +171,13 @@ strip = true debug-assertions = false + ## Configuration for `cargo packager` [package.metadata.packager] product_name = "Robrix" identifier = "org.robius.robrix" category = "SocialNetworking" -authors = [ - "Project Robius ", - "Kevin Boos ", -] +authors = ["Project Robius ", "Kevin Boos "] publisher = "robius" license_file = "LICENSE-MIT" copyright = "Copyright 2023-202, Project Robius" @@ -237,10 +221,7 @@ robius-packaging-commands before-each-package \ """ deep_link_protocols = [ - { schemes = [ - "robrix", - "matrix", - ], role = "viewer" }, ## `name` is left as default + { schemes = ["robrix", "matrix"], role = "viewer" }, ## `name` is left as default ] [package.metadata.packager.deb] @@ -250,10 +231,10 @@ section = "utils" [package.metadata.packager.macos] minimum_system_version = "11.0" -frameworks = [] +frameworks = [ ] info_plist_path = "./packaging/Info.plist" entitlements = "./packaging/Entitlements.plist" -signing_identity = "Developer ID Application: GOSIM FOUNDATION LTD. (HMX6XGJZ3R)" +signing_identity = "Developer ID Application: AppChef Inc. (SFVQ5V48GD)" ## Configuration for `cargo packager`'s generation of a macOS `.dmg`. diff --git a/SPLASH.md b/SPLASH.md deleted file mode 100644 index 88af44bba..000000000 --- a/SPLASH.md +++ /dev/null @@ -1,2362 +0,0 @@ -# Splash Script Manual (Terse AI Reference) - -Splash is Makepad's UI scripting language. It is whitespace-delimited, but Robrix prefers either newlines or commas to separate properties, for readability's sake. -**Please always use newlines or commas to separate properties, not just whitespace.** - -**Do NOT use `Root{}` or `Window{}`** — those are host-level wrappers handled externally. Your output is the content inside a body/splash widget. - ---- - -## NAMING CHILDREN: Use `:=` for dynamic/list properties - -In Splash, when you declare a named child widget inside a `let` template (or any container), you use the `:=` operator. This marks the child as a **named/dynamic** property — addressable and overridable per-instance. - -- To declare: `label := Label{text: "default"}` -- To override: `MyTemplate{label.text: "new value"}` - -If you write `label:` (colon) instead of `label :=` (colon-equals), the child is a **static** property — not addressable, and overrides fail silently (text becomes invisible). - -**Use `:=` for any child you want to reference or override later:** `check :=`, `label :=`, `tag :=`, `title :=`, `body :=`, `icon :=`, `content :=`, etc. - -## COPY-PASTE REFERENCE: Todo list - -``` -let TodoItem = View{ - width: Fill height: Fit - padding: Inset{top: 8 bottom: 8 left: 12 right: 12} - flow: Right spacing: 10 - align: Align{y: 0.5} - check := CheckBox{text: ""} - label := Label{text: "task" draw_text.color: #ddd draw_text.text_style.font_size: 11} - Filler{} - tag := Label{text: "" draw_text.color: #888 draw_text.text_style.font_size: 9} -} - -RoundedView{ - width: 380 height: Fit - flow: Down spacing: 4 - padding: 16 - new_batch: true - draw_bg.color: #1e1e2e - draw_bg.border_radius: 10.0 - Label{text: "My Tasks" draw_text.color: #fff draw_text.text_style.font_size: 14} - Hr{} - TodoItem{label.text: "Buy groceries" tag.text: "errands"} - TodoItem{label.text: "Fix login bug" tag.text: "urgent"} - TodoItem{label.text: "Write unit tests" tag.text: "dev"} - TodoItem{label.text: "Call the dentist" tag.text: "personal"} -} -``` - -## COPY-PASTE REFERENCE: Card with title and body - -``` -let InfoCard = RoundedView{ - width: Fill height: Fit - padding: 16 flow: Down spacing: 6 - draw_bg.color: #2a2a3d - draw_bg.border_radius: 8.0 - title := Label{text: "Title" draw_text.color: #fff draw_text.text_style.font_size: 14} - body := Label{text: "Body" draw_text.color: #aaa draw_text.text_style.font_size: 11} -} - -View{ - flow: Down height: Fit spacing: 10 padding: 20 - InfoCard{title.text: "First card" body.text: "Some content here"} - InfoCard{title.text: "Second card" body.text: "More content here"} -} -``` - ---- - -## 🚫 DO NOT INVENT SYNTAX OR PROPERTIES 🚫 - -**ONLY use widgets, properties, and syntax documented in this manual.** This code must compile and run — do not: - -- Invent new properties (e.g., don't write `background_color:` — use `draw_bg.color:`) -- Guess at property names (e.g., don't write `font_size:` — use `draw_text.text_style.font_size:`) -- Make up new widgets that aren't listed here -- Suggest hypothetical features or syntax that "might work" -- Use CSS-like property names (no `border-radius`, use `draw_bg.border_radius`) - -If you're unsure whether a property exists, **don't use it**. Stick to the exact syntax shown in the examples. - ---- - -## 📝 OUTPUT FORMAT: CODE ONLY 📝 - -**When generating UI, output ONLY the Splash code.** Do not add: - -- Explanatory text before or after the code -- "Here's the UI:" or "This creates..." preambles -- Suggestions for improvements or alternatives -- Commentary about what the code does - -Just output the raw Splash script starting with `use mod.prelude.widgets.*` — nothing else. - ---- - -## ⛔⛔⛔ CRITICAL: YOU MUST SET `height: Fit` ON EVERY CONTAINER ⛔⛔⛔ - -**STOP. READ THIS. THE #1 MISTAKE IS FORGETTING `height: Fit`.** - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ EVERY View, SolidView, RoundedView MUST HAVE height: Fit │ -│ │ -│ ✅ View{ flow: Down height: Fit padding: 10 ... } │ -│ │ -│ If you forget height: Fit, your UI will be INVISIBLE (0px) │ -└─────────────────────────────────────────────────────────────────┘ -``` - -**Why?** The default is `height: Fill`. Your output renders in a `Fit` container. `Fill` inside `Fit` = circular dependency = **0 height**. - -**ALWAYS write `height: Fit` immediately after the opening brace:** - -``` -View{ height: Fit flow: Down padding: 10 - Label{text: "Visible!"} -} - -SolidView{ height: Fit width: Fill draw_bg.color: #333 - Label{text: "Also visible!"} -} - -RoundedView{ height: Fit width: Fill flow: Down spacing: 8 - Label{text: "Card content"} -} -``` - -**Exceptions:** -1. Inside a fixed-height parent, `height: Fill` is OK: -``` -View{ height: 300 // Fixed parent - View{ height: Fill // OK here - fills the 300px - Label{text: "I fill the fixed 300px"} - } -} -``` -2. **MapView** — has no intrinsic height, so `height: Fit` also gives 0px. Use a **fixed pixel height**: `MapView{width: Fill height: 500}` - -**TEMPLATE: Copy this pattern for every container:** -``` -View{ height: Fit ...rest of properties... - ...children... -} -``` - ---- - -## ⛔⛔⛔ CRITICAL: USE `width: Fill` ON THE ROOT CONTAINER ⛔⛔⛔ - -**NEVER use a fixed pixel width (e.g., `width: 400`) on your outermost container.** Your output renders inside a container that provides available width — use `width: Fill` to fill it. - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ The ROOT container MUST use width: Fill │ -│ │ -│ ✅ RoundedView{ width: Fill height: Fit ... } │ -│ ❌ RoundedView{ width: 400 height: Fit ... } │ -│ │ -│ Fixed widths make your UI a narrow sliver or completely broken │ -└─────────────────────────────────────────────────────────────────┘ -``` - -**Why?** A fixed width like `width: 400` does not adapt to the available space. Worse, if the parent container is narrower than 400, your content gets clipped. If a parse error occurs anywhere in the code, the entire layout can collapse to near-zero width. - -**ALWAYS use `width: Fill` on the root element:** -``` -RoundedView{ width: Fill height: Fit flow: Down - // your content -} -``` - -Fixed pixel widths are fine for **inner elements** like icons, avatars, or specific components — just never on the outermost container. - ---- - -## ⛔ CRITICAL: `draw_bg.border_radius` TAKES A FLOAT, NOT AN INSET ⛔ - -``` -✅ draw_bg.border_radius: 16.0 -❌ draw_bg.border_radius: Inset{top: 0 bottom: 16 left: 0 right: 0} -``` - -`border_radius` is a single `f32` value applied uniformly to all corners. Passing an `Inset` or object will cause a parse error that can **silently break your entire layout**. - ---- - -## ⚠️ USE STYLED VIEWS, NOT RAW `View{}` ⚠️ - -**Do NOT use `View{ show_bg: true ... }`** — the raw View has an ugly green test color as its background. - -Instead, use these pre-styled container widgets that have proper backgrounds: - -| Widget | Use for | -|--------|---------| -| `SolidView` | Simple solid color background | -| `RoundedView` | Rounded corners with optional border | -| `RectView` | Rectangle with optional border | -| `RoundedShadowView` | Rounded corners with drop shadow | -| `RectShadowView` | Rectangle with drop shadow | -| `CircleView` | Circular shape | -| `GradientXView` | Horizontal gradient | -| `GradientYView` | Vertical gradient | - -All have `show_bg: true` already set. Set color via `draw_bg.color`: - -``` -SolidView{ width: Fill height: Fit draw_bg.color: #334 - Label{text: "Content here"} -} - -RoundedView{ width: Fill height: Fit draw_bg.color: #445 draw_bg.border_radius: 8.0 - Label{text: "Rounded card"} -} - -RoundedShadowView{ width: Fill height: Fit draw_bg.color: #556 draw_bg.shadow_radius: 10.0 - Label{text: "Card with shadow"} -} -``` - -**Use raw `View{}` only when you need no background** (invisible layout container). - ---- - -## Script Structure - -Every splash script must start with a `use` statement to bring widgets into scope: - -``` -use mod.prelude.widgets.* - -// Now all widgets (View, Label, Button, etc.) are available -View{ - flow: Down - height: Fit // ← ALWAYS set height! Default is Fill which breaks in Fit containers - padding: 20 - Label{text: "Hello world"} -} -``` - -Without `use mod.prelude.widgets.*` at the top, widget names like `View`, `Label`, `Button` etc. will not be found. - -### Let bindings for reusable definitions - -Use `let` to define reusable widget templates. **`let` bindings must be defined ABOVE (before) the places where they are used.** They are local to the current scope. - -**When a template has children you want to customize per-instance, you MUST use `id :=` declarations.** See the critical rule below. - -``` -use mod.prelude.widgets.* - -// Simple template with NO per-instance children — just style overrides -let MyHeader = Label{ - draw_text.color: #fff - draw_text.text_style.font_size: 16 -} - -// Template WITH per-instance children — MUST use id := declarations -let MyCard = RoundedView{ - width: Fill height: Fit - padding: 15 flow: Down spacing: 8 - draw_bg.color: #334 - draw_bg.border_radius: 8.0 - title := Label{text: "default" draw_text.color: #fff draw_text.text_style.font_size: 16} - body := Label{text: "" draw_text.color: #aaa} -} - -// Override children using id.property syntax -View{ - flow: Down height: Fit - spacing: 12 padding: 20 - MyCard{title.text: "First Card" body.text: "Content here"} - MyCard{title.text: "Second Card" body.text: "More content"} -} -``` - -### Naming children in templates — the `:=` operator - -Children inside a `let` template that you want to override per-instance MUST be declared with `:=`. This is part of the syntax — `label :=` creates a named/dynamic child, `label:` does not. - -**Reusable todo/list item with multiple named children:** - -``` -let TodoItem = View{ - width: Fill height: Fit - padding: Inset{top: 8 bottom: 8 left: 12 right: 12} - flow: Right spacing: 8 - align: Align{y: 0.5} - check := CheckBox{text: ""} - label := Label{text: "task" draw_text.color: #ddd draw_text.text_style.font_size: 11} - Filler{} - tag := Label{text: "" draw_text.color: #888 draw_text.text_style.font_size: 9} -} - -View{ - flow: Down height: Fit spacing: 4 - TodoItem{label.text: "Walk the dog" tag.text: "personal"} - TodoItem{label.text: "Fix login bug" tag.text: "urgent"} - TodoItem{label.text: "Buy groceries" tag.text: "errands"} -} -``` - -You can override ANY property on an `id :=` child: `label.draw_text.color: #f00`, `icon.visible: false`, `subtitle.draw_text.text_style.font_size: 10`, etc. - -**⛔ Named children inside anonymous containers are UNREACHABLE.** If a `:=` child is nested inside an anonymous `View{}` (no `:=` on the View), the override path cannot find it. The override fails silently and the default text shows instead: - -Every container in the path from root to the child must have a `:=` name. Then use the full dot-path to override: -``` -let Item = View{ - flow: Right - texts := View{ // named with := - flow: Down - label := Label{text: "default"} - } -} -Item{texts.label.text: "new text"} // full path through named containers -``` - -## Syntax Fundamentals - -``` -// Property assignment -key: value - -// Nested object -key: Type{ prop1: val1 prop2: val2 } - -// Merge (extend parent, don't replace) -key +: { prop: val } - -// Dot-path shorthand -draw_bg.color: #f00 -// equivalent to: draw_bg +: { color: #f00 } - -// Named child (:= declares a dynamic/addressable child) -my_button := Button{ text: "Click" } - -// Anonymous child (no name) -Label{ text: "hello" } - -// Let binding (define BEFORE use, local to current scope) -let MyThing = View{ height: Fit width: Fill } - -// Instantiate let binding -MyThing{} - -// Inherit from existing widget type -MyView = RoundedView{ height: Fit draw_bg.color: #f00 } -``` - -## Colors - -``` -#f00 // RGB short -#ff0000 // RGB full -#ff0000ff // RGBA -#0000 // transparent black -vec4(1.0 0.0 0.0 1.0) // explicit RGBA -``` - -## Sizing (Size enum) - -``` -width: Fill // Fill available space (default) -width: Fit // Shrink to content -width: 200 // Fixed 200px (bare number = Fixed) -width: Fill{min: 100 max: 500} -width: Fit{max: Abs(300)} -height: Fill height: Fit height: 100 -``` - -## Layout - -### Flow (direction children are laid out) -``` -flow: Right // default, left-to-right (no wrap) -flow: Down // top-to-bottom -flow: Overlay // stacked on top of each other -flow: Flow.Right{wrap: true} // wrapping horizontal -flow: Flow.Down{wrap: true} // wrapping vertical -``` - -### Spacing/Padding/Margin -``` -spacing: 10 // gap between children -padding: 15 // uniform padding (bare number) -padding: Inset{top: 5 bottom: 5 left: 10 right: 10} -margin: Inset{top: 2 bottom: 2 left: 5 right: 5} -margin: 0. // uniform zero -``` - -### Alignment -``` -align: Center // Align{x:0.5 y:0.5} -align: HCenter // Align{x:0.5 y:0.0} -align: VCenter // Align{x:0.0 y:0.5} -align: TopLeft // Align{x:0.0 y:0.0} -align: Align{x: 1.0 y: 0.0} // top-right -align: Align{x: 0.0 y: 0.5} // center-left -``` - -### Clipping -``` -clip_x: true // default -clip_y: true // default -clip_x: false // overflow visible -``` - -## View Widgets (containers) - -All inherit from `ViewBase`. Default: no background. - -| Widget | Background | Shape | -|--------|-----------|-------| -| `View` | none | - | -| `SolidView` | flat color | rectangle | -| `RoundedView` | color | rounded rect (`border_radius`) | -| `RoundedAllView` | color | per-corner radius (`vec4`) | -| `RoundedXView` | color | left/right radius (`vec2`) | -| `RoundedYView` | color | top/bottom radius (`vec2`) | -| `RectView` | color | rectangle with border | -| `RectShadowView` | color+shadow | rectangle | -| `RoundedShadowView` | color+shadow | rounded rect | -| `CircleView` | color | circle | -| `HexagonView` | color | hexagon | -| `GradientXView` | horizontal gradient | rectangle | -| `GradientYView` | vertical gradient | rectangle | -| `CachedView` | texture-cached | rectangle | -| `CachedRoundedView` | texture-cached | rounded rect | - -### Scrollable Views -``` -ScrollXYView{} // scroll both axes -ScrollXView{} // horizontal scroll -ScrollYView{} // vertical scroll -``` - -### View Properties (all containers) -**⚠️ REMEMBER: Always set `height: Fit` (default is Fill which breaks in chat output!)** -``` -// Layout (inherited by all containers) -width: Fill // Size: Fill | Fit | -height: Fit // ⚠️ USE Fit! Default Fill breaks in Fit containers! -flow: Down // Flow: Right | Down | Overlay | Flow.Right{wrap:true} -spacing: 10 // gap between children -padding: 15 // Inset or bare number -margin: 0. // Inset or bare number -align: Center // Align preset or Align{x: y:} - -// Display -show_bg: true // enable background drawing (false by default) -visible: true -new_batch: true // see "Draw Batching" section below -cursor: MouseCursor.Hand -grab_key_focus: true -block_signal_event: false -capture_overload: false -clip_x: true -clip_y: true - -// Scrollbar (for ScrollXView/ScrollYView/ScrollXYView) -scroll_bars: ScrollBar{} -``` - -### Draw Batching and `new_batch: true` - -In Makepad, widgets that use the same shader are automatically collected into the same GPU draw call for performance. This means if you draw `Label{} SolidView{ Label{} }`, the second Label's text can end up **behind** the SolidView's background — because both Labels are batched into the same text draw call, which executes before the SolidView's background draw call. - -**Set `new_batch: true` on any View that has `show_bg: true` AND contains text children.** This tells the View to start a new draw batch, ensuring its background is drawn before its children's text. - -**⛔ CRITICAL for hover effects:** If a View has `show_bg: true` with a hover animator (background goes from transparent `#0000` to opaque on hover), you MUST set `new_batch: true` on that View. Without it, when the hover activates the background becomes opaque and covers the text — making text disappear on hover. This is the #1 mistake with hoverable list items. - -**When to use `new_batch: true`:** -- **Any View/SolidView/RoundedView with `show_bg: true` that contains Labels or other text** — always add `new_batch: true` -- **Hoverable items** — a View with `show_bg: true` + animator hover that contains text MUST have `new_batch: true` or text vanishes on hover -- **Container of repeated items** that each have their own background — the container itself also needs `new_batch: true` -- When text appears invisible despite having the correct color — this is almost always a batching issue - -``` -// Hoverable item: new_batch ensures text draws on top of hover bg -let HoverItem = View{ - width: Fill height: Fit - new_batch: true - show_bg: true - draw_bg +: { color: uniform(#0000) color_hover: uniform(#fff2) hover: instance(0.0) ... } - animator: Animator{ hover: { ... } } - label := Label{text: "item" draw_text.color: #fff} -} - -// Parent container of repeated items also needs new_batch -RoundedView{ - flow: Down height: Fit new_batch: true - HoverItem{label.text: "Walk the dog"} - HoverItem{label.text: "Do laundry"} -} -``` - -### draw_bg Properties (for SolidView, RoundedView, etc.) -``` -draw_bg +: { - color: instance(#334) // fill color - color_2: instance(vec4(-1)) // gradient end (-1 = disabled) - gradient_fill_horizontal: uniform(0.0) // 0=vertical, 1=horizontal - border_size: uniform(1.0) - border_radius: uniform(5.0) // for RoundedView - border_color: instance(#888) - border_inset: uniform(vec4(0)) - // Shadow views add: - shadow_color: instance(#0007) - shadow_radius: uniform(10.0) - shadow_offset: uniform(vec2(0 0)) -} -``` - -## Text Widgets - -### Label -Properties: `text`, `draw_text` (DrawText), `align`, `flow`, `padding`, `hover_actions_enabled` - -**⚠️ Label does NOT support `animator` or `cursor`.** Adding them has no effect — they are silently ignored. To make hoverable/clickable text, wrap a Label inside a `View` with animator+cursor (see Animator section for example). - -``` -Label{ text: "Hello" } -Label{ - width: Fit height: Fit - draw_text.color: #fff - draw_text.text_style.font_size: 12 - text: "Styled" -} -``` - -**⛔ CRITICAL: Default text color is WHITE.** All text widgets (Label, H1, H2, Button text, etc.) default to white (`#fff`). For light/white themes, you MUST explicitly set `draw_text.color` to a dark color on EVERY text element, or text will be invisible (white-on-white). Example: -For light themes, always set dark text explicitly: -``` -RoundedView{ draw_bg.color: #f5f5f5 height: Fit new_batch: true - Label{text: "Visible!" draw_text.color: #222} -} -``` - -### Label Variants -| Widget | Description | -|--------|-------------| -| `Label` | Default label | -| `Labelbold` | Bold font | -| `LabelGradientX` | Horizontal text gradient | -| `LabelGradientY` | Vertical text gradient | -| `TextBox` | Full-width, long-form text_style | -| `P` | Paragraph (like TextBox) | -| `Pbold` | Bold paragraph | - -### Headings -``` -H1{ text: "Title" } // font_size_1 -H2{ text: "Subtitle" } // font_size_2 -H3{ text: "Section" } // font_size_3 -H4{ text: "Subsection" } // font_size_4 -``` - -### draw_text Properties -``` -draw_text +: { - color: #fff - color_2: uniform(vec4(-1)) // gradient end (-1 = disabled) - color_dither: uniform(1.0) - gradient_fill_horizontal: uniform(0.0) - text_style: theme.font_regular{ font_size: 11 } -} -``` -Available fonts: `theme.font_regular`, `theme.font_bold`, `theme.font_italic`, `theme.font_bold_italic`, `theme.font_code`, `theme.font_icons` - -### TextInput -Properties: `is_password`, `is_read_only`, `is_numeric_only`, `empty_text`, `draw_bg`, `draw_text`, `draw_selection`, `draw_cursor`, `label_align` -``` -TextInput{ width: Fill height: Fit empty_text: "Placeholder" } -TextInputFlat{ width: Fill height: Fit empty_text: "Type here" } -TextInput{ is_password: true empty_text: "Password" } -TextInput{ is_read_only: true } -TextInput{ is_numeric_only: true } -``` - -### LinkLabel -Properties: same as Button (text, draw_text, draw_bg, icon_walk, label_walk) -``` -LinkLabel{ text: "Click me" } -``` - -### TextFlow (rich text container, used by Markdown/Html) -``` -TextFlow{ - width: Fill height: Fit - selectable: true - font_size: 10 -} -``` - -### Markdown / Html (feature-gated) -``` -Markdown{ - width: Fill height: Fit - selectable: true - body: "# Title\n\nParagraph with **bold**" -} -Html{ - width: Fill height: Fit - body: "

Title

Content

" -} -``` - -## Button Widgets - -Properties: `text`, `draw_bg` (DrawQuad), `draw_text` (DrawText), `draw_icon` (DrawSvg), `icon_walk`, `label_walk`, `grab_key_focus`, `animator` - -``` -Button{ text: "Standard" } -ButtonFlat{ text: "Flat" } // no bevel border -ButtonFlatter{ text: "Minimal" } // invisible bg - -// With icon -Button{ - text: "Save" - icon_walk: Walk{width: 16 height: 16} - draw_icon.color: #fff - draw_icon.svg: crate_resource("self://path/to/icon.svg") -} - -// Customize colors -ButtonFlat{ - text: "Custom" - draw_bg +: { - color: uniform(#336) - color_hover: uniform(#449) - color_down: uniform(#225) - } - draw_text +: { - color: #fff - } -} -``` - -### Button draw_bg Instance Variables -These are per-instance floats driven by the animator: -`hover`, `down`, `focus`, `disabled` - -Color uniforms (each with `_hover`, `_down`, `_focus`, `_disabled` variants): -`color`, `color_2`, `border_color`, `border_color_2` - -Other: `border_size`, `border_radius`, `color_dither`, `gradient_fill_horizontal`, `gradient_border_horizontal` - -## Toggle Widgets - -CheckBox/Toggle share a base. Properties: `text`, `draw_bg`, `draw_text`, `draw_icon`, `icon_walk`, `label_walk`, `label_align`, `animator` - -``` -CheckBox{ text: "Enable" } -CheckBoxFlat{ text: "Flat style" } -Toggle{ text: "Dark mode" } -ToggleFlat{ text: "Flat toggle" } -CheckBoxCustom{ text: "Custom" } -``` - -### CheckBox draw_bg Instance Variables -Animator-driven: `hover`, `down`, `focus`, `active`, `disabled` -Uniforms: `size`, `border_size`, `border_radius` -Color uniforms (each with `_hover`, `_down`, `_active`, `_focus`, `_disabled`): `color`, `border_color`, `mark_color` -Also: `mark_size` - -### RadioButton -Properties: same as CheckBox -``` -RadioButton{ text: "Option A" } -RadioButtonFlat{ text: "Option A" } -``` - -## Input Widgets - -### Slider -Properties: `text`, `min`, `max`, `step`, `default`, `precision`, `axis` (DragAxis), `label_walk`, `label_align`, `draw_bg`, `draw_text`, `bind` -``` -Slider{ width: Fill text: "Volume" min: 0.0 max: 100.0 default: 50.0 } -SliderMinimal{ text: "Value" min: 0.0 max: 1.0 step: 0.01 precision: 2 } -``` - -### DropDown -Properties: `labels` (string array), `draw_bg`, `draw_text`, `popup_menu`, `bind`, `bind_enum` -``` -DropDown{ labels: ["Option A" "Option B" "Option C"] } -DropDownFlat{ labels: ["Small" "Medium" "Large"] } -``` - -## Media - -### Image -Properties: `draw_bg` (DrawImage), `fit` (ImageFit), `min_width`, `min_height`, `width_scale`, `animation` (ImageAnimation) -``` -Image{ width: 200 height: 150 fit: ImageFit.Stretch } -// ImageFit: Stretch | Horizontal | Vertical | Smallest | Biggest | Size -// ImageAnimation: Stop | Once | Loop | Bounce | OnceFps(60) | LoopFps(25) | BounceFps(25) -``` - -### DrawImage Properties -``` -draw_bg +: { - opacity: 1.0 - image_scale: vec2(1.0 1.0) - image_pan: vec2(0.0 0.0) - image_texture: texture_2d(float) -} -``` - -### Icon -Properties: `draw_bg`, `draw_icon` (DrawSvg), `icon_walk` -``` -Icon{ - draw_icon.svg: crate_resource("self://resources/icons/my_icon.svg") - draw_icon.color: #0ff - icon_walk: Walk{width: 32 height: 32} -} -``` - -### LoadingSpinner -A View with animated arc shader. Properties: `color`, `rotation_speed`, `border_size`, `stroke_width`, `max_gap_ratio`, `min_gap_ratio` -``` -LoadingSpinner{ width: 40 height: 40 } -``` - -## Layout Widgets - -### Hr / Vr (dividers) -``` -Hr{} // horizontal rule -Vr{} // vertical rule -``` - -### Filler (spacer) -``` -Filler{} // View{width: Fill height: Fill} - pushes siblings apart -``` - -**⛔ Do NOT use `Filler{}` next to a `width: Fill` sibling in `flow: Right`.** Both compete for remaining space and split it 50/50, causing text to be clipped halfway. Instead, give the content element `width: Fill` — it naturally pushes `width: Fit` siblings to the edge. Only use `Filler{}` between `width: Fit` siblings: -``` -// Filler between Fit siblings — correct use -View{ flow: Right - Label{text: "left"} - Filler{} - Label{text: "right"} -} - -// width: Fill takes remaining space, pushes Fit siblings right — no Filler needed -View{ flow: Right - texts := View{ width: Fill height: Fit flow: Down - label := Label{text: "title"} - sub := Label{text: "subtitle"} - } - tag := Label{text: "tag"} -} -``` - -### Splitter -Properties: `axis` (SplitterAxis), `align` (SplitterAlign), `a`, `b`, `size`, `min_horizontal`, `max_horizontal`, `min_vertical`, `max_vertical`, `draw_bg` -``` -Splitter{ - axis: SplitterAxis.Horizontal // Horizontal | Vertical - align: SplitterAlign.FromA(250.0) // FromA(px) | FromB(px) | Weighted(0.5) - a := left_panel - b := right_panel -} -``` -Note: `a` and `b` reference named children — use `a := left_panel` (the `:=` operator) to bind them. - -### FoldHeader (collapsible section) -Properties: `body_walk`, `animator` (with `active` group: `on`/`off` states controlling `opened` float) -``` -FoldHeader{ - header: View{ height: Fit - flow: Right align: Align{y: 0.5} spacing: 8 - FoldButton{} - Label{text: "Section Title"} - } - body: View{ height: Fit - flow: Down padding: Inset{left: 23} spacing: 8 - // content - } -} -``` - -## List Widgets - -### PortalList (virtualized list) -Properties: `flow`, `scroll_bar`, `capture_overload`, `selectable`, `drag_scrolling`, `auto_tail` -Define templates with `:=` declarations. Templates are instantiated by host code at draw time. -``` -list := PortalList{ - width: Fill height: Fill - flow: Down - scroll_bar: ScrollBar{} - Item := View{ - width: Fill height: Fit - title := Label{text: ""} - } - Header := View{ height: Fit ... } -} -``` - -### FlatList (non-virtualized) -``` -FlatList{ - width: Fill height: Fill - flow: Down - Item := View{ height: Fit ... } -} -``` - -### ScrollBar -Properties: `bar_size`, `bar_side_margin`, `min_handle_size`, `draw_bg` -``` -ScrollBar{ - bar_size: 10.0 - bar_side_margin: 3.0 - min_handle_size: 30.0 -} -``` - -## Dock System - -The Dock is a tabbed panel layout with splitters, tabs, and content templates. Three sections: -1. **`tab_bar +:`** — define tab header templates (appearance of tab buttons) -2. **`root :=`** — the layout tree of DockSplitter/DockTabs -3. **Content templates** — `Name := Widget{}` defines content instantiated by tabs - -### Dock Properties -`tab_bar` (TabBar widget for tab headers), `splitter` (Splitter widget), `round_corner`, `drag_target_preview`, `padding` - -### DockSplitter -`axis` (SplitterAxis), `align` (SplitterAlign), `a` (LiveId ref), `b` (LiveId ref) - -### DockTabs -`tabs` (array of tab refs), `selected` (index), `closable` - -### DockTab -`name` (string), `template` (ref to tab_bar template), `kind` (ref to content template) - -### Complete Dock Example (from Makepad Studio) -``` -Dock{ - width: Fill height: Fill - - // 1. Tab header templates (how tab buttons look) - tab_bar +: { - FilesTab := IconTab{ - draw_icon +: { - color: #80FFBF - svg: crate_resource("self://resources/icons/icon_file.svg") - } - } - EditTab := IconTab{ - draw_icon +: { - color: #FFB368 - svg: crate_resource("self://resources/icons/icon_editor.svg") - } - } - LogTab := IconTab{ - draw_icon +: { - color: #80FFBF - svg: crate_resource("self://resources/icons/icon_log.svg") - } - } - } - - // 2. Layout tree - root := DockSplitter{ - axis: SplitterAxis.Horizontal - align: SplitterAlign.FromA(250.0) - a := left_tabs - b := right_split - } - - right_split := DockSplitter{ - axis: SplitterAxis.Vertical - align: SplitterAlign.FromB(200.0) - a := center_tabs - b := bottom_tabs - } - - left_tabs := DockTabs{ - tabs: [@files_tab] - selected: 0 - } - - center_tabs := DockTabs{ - tabs: [@edit_tab] - selected: 0 - } - - bottom_tabs := DockTabs{ - tabs: [@log_tab] - selected: 0 - } - - // 3. Tab definitions (connect header template to content template) - files_tab := DockTab{ - name: "Files" - template := FilesTab // references tab_bar template - kind := FileTreeContent // references content template - } - - edit_tab := DockTab{ - name: "Editor" - template := EditTab - kind := EditorContent - } - - log_tab := DockTab{ - name: "Log" - template := LogTab - kind := LogContent - } - - // 4. Content templates (instantiated when tab is shown) - FileTreeContent := View{ - flow: Down - width: Fill height: Fill - Label{text: "File tree here"} - } - - EditorContent := View{ - flow: Down - width: Fill height: Fill - Label{text: "Editor here"} - } - - LogContent := View{ - flow: Down - width: Fill height: Fill - Label{text: "Log here"} - } -} -``` - -Dock variants: `Dock` (rounded corners), `DockFlat` (flat style) - -## Navigation - -### Modal -Properties: inherits View (flow: Overlay, align: Center). Contains `bg_view` (backdrop) and `content` (dialog body), both declared with `:=`. -``` -my_modal := Modal{ - content +: { - width: 300 height: Fit - RoundedView{ height: Fit - padding: 20 flow: Down spacing: 10 - draw_bg.color: #333 - Label{text: "Dialog Title"} - close := ButtonFlat{text: "Close"} - } - } -} -``` - -### Tooltip -``` -tooltip := Tooltip{} -``` - -### PopupNotification -``` -popup := PopupNotification{ - align: Align{x: 1.0 y: 0.0} - content +: { ... } -} -``` - -### SlidePanel -Properties: `side` (SlideSide), inherits View. Animated `active` float. -``` -panel := SlidePanel{ - side: SlideSide.Left // Left | Right | Top - width: 200 - height: Fill - // child content -} -``` - -### ExpandablePanel -Properties: `initial_offset`, inherits View (flow: Overlay). First child = background, `panel` (declared with `:=`) = draggable overlay. -``` -ExpandablePanel{ - width: Fill height: Fill - initial_offset: 100.0 - View{ height: Fit ... } // background - panel := View{ height: Fit ... } // draggable panel -} -``` - -### PageFlip -Properties: `active_page` (LiveId), `lazy_init`. Children are page templates declared with `:=`. -``` -PageFlip{ - active_page := page1 - page1 := View{ height: Fit ... } - page2 := View{ height: Fit ... } -} -``` - -### StackNavigation -``` -StackNavigation{ - root_view := View{ height: Fit ... } - // StackNavigationViews added as children -} -``` - -### SlidesView -``` -SlidesView{ - slide1 := Slide{ - title := H1{text: "Title"} - SlideBody{text: "Content"} - } - slide2 := SlideChapter{ - title := H1{text: "Chapter"} - } -} -``` - -### FileTree -``` -FileTree{} -// Driven programmatically: begin_folder/end_folder/file -``` - -## Shader System - -### Instance vs Uniform -``` -draw_bg +: { - hover: instance(0.0) // per-draw-call, animatable by Animator - color: uniform(#fff) // shared across all instances of this shader variant - tex: texture_2d(float) // texture sampler - my_var: varying(vec2(0)) // vertex→pixel interpolated (set in vertex shader) -} -``` -**When to use each:** -- `instance()` — state that varies per widget (hover, down, focus, active, disabled), per-widget colors, scale/pan. Driven by the Animator system. -- `uniform()` — theme constants shared by all instances (border_size, border_radius, theme colors). Cannot be animated. - -### Pixel Shader -``` -draw_bg +: { - pixel: fn() { - let sdf = Sdf2d.viewport(self.pos * self.rect_size) - sdf.box(0. 0. self.rect_size.x self.rect_size.y 4.0) - sdf.fill(#f00) - return sdf.result // already premultiplied by sdf.fill(), no Pal.premul() needed - } -} -``` - -**⛔ CRITICAL: Premultiply colors returned from pixel()!** When you hand-code a `pixel: fn()` that returns a color (not via `sdf.result`), you MUST premultiply the alpha. Without this, colors with alpha (e.g. `#ffffff08`) will render as bright white instead of a subtle tint. Always wrap your return value in `Pal.premul()`: -``` -pixel: fn(){ - return Pal.premul(self.color.mix(self.color_hover, self.hover)) -} -``` -Note: `sdf.fill()` / `sdf.stroke()` already premultiply internally, so `return sdf.result` is safe without extra `Pal.premul()`. - -**Common pattern — fill + border stroke:** -``` -pixel: fn() { - let sdf = Sdf2d.viewport(self.pos * self.rect_size) - sdf.box(1. 1. self.rect_size.x - 2. self.rect_size.y - 2. 4.0) - sdf.fill_keep(self.color) // fill the shape, keep it for stroke - sdf.stroke(self.border_color, 1.0) // stroke the same shape's outline - return sdf.result -} -``` - -### SDF Primitives -``` -sdf.circle(cx cy radius) -sdf.rect(x y w h) -sdf.box(x y w h border_radius) -sdf.box_all(x y w h r_lt r_rt r_rb r_lb) // per-corner radius -sdf.box_x(x y w h r_left r_right) -sdf.box_y(x y w h r_top r_bottom) -sdf.hexagon(cx cy radius) -sdf.hline(y half_height) -sdf.arc_round_caps(cx cy radius start_angle end_angle thickness) -sdf.arc_flat_caps(cx cy radius start_angle end_angle thickness) -``` - -### SDF Path Operations -``` -sdf.move_to(x y) -sdf.line_to(x y) -sdf.close_path() -``` - -### SDF Combinators - -These operate on the **current** shape and the **previous** shape. Draw two primitives, then combine: -``` -sdf.union() // merge shapes together (min of distances) -sdf.intersect() // keep only overlap (max of distances) -sdf.subtract() // cut current shape from previous shape -sdf.gloop(k) // smooth/gooey union with rounding factor k -sdf.blend(k) // linear blend: 0.0 = previous shape, 1.0 = current shape -``` -Example — ring (circle with hole): -``` -sdf.circle(cx cy outer_radius) -sdf.circle(cx cy inner_radius) -sdf.subtract() -sdf.fill(#fff) -``` -Example — blend for toggle animation: -``` -sdf.circle(x y r) // ring shape (from subtract above) -sdf.circle(x y r) // solid circle -sdf.blend(self.active) // animate between ring (0) and solid (1) -``` - -### SDF Drawing -``` -sdf.fill(color) // fill and reset shape -sdf.fill_keep(color) // fill, keep shape for subsequent stroke -sdf.stroke(color width) // stroke and reset shape -sdf.stroke_keep(color w) // stroke, keep shape -sdf.glow(color width) // additive glow around shape, reset -sdf.glow_keep(color w) // additive glow, keep shape -sdf.clear(color) // clear result buffer with color -``` - -### SDF Transforms -``` -sdf.translate(x y) -sdf.rotate(angle cx cy) -sdf.scale(factor cx cy) -``` - -### Built-in Shader Variables -``` -self.pos // vec2: normalized position [0,1] (computed from clipping in vertex shader) -self.rect_size // vec2: pixel size of the drawn rect -self.rect_pos // vec2: pixel position of the drawn rect -self.dpi_factor // float: display DPI factor for high-DPI screens -self.draw_pass.time // float: elapsed time in seconds (for continuous animation) -self.draw_pass.dpi_dilate // float: DPI dilation factor for pixel-perfect strokes -self.draw_depth // float: base depth for z-ordering -self.draw_zbias // float: z-bias offset added to depth -self.geom_pos // vec2: raw geometry position [0,1] (before clipping) -``` - -### Vertex Shader - -Most widgets use the default vertex shader from DrawQuad. You can override it for custom geometry expansion (e.g., shadows) or DPI-aware texture coordinates: -``` -draw_bg +: { - // custom varying to pass data from vertex to pixel shader - my_scale: varying(vec2(0)) - - vertex: fn() { - let dpi = self.dpi_factor - let ceil_size = ceil(self.rect_size * dpi) / dpi - self.my_scale = self.rect_size / ceil_size - return self.clip_and_transform_vertex(self.rect_pos self.rect_size) - } - pixel: fn() { - // my_scale is available here, interpolated from vertex - return Pal.premul(self.color) - } -} -``` -`self.clip_and_transform_vertex(rect_pos rect_size)` is the standard helper that handles clipping, view shift (scrolling), and camera projection. Always call it in custom vertex shaders. - -### Custom Shader Functions - -You can define named functions on a draw shader for reuse: -``` -draw_bg +: { - get_color: fn() { - return self.color - .mix(self.color_hover, self.hover) - .mix(self.color_down, self.down) - } - pixel: fn() { - return Pal.premul(self.get_color()) - } -} -``` -Functions with parameters: -``` -draw_bg +: { - get_color_at: fn(scale: vec2, pan: vec2) { - return self.my_texture.sample(self.pos * scale + pan) - } -} -``` - -### Mutable Variables - -Use `let mut` to declare mutable variables in shader code: -``` -pixel: fn() { - let mut color = self.color - if self.hover > 0.5 { - color = self.color_hover - } - return Pal.premul(color) -} -``` - -### Conditionals and Match - -Shaders support `if`/`else` and `match` on enum instance variables: -``` -pixel: fn() { - let sdf = Sdf2d.viewport(self.pos * self.rect_size) - if self.is_vertical > 0.5 { - sdf.box(1. self.rect_size.y * self.scroll_pos 8. self.rect_size.y * self.handle_size 2.) - } else { - sdf.box(self.rect_size.x * self.scroll_pos 1. self.rect_size.x * self.handle_size 8. 2.) - } - sdf.fill(self.color) - return sdf.result -} -``` - -### Texture Sampling - -Declare texture samplers and sample them in pixel shaders: -``` -draw_bg +: { - my_tex: texture_2d(float) - pixel: fn() { - let color = self.my_tex.sample(self.pos) // standard 2D sampling - return Pal.premul(color) - } -} -``` -Alternative sampling functions: -``` -sample2d(self.my_tex, uv) // free-function form of texture sampling -sample2d_rt(self.image, uv) // sample from render-target texture (handles Y-flip on some platforms) -``` - -### Color Operations -``` -mix(color1 color2 factor) // linear interpolation (free function) -color1.mix(color2 factor) // method chaining form -#f00.mix(#0f0 0.5).mix(#00f hover) // multi-chain for state interpolation -Pal.premul(color) // premultiply alpha — REQUIRED when returning from pixel()! -Pal.hsv2rgb(vec4(h s v 1.0)) // HSV to RGB conversion -Pal.rgb2hsv(color) // RGB to HSV conversion -Pal.iq(t a b c d) // Inigo Quilez cosine color palette -Pal.iq0(t) .. Pal.iq7(t) // pre-built cosine color palettes -``` -⚠️ Always wrap your final color in `Pal.premul()` when returning from `pixel: fn()` (unless returning `sdf.result` which is already premultiplied). - -**Gradient pattern** — use `vec4(-1.0, -1.0, -1.0, -1.0)` as a sentinel for "no gradient", then check with `if self.color_2.x > -0.5`: -``` -color_2: uniform(vec4(-1.0, -1.0, -1.0, -1.0)) // sentinel: no gradient -pixel: fn() { - let mut fill = self.color - if self.color_2.x > -0.5 { - let dither = Math.random_2d(self.pos.xy) * 0.04 - let dir = self.pos.y + dither - fill = mix(self.color, self.color_2, dir) - } - return Pal.premul(fill) -} -``` - -### SDF Anti-aliasing - -The `sdf.aa` field controls anti-aliasing sharpness. Default is computed from viewport. Set higher for sharper edges: -``` -pixel: fn() { - let sdf = Sdf2d.viewport(self.pos * self.rect_size) - sdf.aa = sdf.aa * 3.0 // sharper edges (useful for small icons) - sdf.move_to(c.x - sz, c.y - sz) - sdf.line_to(c.x + sz, c.y + sz) - sdf.stroke(#fff, 0.5 + 0.5 * self.draw_pass.dpi_dilate) - return sdf.result -} -``` - -### SDF fill_premul / fill_keep_premul - -When filling with a color that is already premultiplied (e.g., from a texture sample or render target): -``` -sdf.fill_premul(color) // fill with premultiplied color, reset shape -sdf.fill_keep_premul(color) // fill with premultiplied color, keep shape -``` - -### GaussShadow (box shadows) -``` -GaussShadow.box_shadow(lower upper point sigma) // fast rectangular shadow -GaussShadow.rounded_box_shadow(lower upper point sigma corner) // rounded rectangle shadow -``` -Used in shadow view variants (`RectShadowView`, `RoundedShadowView`) to render drop shadows efficiently. - -### Math Utilities -``` -// Custom Makepad functions -Math.random_2d(vec2) // pseudo-random 0-1 from vec2 seed (for dithering) -Math.rotate_2d(v angle) // 2D rotation of vector by angle - -// Constants -PI // 3.14159... -E // 2.71828... -TORAD // degrees→radians multiplier (0.01745...) -GOLDEN // golden ratio (1.61803...) - -// Standard GLSL math (all work on float, vec2, vec3, vec4) -sin(x) cos(x) tan(x) asin(x) acos(x) atan(y x) -pow(x y) sqrt(x) exp(x) exp2(x) log(x) log2(x) -abs(x) sign(x) floor(x) ceil(x) fract(x) mod(x y) -min(x y) max(x y) clamp(x min max) -step(edge x) smoothstep(edge0 edge1 x) - -// Vector operations -length(v) distance(a b) dot(a b) cross(a b) normalize(v) - -// Fragment-only (for advanced anti-aliasing) -dFdx(v) dFdy(v) // partial derivatives (used in text SDF rendering) -``` - -## Animator - -The animator drives `instance()` variables on draw shaders over time, enabling hover effects, transitions, and looping animations. - -### ⛔ CRITICAL: Only Certain Widgets Support Animator ⛔ - -**NOT all widgets have an `animator` field.** If you add `animator: Animator{...}` to a widget that doesn't support it, the definition is **silently ignored** — no error, no hover, nothing happens. - -**Widgets that SUPPORT animator:** `View`, `SolidView`, `RoundedView`, `ScrollXView`, `ScrollYView`, `ScrollXYView`, `Button`, `ButtonFlat`, `ButtonFlatter`, `CheckBox`, `Toggle`, `RadioButton`, `LinkLabel`, `TextInput` - -**Widgets that DO NOT support animator:** `Label`, `H1`–`H4`, `P`, `TextBox`, `Image`, `Icon`, `Markdown`, `Html`, `Slider`, `DropDown`, `Splitter`, `Hr`, `Filler` - -**To make a Label hoverable, wrap it in a View:** -``` -View{ - width: Fill height: Fit - cursor: MouseCursor.Hand - show_bg: true - draw_bg +: { - color: uniform(#0000) - color_hover: uniform(#fff2) - hover: instance(0.0) - pixel: fn(){ - return Pal.premul(self.color.mix(self.color_hover, self.hover)) - } - } - animator: Animator{ - hover: { - default: @off - off: AnimatorState{ - from: {all: Forward {duration: 0.15}} - apply: {draw_bg: {hover: 0.0}} - } - on: AnimatorState{ - from: {all: Forward {duration: 0.15}} - apply: {draw_bg: {hover: 1.0}} - } - } - } - Label{text: "hoverable item" draw_text.color: #fff} -} -``` - -### Structure - -``` -animator: Animator{ - : { - default: @ // initial state (@ prefix required) - : AnimatorState{ - from: { ... } // transition timing - ease: // optional ease override - redraw: true // optional: force redraw each frame - apply: { ... } // target values - } - : AnimatorState{ ... } - } - : { ... } // multiple groups allowed -} -``` - -### Groups -Each group is an independent animation track (e.g. `hover`, `focus`, `active`, `disabled`, `time`). Multiple groups animate simultaneously without interfering. - -### The `from` Block -Controls when/how the transition plays. Keys are state names being transitioned FROM, or `all` as catch-all: -``` -from: {all: Forward {duration: 0.2}} // from any state -from: {all: Snap} // instant from any state -from: { - all: Forward {duration: 0.1} // default - down: Forward {duration: 0.01} // faster when coming from "down" -} -``` - -### The `apply` Block -Target values to animate TO. The structure mirrors the widget's property tree. Keys are the widget's sub-objects (like `draw_bg`, `draw_text`), values are the shader instance variables to animate: - -``` -apply: { - draw_bg: {hover: 1.0} // animate draw_bg.hover to 1.0 - draw_text: {hover: 1.0} // animate draw_text.hover to 1.0 -} -``` - -Multiple properties in one block: -``` -apply: { - draw_bg: {down: 1.0, hover: 0.5} - draw_text: {down: 1.0, hover: 0.5} -} -``` - -For non-draw properties (e.g. a float field on the widget itself): -``` -apply: { - opened: 1.0 // animate widget's own "opened" field - active: 0.0 // animate widget's own "active" field -} -``` - -### snap() — Instant Jump -Wrapping a value in `snap()` makes it jump instantly instead of interpolating: -``` -apply: { - draw_bg: {down: snap(1.0), hover: 1.0} // down jumps, hover interpolates -} -``` - -### timeline() — Keyframes -Animate through multiple values over the duration using time/value pairs (times 0.0–1.0): -``` -apply: { - draw_bg: {anim_time: timeline(0.0 0.0 1.0 1.0)} // linear 0→1 -} -``` - -### Complete Button Animator Example -``` -animator: Animator{ - disabled: { - default: @off - off: AnimatorState{ - from: {all: Forward {duration: 0.}} - apply: { - draw_bg: {disabled: 0.0} - draw_text: {disabled: 0.0} - } - } - on: AnimatorState{ - from: {all: Forward {duration: 0.2}} - apply: { - draw_bg: {disabled: 1.0} - draw_text: {disabled: 1.0} - } - } - } - hover: { - default: @off - off: AnimatorState{ - from: {all: Forward {duration: 0.1}} - apply: { - draw_bg: {down: 0.0, hover: 0.0} - draw_text: {down: 0.0, hover: 0.0} - } - } - on: AnimatorState{ - from: { - all: Forward {duration: 0.1} - down: Forward {duration: 0.01} - } - apply: { - draw_bg: {down: 0.0, hover: snap(1.0)} - draw_text: {down: 0.0, hover: snap(1.0)} - } - } - down: AnimatorState{ - from: {all: Forward {duration: 0.2}} - apply: { - draw_bg: {down: snap(1.0), hover: 1.0} - draw_text: {down: snap(1.0), hover: 1.0} - } - } - } - focus: { - default: @off - off: AnimatorState{ - from: {all: Snap} - apply: { - draw_bg: {focus: 0.0} - draw_text: {focus: 0.0} - } - } - on: AnimatorState{ - from: {all: Snap} - apply: { - draw_bg: {focus: 1.0} - draw_text: {focus: 1.0} - } - } - } - time: { - default: @off - off: AnimatorState{ - from: {all: Forward {duration: 0.}} - apply: {} - } - on: AnimatorState{ - from: {all: Loop {duration: 1.0, end: 1000000000.0}} - apply: { - draw_bg: {anim_time: timeline(0.0 0.0 1.0 1.0)} - } - } - } -} -``` - -### Play Types (transition modes) -``` -Forward {duration: 0.2} // play once forward -Snap // instant (no interpolation) -Reverse {duration: 0.2, end: 1.0} // play in reverse -Loop {duration: 1.0, end: 1000000000.0} // repeat forward -ReverseLoop {duration: 1.0, end: 1.0} // repeat in reverse -BounceLoop {duration: 1.0, end: 1.0} // bounce back and forth -``` - -### Ease Functions -``` -Linear // default -InQuad OutQuad InOutQuad -InCubic OutCubic InOutCubic -InQuart OutQuart InOutQuart -InQuint OutQuint InOutQuint -InSine OutSine InOutSine -InExp OutExp InOutExp -InCirc OutCirc InOutCirc -InElastic OutElastic InOutElastic -InBack OutBack InOutBack -InBounce OutBounce InOutBounce -ExpDecay {d1: 0.82, d2: 0.97, max: 100} -Pow {begin: 0.0, end: 1.0} -Bezier {cp0: 0.0, cp1: 0.0, cp2: 1.0, cp3: 1.0} -``` - -## Theme Variables (prefix: `theme.`) - -### Spacing -`space_1` `space_2` `space_3` - -### Inset Presets -`mspace_1` `mspace_2` `mspace_3` (uniform) -`mspace_h_1` `mspace_h_2` `mspace_h_3` (horizontal only) -`mspace_v_1` `mspace_v_2` `mspace_v_3` (vertical only) - -### Dimensions -`corner_radius` `beveling` `tab_height` `splitter_size` `container_corner_radius` `dock_border_size` - -### Colors (key ones) -`color_bg_app` `color_fg_app` `color_bg_container` `color_bg_even` `color_bg_odd` -`color_text` `color_text_hl` `color_text_disabled` -`color_label_inner` `color_label_outer` (+ `_hover` `_down` `_focus` `_active` `_disabled`) -`color_inset` (+ variants) `color_outset` (+ variants) -`color_bevel` (+ variants) -`color_shadow` `color_highlight` `color_makepad` (#FF5C39) -`color_white` `color_black` -`color_error` `color_warning` `color_panic` -`color_selection_focus` `color_cursor` -`color_u_1`..`color_u_6` (light scale) `color_d_1`..`color_d_5` (dark scale) -`color_u_hidden` `color_d_hidden` (transparent) -`color_drag_target_preview` -`color_val` `color_handle` (+ `_hover` `_focus` `_drag` `_disabled`) — slider colors -`color_mark_off` `color_mark_active` (+ variants) — check/radio marks -`color_app_caption_bar` - -### Typography -`font_size_1`..`font_size_4` `font_size_p` `font_size_code` `font_size_base` -`font_regular` `font_bold` `font_italic` `font_bold_italic` `font_code` `font_icons` -`font_wdgt_line_spacing` `font_longform_line_spacing` - -## Enums Reference - -### MouseCursor -`Default` `Hand` `Arrow` `Text` `Move` `Wait` `Help` `NotAllowed` `Crosshair` `Grab` `Grabbing` `NResize` `EResize` `SResize` `WResize` `NsResize` `EwResize` `ColResize` `RowResize` `Hidden` -Usage: `cursor: MouseCursor.Hand` - -### ImageFit -`Stretch` `Horizontal` `Vertical` `Smallest` `Biggest` `Size` - -### SplitterAxis -`Horizontal` `Vertical` - -### SplitterAlign -`FromA(250.0)` `FromB(200.0)` `Weighted(0.5)` - -### SlideSide -`Left` `Right` `Top` - -### DragAxis (for Slider) -`Horizontal` `Vertical` - -### ImageAnimation -`Stop` `Once` `Loop` `Bounce` `Frame(0.0)` `Factor(0.0)` `OnceFps(60.0)` `LoopFps(60.0)` `BounceFps(60.0)` - -## Common Patterns - -**REMINDER: Every container below uses `height: Fit` — you must too!** - -### Colored card -``` -RoundedView{ - width: Fill height: Fit - padding: 15 flow: Down spacing: 8 - draw_bg.color: #445 - draw_bg.border_radius: 8.0 - Label{text: "Card Title" draw_text.color: #fff} -} -``` - -### Sidebar + content -``` -View{ - width: Fill height: Fill - flow: Right - SolidView{ - width: 250 height: Fill - draw_bg.color: #222 - flow: Down padding: 10 - } - View{ - width: Fill height: Fill - flow: Down padding: 15 - } -} -``` - -### Sidebar + content using Splitter -``` -Splitter{ - axis: SplitterAxis.Horizontal - align: SplitterAlign.FromA(250.0) - a := sidebar - b := main -} -sidebar := View{ width: Fill height: Fill flow: Down padding: 10 } -main := View{ width: Fill height: Fill flow: Down padding: 15 } -``` - -### Overlay (modal/tooltip pattern) -``` -View{ height: Fit - flow: Overlay - View{ height: Fit width: Fill ... } // base content - View{ height: Fit align: Center ... } // overlay on top -} -``` - -### Scrollable list -``` -ScrollYView{ - width: Fill height: Fill - flow: Down padding: 10 spacing: 8 - Label{text: "Item 1"} - Label{text: "Item 2"} -} -``` - -### Custom shader widget -Note: `View{ show_bg: true }` is OK here because we provide a complete custom `pixel` shader that overrides the ugly default. -``` -View{ - width: 200 height: 200 - show_bg: true - draw_bg +: { - pixel: fn(){ - let sdf = Sdf2d.viewport(self.pos * self.rect_size) - sdf.circle( - self.rect_size.x * 0.5 - self.rect_size.y * 0.5 - min(self.rect_size.x self.rect_size.y) * 0.4 - ) - sdf.fill(#f80) - return sdf.result // already premultiplied by sdf.fill(), no Pal.premul() needed - } - } -} -``` - -### Hoverable list item -Label does NOT support animator. Wrap it in a View to get hover effects. Use `label :=` to declare the inner Label so each instance can override its text via `label.text:`: -``` -let HoverItem = View{ - width: Fill height: Fit - padding: 8 - cursor: MouseCursor.Hand - new_batch: true - show_bg: true - draw_bg +: { - color: uniform(#0000) - color_hover: uniform(#fff2) - hover: instance(0.0) - pixel: fn(){ - return self.color.mix(self.color_hover, self.hover) - } - } - animator: Animator{ - hover: { - default: @off - off: AnimatorState{ - from: {all: Forward {duration: 0.15}} - apply: {draw_bg: {hover: 0.0}} - } - on: AnimatorState{ - from: {all: Forward {duration: 0.15}} - apply: {draw_bg: {hover: 1.0}} - } - } - } - label := Label{text: "item" draw_text.color: #fff} -} - -RoundedView{ - width: 300 height: Fit - padding: 10 flow: Down spacing: 4 - new_batch: true - draw_bg.color: #222 - draw_bg.border_radius: 5.0 - Label{text: "Todo Items" draw_text.color: #fff} - HoverItem{label.text: "Walk the dog"} - HoverItem{label.text: "Do laundry"} - HoverItem{label.text: "Buy groceries"} -} -``` - -### Toolbar pattern -``` -RectShadowView{ - width: Fill height: 38. - flow: Down padding: theme.mspace_2 - draw_bg +: { - shadow_color: theme.color_shadow - shadow_radius: 7.5 - color: theme.color_fg_app - } - content := View{ - height: Fit width: Fill - flow: Right spacing: theme.space_2 - align: Align{x: 0. y: 0.5} - ButtonFlatter{text: "File"} - ButtonFlatter{text: "Edit"} - Filler{} - ButtonFlat{text: "Run"} - } -} -``` - -## HTTP Requests (`net.http_request`) - -Make async HTTP requests from script. Responses arrive via callbacks. - -### GET request -``` -let req = net.HttpRequest{ - url: "https://html.duckduckgo.com/html/?q=rust+programming" - method: net.HttpMethod.GET - headers: {"User-Agent": "MakepadApp/1.0"} -} -net.http_request(req) do net.HttpEvents{ - on_response: |res| { - let text = res.body.to_string() // body as string - let json = res.body.parse_json() // or parse as JSON - // res.status_code // HTTP status (200, 404, etc.) - } - on_error: |e| { - // e.message // error description - } -} -``` - -### POST request with JSON body -``` -let req = net.HttpRequest{ - url: "https://api.example.com/data" - method: net.HttpMethod.POST - headers: {"Content-Type": "application/json"} - body: {key: "value" count: 42}.to_json() -} -net.http_request(req) do net.HttpEvents{ - on_response: |res| { /* ... */ } - on_error: |e| { /* ... */ } -} -``` - -### Streaming response -``` -let req = net.HttpRequest{ - url: "https://api.example.com/stream" - method: net.HttpMethod.POST - is_streaming: true - body: {stream: true}.to_json() -} -var total = "" -net.http_request(req) do net.HttpEvents{ - on_stream: |res| { - total += res.body.to_string() // called per chunk - } - on_complete: |res| { - // stream finished, total has all data - } - on_error: |e| { /* ... */ } -} -``` - -### HttpMethod values -`net.HttpMethod.GET`, `POST`, `PUT`, `DELETE`, `HEAD`, `PATCH`, `OPTIONS` - -### Cookie-free search endpoints -DuckDuckGo provides HTML endpoints that return static HTML — no cookies, no JS, no API key: -- `https://html.duckduckgo.com/html/?q=QUERY` — div-based, CSS classes for results -- `https://lite.duckduckgo.com/lite/?q=QUERY` — table-based, ~10kB compressed - -Both require a `User-Agent` header. Results can be parsed with `parse_html()`. - ---- - -## HTML Parsing (`parse_html`) - -Parse an HTML string and query it with CSS-like selectors. Call `.parse_html()` on any string. - -### Basic usage -``` -let html = "

Hello

World

" -let doc = html.parse_html() -``` - -### Querying elements -``` -doc.query("p") // all

elements (returns html handle) -doc.query("p[0]") // first

element -doc.query("#main") // element with id "main" -doc.query("p.bold") //

with class "bold" -doc.query("div > p") // direct children -doc.query("div p") // descendants -doc.query("div > *") // all direct children (wildcard) -doc.query("div").query("p") // chained queries -``` - -### Extracting data -``` -doc.query("p[0]").text // text content: "Hello" -doc.query("div@class") // attribute value: "box" -doc.query("div@id") // attribute value: "main" -doc.query("p.text") // array of text from all

: ["Hello", "World"] -doc.query("p@class") // array of class attrs from all

-``` - -### Properties on html handles -``` -handle.length // number of matched elements -handle.text // text content (concatenated) -handle.html // reconstructed HTML string -handle.attr("name") // attribute value (string or nil) -handle.array() // convert to array of element handles -``` - -### Iterating results -``` -let items = doc.query("a.result__a").array() -for item, i in items { - let title = item.text - let href = item.attr("href") - // ... use title and href -} -``` - -### Full example: search DuckDuckGo and parse results -``` -fn do_search(query) { - let req = net.HttpRequest{ - url: "https://html.duckduckgo.com/html/?q=" + query - method: net.HttpMethod.GET - headers: {"User-Agent": "MakepadApp/1.0"} - } - net.http_request(req) do net.HttpEvents{ - on_response: |res| { - let doc = res.body.to_string().parse_html() - let links = doc.query("a.result__a").array() - let snippets = doc.query("a.result__snippet").array() - for link, i in links { - let title = link.text - let url = link.attr("href") - let snippet = if i < snippets.len() snippets[i].text else "" - // ... build result list - } - } - on_error: |e| { /* handle error */ } - } -} -``` - ---- - -## Notes - -- **⛔ Default text color is WHITE.** For light/white themes, set `draw_text.color` to a dark color (e.g. `#222`, `#333`) on ALL text elements. Otherwise text is invisible (white-on-white). -- **⛔ Set `new_batch: true` on ANY View with `show_bg: true` that contains text.** Makepad batches same-shader widgets into one draw call. Without `new_batch: true`, text renders behind backgrounds (invisible text). This is especially critical for **hoverable items** — text vanishes on hover when the background becomes opaque. Set it on BOTH the item template AND the parent container. -- **⚠️ ALWAYS set `height: Fit` on containers!** The default is `height: Fill` which causes 0-height (invisible UI) in this context. -- **⛔ Named children in `let` templates MUST use `:=`:** `label := Label{...}`, `tag := Label{...}`, `check := CheckBox{...}`. Override with `Item{label.text: "x"}`. Without `:=`, text is invisible. -- **⛔ Named children inside anonymous Views are UNREACHABLE.** If `label :=` is inside an unnamed `View{}`, `Item{label.text: "x"}` fails silently. Give the View a name: `texts := View{ label := Label{...} }` then override with `Item{texts.label.text: "x"}`. -- **🚫 DO NOT invent properties or syntax.** Only use what's documented in this manual. No guessing. -- No commas between sibling properties (space or newline separated) -- **Use commas when values contain negative numbers or could be parsed as expressions**: `vec4(-1.0, -1.0, -1.0, -1.0)` NOT `vec4(-1.0 -1.0 -1.0 -1.0)` (the parser would see `-1.0 -1.0` as subtraction). Safe rule: always use commas inside `vec2()`, `vec4()`, and array literals when any value is negative or an expression -- `+:` merges with parent; without it, replaces entirely -- `:=` declares named/dynamic/template children (e.g. `label := Label{...}`) -- Bare numbers for Size become `Fixed(n)`: `width: 200` = `width: Size.Fixed(200)` -- Resources: `crate_resource("self://relative/path")` -- Function args in shaders: space-separated, no commas: `sdf.box(0. 0. 100. 100. 5.0)` -- `if` in shaders: `if condition { ... } else { ... }` (no parens around condition) -- `for` in shaders: `for i in 0..4 { ... }` -- `match` in shaders: `match self.block_type { Type.A => { ... } Type.B => { ... } }` -- Inherit + override: `theme.mspace_1{left: theme.space_2}` — takes mspace_1 but overrides left -- Strings use double quotes only: `text: "Hello"`. No single quotes, no backticks. - -## Guidelines - -- Use runsplash blocks for anything visual: UI mockups, styled cards, layouts, color palettes, shader demos, button groups, form layouts, etc. -- You can have multiple runsplash blocks in a single response, mixed with normal markdown text. -- Keep splash blocks focused — one concept per block when possible. -- Use `let` bindings at the top of a block to define reusable styled components, then instantiate them below. -- Use theme variables (theme.color_bg_app, theme.space_2, etc.) for consistent styling. -- For simple text answers, just use normal markdown without runsplash blocks. - -## Vector Widget (SVG-like Drawing) - -The `Vector{}` widget renders SVG-like vector graphics declaratively in Splash. It supports paths, shapes, gradients, filters, groups, transforms, and animations — all without loading external SVG files. - -### Basic Usage - -``` -Vector{width: 200 height: 200 viewbox: vec4(0 0 200 200) - Rect{x: 10 y: 10 w: 80 h: 60 rx: 5 ry: 5 fill: #f80} - Circle{cx: 150 cy: 50 r: 30 fill: #08f} - Line{x1: 10 y1: 150 x2: 190 y2: 150 stroke: #fff stroke_width: 2} -} -``` - -The `viewbox` property defines the coordinate space as `vec4(x y width height)`. The widget sizes itself to fit the viewbox when `width: Fit` and `height: Fit` (the defaults), or you can set explicit pixel dimensions. - -### Shape Types - -All shapes support these common style properties: - -| Property | Type | Default | Notes | -|----------|------|---------|-------| -| `fill` | color, Gradient, RadGradient, Tween, or `false` | inherited | `false` = no fill | -| `fill_opacity` | f32 | 1.0 | multiplied with fill alpha | -| `stroke` | color, Gradient, or Tween | none | outline color | -| `stroke_width` | f32 or Tween | 0.0 | outline thickness | -| `stroke_opacity` | f32 or Tween | 1.0 | outline alpha | -| `opacity` | f32 or Tween | 1.0 | overall shape opacity | -| `stroke_linecap` | string | "butt" | "butt", "round", "square" | -| `stroke_linejoin` | string | "miter" | "miter", "round", "bevel" | -| `transform` | Transform or array | identity | see Transforms section | -| `filter` | Filter ref | none | see Filters section | -| `shader_id` | f32 | 0.0 | for custom GPU effects on Svg widget | - -#### Path — SVG path data -``` -Path{d: "M 10 10 L 100 100 C 50 50 200 200 300 300 Z" fill: #f00 stroke: #000 stroke_width: 2} -``` -The `d` property accepts standard SVG path data strings (M, L, C, Q, A, Z, etc.). - -#### Rect — Rectangle -``` -Rect{x: 10 y: 20 w: 100 h: 50 rx: 5 ry: 5 fill: #f80 stroke: #fff stroke_width: 1} -``` - -#### Circle -``` -Circle{cx: 50 cy: 50 r: 40 fill: #08f} -``` - -#### Ellipse -``` -Ellipse{cx: 100 cy: 50 rx: 80 ry: 40 fill: #0f8} -``` - -#### Line -``` -Line{x1: 10 y1: 10 x2: 190 y2: 190 stroke: #fff stroke_width: 2 stroke_linecap: "round"} -``` - -#### Polyline — open connected segments -``` -Polyline{pts: [10 10 50 80 100 20 150 90] fill: false stroke: #ff0 stroke_width: 2} -``` - -#### Polygon — closed connected segments -``` -Polygon{pts: [100 10 40 198 190 78 10 78 160 198] fill: #f0f stroke: #fff stroke_width: 1} -``` - -### Groups - -`Group{}` composes shapes and applies shared styles/transforms to all children: - -``` -Vector{width: 200 height: 200 viewbox: vec4(0 0 200 200) - Group{opacity: 0.7 transform: Rotate{deg: 15} - Rect{x: 20 y: 20 w: 60 h: 60 fill: #f00} - Circle{cx: 130 cy: 50 r: 30 fill: #0f0} - } -} -``` - -Groups can be nested. Style properties on a Group (fill, stroke, etc.) apply to its children. - -### Gradients - -Define gradients as `let` bindings and reference them in `fill` or `stroke`: - -#### Linear Gradient -``` -let my_grad = Gradient{x1: 0 y1: 0 x2: 1 y2: 1 - Stop{offset: 0 color: #ff0000} - Stop{offset: 0.5 color: #00ff00} - Stop{offset: 1 color: #0000ff} -} - -Vector{width: 200 height: 100 viewbox: vec4(0 0 200 100) - Rect{x: 0 y: 0 w: 200 h: 100 fill: my_grad} -} -``` - -Gradient coordinates (`x1`, `y1`, `x2`, `y2`) are in the range 0–1 (object bounding box). `Stop` children define color stops with `offset` (0–1), `color`, and optional `opacity`. - -#### Radial Gradient -``` -let radial = RadGradient{cx: 0.5 cy: 0.5 r: 0.5 - Stop{offset: 0 color: #fff} - Stop{offset: 1 color: #000} -} - -Vector{width: 200 height: 200 viewbox: vec4(0 0 200 200) - Circle{cx: 100 cy: 100 r: 90 fill: radial} -} -``` - -RadGradient properties: `cx`, `cy` (center, default 0.5), `r` (radius, default 0.5), `fx`, `fy` (focal point, defaults to center). - -#### Gradient stops with opacity -``` -let glass = Gradient{x1: 0 y1: 0 x2: 1 y2: 1 - Stop{offset: 0 color: #xffffff opacity: 0.35} - Stop{offset: 0.4 color: #xffffff opacity: 0.08} - Stop{offset: 1 color: #xffffff opacity: 0.2} -} -``` - -### Filters - -Define a `Filter` with `DropShadow` effects: - -``` -let shadow = Filter{ - DropShadow{dx: 2 dy: 4 blur: 6 color: #000000 opacity: 0.5} -} - -Vector{width: 200 height: 200 viewbox: vec4(0 0 200 200) - Rect{x: 40 y: 40 w: 120 h: 120 rx: 10 ry: 10 fill: #445 filter: shadow} -} -``` - -DropShadow properties: `dx` (x offset), `dy` (y offset), `blur` (blur radius), `color`, `opacity`. - -### Transforms - -Transforms can be applied to any shape or group via the `transform` property. Use a single transform or an array of transforms (composed left-to-right): - -#### Static transforms -``` -// Single transform -Rect{x: 0 y: 0 w: 50 h: 50 fill: #f00 transform: Rotate{deg: 45}} - -// Multiple transforms (composed left-to-right) -Group{transform: [Translate{x: 100 y: 50} Scale{x: 2 y: 2} Rotate{deg: 30}] - Circle{cx: 0 cy: 0 r: 20 fill: #0ff} -} -``` - -Available transforms: -- `Rotate{deg: 45}` — rotation in degrees. Optional `cx`, `cy` for rotation center -- `Scale{x: 2 y: 1.5}` — scale factors. If only `x` is given, `y` defaults to the same value -- `Translate{x: 100 y: 50}` — translation offset -- `SkewX{deg: 30}` — horizontal skew -- `SkewY{deg: 15}` — vertical skew - -#### Animated transforms -Add `dur`, `from`, `to` (or `values`), and optionally `loop_` and `begin` to animate: - -``` -// Continuously rotating shape -Circle{cx: 100 cy: 100 r: 30 fill: #0ff - transform: Rotate{deg: 0 dur: 2.0 from: 0 to: 360 loop_: true} -} - -// Animated scale -Rect{x: 50 y: 50 w: 40 h: 40 fill: #f80 - transform: Scale{x: 1 dur: 1.5 from: 1 to: 2 loop_: true} -} -``` - -### Tween (Property Animation) - -Use `Tween{}` to animate individual shape properties (fill, stroke, d, x, y, r, etc.): - -``` -// Animated path morphing -Path{d: Tween{ - dur: 2.0 loop_: true - values: ["M 10 80 Q 50 10 100 80" "M 10 80 Q 50 150 100 80"] -} fill: #f0f} - -// Animated fill color -Circle{cx: 50 cy: 50 r: 30 - fill: Tween{dur: 1.5 loop_: true from: #ff0000 to: #0000ff} -} - -// Animated stroke width -Rect{x: 10 y: 10 w: 80 h: 80 - fill: false stroke: #fff - stroke_width: Tween{dur: 2.0 loop_: true from: 1 to: 5} -} -``` - -Tween properties: -- `from`, `to` — start and end values -- `values` — array of keyframe values (alternative to from/to) -- `dur` — duration in seconds -- `begin` — start delay in seconds -- `loop_` — `true` for indefinite, or a number for repeat count -- `calc` — "linear" (default), "discrete", "paced", "spline" -- `fill_mode` — "remove" (default) or "freeze" - -### Complete Example: App Icon with Gradients, Groups, and Filters - -This example from the splash demo recreates the Makepad app icon using Vector: - -``` -// Define gradients -let glass_bg = Gradient{x1: 0 y1: 0 x2: 1 y2: 1 - Stop{offset: 0 color: #x556677 opacity: 0.45} - Stop{offset: 1 color: #x334455 opacity: 0.35} -} -let brain_grad = Gradient{x1: 0.5 y1: 0 x2: 0.5 y2: 1 - Stop{offset: 0 color: #x77ccff} - Stop{offset: 0.4 color: #x7799ee} - Stop{offset: 0.75 color: #x8866dd} - Stop{offset: 1 color: #x9944cc} -} -let brain_glow = RadGradient{cx: 0.5 cy: 0.45 r: 0.45 - Stop{offset: 0 color: #x4466ee opacity: 0.4} - Stop{offset: 1 color: #x4466dd opacity: 0.0} -} - -// Define filter -let icon_shadow = Filter{ - DropShadow{dx: 0 dy: 4 blur: 6 color: #x000000 opacity: 0.5} -} - -Vector{width: 256 height: 256 viewbox: vec4(0 0 256 256) - // Glass background with shadow - Rect{x: 16 y: 16 w: 224 h: 224 rx: 44 ry: 44 - fill: glass_bg filter: icon_shadow} - - // Brain glow - Circle{cx: 128 cy: 95 r: 80 fill: brain_glow} - - // Brain paths (scaled and translated group) - Group{transform: [Translate{x: 36.8 y: 11.4} Scale{x: 7.6 y: 7.6}] - Path{d: "M15.5 13a3.5 3.5 0 0 0 -3.5 3.5v1a3.5 3.5 0 0 0 7 0v-1.8" - fill: false stroke: brain_grad stroke_width: 0.35 - stroke_linecap: "round" stroke_linejoin: "round"} - Path{d: "M8.5 13a3.5 3.5 0 0 1 3.5 3.5v1a3.5 3.5 0 0 1 -7 0v-1.8" - fill: false stroke: brain_grad stroke_width: 0.35 - stroke_linecap: "round" stroke_linejoin: "round"} - } - - // Keyboard keys - Rect{x: 73 y: 190 w: 9 h: 6 rx: 1 ry: 1 fill: #xffffff fill_opacity: 0.18} - Rect{x: 85 y: 190 w: 9 h: 6 rx: 1 ry: 1 fill: #xffffff fill_opacity: 0.18} -} -``` - -### SVG Icons in Vector - -Simple SVG icons can be embedded directly as `Path` shapes: - -``` -// File icon (from icon_file.svg) -Vector{width: 32 height: 32 viewbox: vec4(0 0 49 49) - Path{d: "M12.069,11.678c0,-2.23 1.813,-4.043 4.043,-4.043l10.107,0l0,8.086c0,1.118 0.903,2.021 2.021,2.021l8.086,0l0,18.193c0,2.23 -1.813,4.043 -4.043,4.043l-16.171,0c-2.23,0 -4.043,-1.813 -4.043,-4.043l0,-24.257Zm24.257,4.043l-8.086,0l0,-8.086l8.086,8.086Z"} -} - -// Folder icon -Vector{width: 32 height: 32 viewbox: vec4(0 0 49 49) - Path{d: "M11.884,37.957l24.257,0c2.23,0 4.043,-1.813 4.043,-4.043l0,-16.172c0,-2.23 -1.813,-4.042 -4.043,-4.042l-10.107,0c-0.638,0 -1.238,-0.297 -1.617,-0.809l-1.213,-1.617c-0.765,-1.017 -1.965,-1.617 -3.235,-1.617l-8.085,0c-2.23,0 -4.043,1.813 -4.043,4.043l0,20.214c0,2.23 1.813,4.043 4.043,4.043Z"} -} -``` - -### Vector vs Svg Widget - -| | `Vector{}` | `Svg{}` | -|---|---|---| -| **Input** | Declarative shapes in Splash script | External `.svg` file via resource handle | -| **Use case** | Programmatic/inline vector graphics | Loading pre-made SVG assets | -| **Gradients** | `let` bindings, referenced by name | Parsed from SVG `` | -| **Animation** | `Tween{}` on properties, animated transforms | Parsed from SVG `` elements | -| **Custom shaders** | `shader_id` + custom `get_color` on Svg | Same mechanism via `draw_svg +:` | -| **Syntax** | `Vector{viewbox: ... Path{} Rect{}}` | `Svg{draw_svg +: {svg: crate_resource("self://file.svg")}}` | - -Use `Vector{}` when you want to define graphics inline in your UI script. Use `Svg{}` when loading existing SVG files as assets. - -### Hex Color Escaping Reminder - -When using hex colors containing the letter `e` inside `script_mod!`, use the `#x` prefix to avoid parse errors: -``` -// These need #x prefix (contain 'e' adjacent to digits) -fill: #x2ecc71 -fill: #x1e1e2e -fill: #x4466ee - -// These are fine without #x (no 'e' issue) -fill: #ff4444 -fill: #00ff00 -``` - -## MathView Widget (LaTeX Math Rendering) - -The `MathView{}` widget renders LaTeX mathematical equations using vector glyph rendering with the NewCMMath font. - -### Basic Usage - -``` -MathView{text: "x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}" font_size: 14.0} -``` - -### Properties - -| Property | Type | Default | Notes | -|----------|------|---------|-------| -| `text` | string | "" | LaTeX math expression | -| `font_size` | f64 | 11.0 | Font size in points | -| `color` | vec4 | #fff | Color of rendered math | -| `width` | Size | Fit | Widget width | -| `height` | Size | Fit | Widget height | - -### Examples - -``` -// Inline in a layout -View{flow: Down height: Fit spacing: 12 padding: 15 - - Label{text: "Quadratic Formula" draw_text.color: #aaa draw_text.text_style.font_size: 10} - MathView{text: "x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}" font_size: 14.0} - - Label{text: "Euler's Identity" draw_text.color: #aaa draw_text.text_style.font_size: 10} - MathView{text: "e^{i\\pi} + 1 = 0" font_size: 16.0} - - Label{text: "Integral" draw_text.color: #aaa draw_text.text_style.font_size: 10} - MathView{text: "\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}" font_size: 14.0} - - Label{text: "Matrix" draw_text.color: #aaa draw_text.text_style.font_size: 10} - MathView{text: "\\begin{pmatrix} a & b \\\\ c & d \\end{pmatrix}" font_size: 14.0} - - Label{text: "Sum" draw_text.color: #aaa draw_text.text_style.font_size: 10} - MathView{text: "\\sum_{n=1}^{\\infty} \\frac{1}{n^2} = \\frac{\\pi^2}{6}" font_size: 14.0} - - Label{text: "Maxwell's Equations" draw_text.color: #aaa draw_text.text_style.font_size: 10} - MathView{text: "\\nabla \\times \\mathbf{E} = -\\frac{\\partial \\mathbf{B}}{\\partial t}" font_size: 14.0} -} -``` - -### Different Sizes - -``` -View{width: Fill height: Fit flow: Right spacing: 15 align: Align{y: 0.5}} -MathView{text: "\\alpha + \\beta" font_size: 8.0} -MathView{text: "\\alpha + \\beta" font_size: 12.0} -MathView{text: "\\alpha + \\beta" font_size: 18.0} -MathView{text: "\\alpha + \\beta" font_size: 24.0} -``` - -### Supported LaTeX - -**Fractions & Roots:** -`\frac{a}{b}`, `\dfrac{a}{b}`, `\tfrac{a}{b}`, `\sqrt{x}`, `\sqrt[n]{x}` - -**Subscripts & Superscripts:** -`x_i`, `x^2`, `x_i^2`, `a_{n+1}` - -**Greek Letters (lowercase):** -`\alpha`, `\beta`, `\gamma`, `\delta`, `\epsilon`, `\zeta`, `\eta`, `\theta`, `\lambda`, `\mu`, `\nu`, `\xi`, `\pi`, `\rho`, `\sigma`, `\tau`, `\phi`, `\chi`, `\psi`, `\omega` - -**Greek Letters (uppercase):** -`\Gamma`, `\Delta`, `\Theta`, `\Lambda`, `\Xi`, `\Pi`, `\Sigma`, `\Phi`, `\Psi`, `\Omega` - -**Big Operators:** -`\sum`, `\prod`, `\int`, `\iint`, `\iiint`, `\oint`, `\bigcup`, `\bigcap`, `\bigoplus`, `\bigotimes` - -**Relations:** -`=`, `\neq`, `<`, `>`, `\leq`, `\geq`, `\sim`, `\approx`, `\equiv`, `\subset`, `\supset`, `\in`, `\notin` - -**Arrows:** -`\leftarrow`, `\rightarrow`, `\leftrightarrow`, `\Leftarrow`, `\Rightarrow`, `\Leftrightarrow`, `\mapsto` - -**Accents:** -`\hat{x}`, `\bar{x}`, `\tilde{x}`, `\vec{x}`, `\dot{x}`, `\ddot{x}`, `\overline{x}`, `\underline{x}` - -**Delimiters (auto-sizing with \left...\right):** -`\left( \right)`, `\left[ \right]`, `\left\{ \right\}`, `\left| \right|`, `\langle \rangle`, `\lfloor \rfloor`, `\lceil \rceil` - -**Matrices:** -``` -\begin{pmatrix} a & b \\ c & d \end{pmatrix} % parentheses -\begin{bmatrix} a & b \\ c & d \end{bmatrix} % brackets -\begin{vmatrix} a & b \\ c & d \end{vmatrix} % determinant bars -\begin{cases} a & \text{if } x > 0 \\ b & \text{otherwise} \end{cases} -``` - -**Styles:** -`\mathbf{x}` (bold), `\mathit{x}` (italic), `\mathrm{x}` (roman), `\mathcal{x}` (calligraphic), `\mathbb{R}` (blackboard bold), `\mathfrak{g}` (fraktur) - -**Spacing:** -`\,` (thin), `\:` (medium), `\;` (thick), `\!` (negative thin), `\quad`, `\qquad` - -**Text & Operators:** -`\text{...}`, `\sin`, `\cos`, `\tan`, `\log`, `\ln`, `\exp`, `\lim`, `\min`, `\max`, `\det` - -**Dots:** -`\ldots`, `\cdots`, `\vdots`, `\ddots` - -**Misc Symbols:** -`\infty`, `\partial`, `\nabla`, `\forall`, `\exists`, `\emptyset`, `\pm`, `\mp`, `\times`, `\div`, `\cdot` - -### Notes - -- MathView is read-only — no selection or editing -- Uses Display math style (large operators centered) -- Backslashes must be escaped as `\\` in Splash strings -- The widget sizes itself to fit the rendered equation by default (`width: Fit`, `height: Fit`) -- An empty `text` produces no output - diff --git a/resources/icons/search.svg b/resources/icons/search.svg index a685692b8..52f7f3ff4 100644 --- a/resources/icons/search.svg +++ b/resources/icons/search.svg @@ -1,3 +1,5 @@ - - + + + + diff --git a/resources/icons/settings.svg b/resources/icons/settings.svg index f047ec0cd..302f3e489 100644 --- a/resources/icons/settings.svg +++ b/resources/icons/settings.svg @@ -1,3 +1,12 @@ - - - + + + + + + + + + + \ No newline at end of file diff --git a/resources/icons/triangle_down_fill.svg b/resources/icons/triangle_down_fill.svg deleted file mode 100644 index 70710b89b..000000000 --- a/resources/icons/triangle_down_fill.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/resources/icons/triangle_up_fill.svg b/resources/icons/triangle_fill.svg similarity index 100% rename from resources/icons/triangle_up_fill.svg rename to resources/icons/triangle_fill.svg diff --git a/resources/img/default_avatar.png b/resources/img/default_avatar.png new file mode 100644 index 000000000..bbd4fc661 Binary files /dev/null and b/resources/img/default_avatar.png differ diff --git a/src/app.rs b/src/app.rs index 6066b3f9b..4c0a4a54f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -11,33 +11,53 @@ use crate::{ event_source_modal::{EventSourceModalAction, EventSourceModalWidgetRefExt}, invite_modal::{InviteModalAction, InviteModalWidgetRefExt}, main_desktop_ui::MainDesktopUiAction, navigation_tab_bar::{NavigationBarAction, SelectedTab}, new_message_context_menu::NewMessageContextMenuWidgetRefExt, room_context_menu::RoomContextMenuWidgetRefExt, room_screen::{InviteAction, MessageAction, clear_timeline_states}, rooms_list::{RoomsListAction, RoomsListRef, RoomsListUpdate, clear_all_invited_rooms, enqueue_rooms_list_update} }, join_leave_room_modal::{ JoinLeaveModalKind, JoinLeaveRoomModalAction, JoinLeaveRoomModalWidgetRefExt - }, login::login_screen::LoginAction, logout::logout_confirm_modal::{LogoutAction, LogoutConfirmModalAction, LogoutConfirmModalWidgetRefExt}, persistence, profile::user_profile_cache::clear_user_profile_cache, room::BasicRoomDetails, shared::{confirmation_modal::{ConfirmationModalContent, ConfirmationModalWidgetRefExt}, image_viewer::{ImageViewerAction, LoadState}, popup_list::{PopupKind, enqueue_popup_notification}}, sliding_sync::{DirectMessageRoomAction, MatrixRequest, current_user_id, submit_async_request}, utils::RoomNameId, verification::VerificationAction, verification_modal::{ + }, login::login_screen::LoginAction, logout::logout_confirm_modal::{LogoutAction, LogoutConfirmModalAction, LogoutConfirmModalWidgetRefExt}, persistence, profile::user_profile_cache::clear_user_profile_cache, room::BasicRoomDetails, shared::{callout_tooltip::{ + CalloutTooltipWidgetRefExt, + TooltipAction, + }, confirmation_modal::{ConfirmationModalContent, ConfirmationModalWidgetRefExt}, image_viewer::{ImageViewerAction, LoadState}, popup_list::{PopupKind, enqueue_popup_notification}}, sliding_sync::{DirectMessageRoomAction, MatrixRequest, current_user_id, submit_async_request}, utils::RoomNameId, verification::VerificationAction, verification_modal::{ VerificationModalAction, VerificationModalWidgetRefExt, } }; -script_mod! { - use mod.prelude.widgets.* - use mod.widgets.* - - load_all_resources() do #(App::script_component(vm)) { - ui: Root { - main_window := Window { - window.inner_size: vec2(1280, 800) - window.title: "Robrix" - pass.clear_color: #FFFFFF00 - caption_bar +: { - draw_bg.color: #F3F3F3 - caption_label +: { - label +: { - align: Align{x: 0.5}, - draw_text +: { color: #0 } - text: "Robrix" +live_design! { + use link::theme::*; + use link::shaders::*; + use link::widgets::*; + + use crate::shared::styles::*; + use crate::home::home_screen::HomeScreen; + use crate::verification_modal::VerificationModal; + use crate::join_leave_room_modal::JoinLeaveRoomModal; + use crate::login::login_screen::LoginScreen; + use crate::logout::logout_confirm_modal::LogoutConfirmModal; + use crate::shared::confirmation_modal::*; + use crate::shared::popup_list::*; + use crate::home::new_message_context_menu::*; + use crate::home::room_context_menu::*; + use crate::home::invite_modal::InviteModal; + use crate::home::event_source_modal::EventSourceModal; + use crate::shared::callout_tooltip::CalloutTooltip; + use crate::shared::image_viewer::ImageViewer; + use link::tsp_link::TspVerificationModal; + + + App = {{App}} { + ui: { + main_window = { + window: {inner_size: vec2(1280, 800), title: "Robrix"}, + pass: {clear_color: #FFFFFF00} + caption_bar = { + caption_label = { + label = { + margin: {left: 65}, + align: {x: 0.5}, + text: "Robrix", + draw_text: {color: (COLOR_TEXT)} } } - windows_buttons +: { - // Note: these are the background colors of the buttons used in Windows: + windows_buttons = { + // Note: these are the background colors of the buttons used in Windows: // * idle: Clear, for all three buttons. // * hover: #E9E9E9 for minimize and maximize, #E81123 for close. // * down: either darker (on light mode) or lighter (on dark mode). @@ -46,113 +66,116 @@ script_mod! { // so these colors are the colors of the icon itself, not the background highlight. // When it supports that, we will keep the icon color always black, // and change the background color instead based on the above colors. - min +: { draw_bg +: {color: #0, color_hover: #9, color_down: #3} } - max +: { draw_bg +: {color: #0, color_hover: #9, color_down: #3} } - close +: { draw_bg +: {color: #0, color_hover: #E81123, color_down: #FF0015} } + min = { draw_bg: {color: #0, color_hover: #9, color_down: #3} } + max = { draw_bg: {color: #0, color_hover: #9, color_down: #3} } + close = { draw_bg: {color: #0, color_hover: #E81123, color_down: #FF0015} } } + draw_bg: {color: #F3F3F3}, } - body +: { + body = { padding: 0, - View { + { width: Fill, height: Fill, flow: Overlay, - home_screen_view := View { + home_screen_view = { visible: false - home_screen := HomeScreen {} + home_screen = {} } - join_leave_modal := Modal { - content +: { - join_leave_modal_inner := JoinLeaveRoomModal {} + join_leave_modal = { + content: { + join_leave_modal_inner = {} } } - login_screen_view := View { + login_screen_view = { visible: true - login_screen := LoginScreen {} + login_screen = {} } - image_viewer_modal := Modal { - content +: { + image_viewer_modal = { + content: { width: Fill, height: Fill, - image_viewer_modal_inner := ImageViewer {} + image_viewer_modal_inner = {} } } // Context menus should be shown in front of other UI elements, // but behind verification modals. - new_message_context_menu := NewMessageContextMenu { } - room_context_menu := RoomContextMenu { } + new_message_context_menu = { } + room_context_menu = { } // A modal to confirm sending out an invite to a room. - invite_confirmation_modal := Modal { - content +: { - invite_confirmation_modal_inner := PositiveConfirmationModal { - wrapper +: { buttons_view +: { accept_button +: { - draw_icon +: { svg: (ICON_INVITE) } - icon_walk: Walk{width: 28, height: Fit, margin: Inset{left: -10, right: 2} } + invite_confirmation_modal = { + content: { + invite_confirmation_modal_inner = { + wrapper = { buttons_view = { accept_button = { + draw_icon: { + svg_file: (ICON_INVITE), + } + icon_walk: {width: 28, height: Fit, margin: {left: -10} } } } } } } } // A modal to invite a user to a room. - invite_modal := Modal { - content +: { - invite_modal_inner := InviteModal {} + invite_modal = { + content: { + invite_modal_inner = {} } } // Show the logout confirmation modal. - logout_confirm_modal := Modal { - content +: { - logout_confirm_modal_inner := LogoutConfirmModal {} + logout_confirm_modal = { + content: { + logout_confirm_modal_inner = {} } } // Show the event source modal (View Source for messages). - event_source_modal := Modal { - content +: { + event_source_modal = { + content: { height: Fill, width: Fill, - align: Align{x: 0.5, y: 0.5}, - event_source_modal_inner := EventSourceModal {} + align: {x: 0.5, y: 0.5}, + event_source_modal_inner = {} } } // Show incoming verification requests in front of the aforementioned UI elements. - verification_modal := Modal { - content +: { - verification_modal_inner := VerificationModal {} + verification_modal = { + content: { + verification_modal_inner = {} } } - tsp_verification_modal := Modal { - content +: { - tsp_verification_modal_inner := TspVerificationModal {} + tsp_verification_modal = { + content: { + tsp_verification_modal_inner = {} } } // A generic modal to confirm any positive action. - positive_confirmation_modal := Modal { - content +: { - positive_confirmation_modal_inner := PositiveConfirmationModal { } + positive_confirmation_modal = { + content: { + positive_confirmation_modal_inner = { } } } // A modal to confirm any deletion/removal action. - delete_confirmation_modal := Modal { - content +: { - delete_confirmation_modal_inner := NegativeConfirmationModal { } + delete_confirmation_modal = { + content: { + delete_confirmation_modal_inner = { } } } - PopupList {} + {} // Tooltips must be shown in front of all other UI elements, // since they can be shown as a hover atop any other widget. - app_tooltip := CalloutTooltip {} + app_tooltip = {} } } // end of body } @@ -162,7 +185,7 @@ script_mod! { app_main!(App); -#[derive(Script)] +#[derive(Live)] pub struct App { #[live] ui: WidgetRef, /// The top-level app state, shared across various parts of the app. @@ -173,19 +196,52 @@ pub struct App { #[rust] waiting_to_navigate_to_room: Option<(BasicRoomDetails, Option)>, } -impl ScriptHook for App { - /// After a hot-reload update, refresh the login/home screen visibility. - fn on_after_reload(&mut self, vm: &mut ScriptVm) { - vm.with_cx_mut(|cx| { - self.update_login_visibility(cx); - }); +impl LiveRegister for App { + fn live_register(cx: &mut Cx) { + // Order matters here, as some widget definitions depend on others. + // The main `makepad_widgets` crate must be registered first, + // then other first-party makepad crates (like `makepad_code_editor`), + // then `shared`` widgets (in which styles are defined), + // then other modules widgets. + makepad_widgets::live_design(cx); + makepad_code_editor::live_design(cx); + // Override Makepad's default desktop dark theme with the desktop light theme. + cx.link(id!(theme), id!(theme_desktop_light)); + crate::shared::live_design(cx); + + // If the `tsp` cargo feature is enabled, we create a new "tsp_link" DSL namespace + // and link it to the real `tsp_enabled` DSL namespace, which contains real TSP widgets. + // If the `tsp` feature is not enabled, link the "tsp_link" DSL namespace + // to the `tsp_disabled` DSL namespace instead, which defines dummy placeholder widgets. + #[cfg(feature = "tsp")] { + crate::tsp::live_design(cx); + cx.link(id!(tsp_link), id!(tsp_enabled)); + } + #[cfg(not(feature = "tsp"))] { + crate::tsp_dummy::live_design(cx); + cx.link(id!(tsp_link), id!(tsp_disabled)); + } + + crate::settings::live_design(cx); + crate::room::live_design(cx); + crate::join_leave_room_modal::live_design(cx); + crate::verification_modal::live_design(cx); + crate::home::live_design(cx); + crate::profile::live_design(cx); + crate::login::live_design(cx); + crate::logout::live_design(cx); + } +} + +impl LiveHook for App { + fn after_update_from_doc(&mut self, cx: &mut Cx) { + self.update_login_visibility(cx); } - /// After initial creation, set the global singleton for the PopupList widget. - fn on_after_new(&mut self, vm: &mut ScriptVm) { - vm.with_cx_mut(|cx| { - crate::shared::popup_list::set_global_popup_list(cx, &self.ui); - }); + fn after_new_from_doc(&mut self, cx: &mut Cx) { + // Here we set the global singleton for the PopupList widget, + // which is used to access PopupList Widget from anywhere in the app. + crate::shared::popup_list::set_global_popup_list(cx, &self.ui); } } @@ -212,19 +268,10 @@ impl MatchEvent for App { let _app_data_dir = crate::app_data_dir(); log!("App::handle_startup(): app_data_dir: {:?}", _app_data_dir); - if let Err(e) = persistence::load_window_state(self.ui.window(cx, ids!(main_window)), cx) { + if let Err(e) = persistence::load_window_state(self.ui.window(ids!(main_window)), cx) { error!("Failed to load window state: {}", e); } - // Hide the caption bar on macOS, which uses native window chrome. - // On Windows (and Linux with custom chrome), the caption bar is needed. - if let OsType::Macos = cx.os_type() { - let mut window = self.ui.window(cx, ids!(main_window)); - script_apply_eval!(cx, window, { - show_caption_bar: false - }); - } - self.update_login_visibility(cx); log!("App::Startup: starting matrix sdk loop"); @@ -237,31 +284,31 @@ impl MatchEvent for App { } fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) { - let invite_confirmation_modal_inner = self.ui.confirmation_modal(cx, ids!(invite_confirmation_modal_inner)); + let invite_confirmation_modal_inner = self.ui.confirmation_modal(ids!(invite_confirmation_modal_inner)); if let Some(_accepted) = invite_confirmation_modal_inner.closed(actions) { - self.ui.modal(cx, ids!(invite_confirmation_modal)).close(cx); + self.ui.modal(ids!(invite_confirmation_modal)).close(cx); } - let delete_confirmation_modal_inner = self.ui.confirmation_modal(cx, ids!(delete_confirmation_modal_inner)); + let delete_confirmation_modal_inner = self.ui.confirmation_modal(ids!(delete_confirmation_modal_inner)); if let Some(_accepted) = delete_confirmation_modal_inner.closed(actions) { - self.ui.modal(cx, ids!(delete_confirmation_modal)).close(cx); + self.ui.modal(ids!(delete_confirmation_modal)).close(cx); } - let positive_confirmation_modal_inner = self.ui.confirmation_modal(cx, ids!(positive_confirmation_modal_inner)); + let positive_confirmation_modal_inner = self.ui.confirmation_modal(ids!(positive_confirmation_modal_inner)); if let Some(_accepted) = positive_confirmation_modal_inner.closed(actions) { - self.ui.modal(cx, ids!(positive_confirmation_modal)).close(cx); + self.ui.modal(ids!(positive_confirmation_modal)).close(cx); } for action in actions { match action.downcast_ref() { Some(LogoutConfirmModalAction::Open) => { - self.ui.logout_confirm_modal(cx, ids!(logout_confirm_modal_inner)).reset_state(cx); - self.ui.modal(cx, ids!(logout_confirm_modal)).open(cx); + self.ui.logout_confirm_modal(ids!(logout_confirm_modal_inner)).reset_state(cx); + self.ui.modal(ids!(logout_confirm_modal)).open(cx); continue; }, Some(LogoutConfirmModalAction::Close { was_internal, .. }) => { if *was_internal { - self.ui.modal(cx, ids!(logout_confirm_modal)).close(cx); + self.ui.modal(ids!(logout_confirm_modal)).close(cx); } continue; }, @@ -271,7 +318,7 @@ impl MatchEvent for App { match action.downcast_ref() { Some(LogoutAction::LogoutSuccess) => { self.app_state.logged_in = false; - self.ui.modal(cx, ids!(logout_confirm_modal)).close(cx); + self.ui.modal(ids!(logout_confirm_modal)).close(cx); self.update_login_visibility(cx); self.ui.redraw(cx); continue; @@ -295,37 +342,17 @@ impl MatchEvent for App { continue; } - // If a login failure occurs mid-session (e.g., an expired/revoked token detected - // by `handle_session_changes`), navigate back to the login screen. - // When not yet logged in, the login_screen widget handles displaying the failure modal. - if let Some(LoginAction::LoginFailure(_)) = action.downcast_ref() { - if self.app_state.logged_in { - log!("Received LoginAction::LoginFailure while logged in; showing login screen."); - self.app_state.logged_in = false; - self.update_login_visibility(cx); - self.ui.redraw(cx); - } - continue; - } - // Handle an action requesting to open the new message context menu. if let MessageAction::OpenMessageContextMenu { details, abs_pos } = action.as_widget_action().cast() { - self.ui.callout_tooltip(cx, ids!(app_tooltip)).hide(cx); - let new_message_context_menu = self.ui.new_message_context_menu(cx, ids!(new_message_context_menu)); + self.ui.callout_tooltip(ids!(app_tooltip)).hide(cx); + let new_message_context_menu = self.ui.new_message_context_menu(ids!(new_message_context_menu)); let expected_dimensions = new_message_context_menu.show(cx, details); // Ensure the context menu does not spill over the window's bounds. - let rect = self.ui.window(cx, ids!(main_window)).area().rect(cx); + let rect = self.ui.window(ids!(main_window)).area().rect(cx); let pos_x = min(abs_pos.x, rect.size.x - expected_dimensions.x); let pos_y = min(abs_pos.y, rect.size.y - expected_dimensions.y); - let margin = Inset { - left: pos_x as f64, - top: pos_y as f64, - right: 0.0, - bottom: 0.0, - }; - let mut main_content_view = new_message_context_menu.view(cx, ids!(main_content)); - script_apply_eval!(cx, main_content_view, { - margin: #(margin) + new_message_context_menu.apply_over(cx, live! { + main_content = { margin: { left: (pos_x), top: (pos_y) } } }); self.ui.redraw(cx); continue; @@ -333,22 +360,15 @@ impl MatchEvent for App { // Handle an action requesting to open the room context menu. if let RoomsListAction::OpenRoomContextMenu { details, pos } = action.as_widget_action().cast() { - self.ui.callout_tooltip(cx, ids!(app_tooltip)).hide(cx); - let room_context_menu = self.ui.room_context_menu(cx, ids!(room_context_menu)); + self.ui.callout_tooltip(ids!(app_tooltip)).hide(cx); + let room_context_menu = self.ui.room_context_menu(ids!(room_context_menu)); let expected_dimensions = room_context_menu.show(cx, details); // Ensure the context menu does not spill over the window's bounds. - let rect = self.ui.window(cx, ids!(main_window)).area().rect(cx); + let rect = self.ui.window(ids!(main_window)).area().rect(cx); let pos_x = min(pos.x, rect.size.x - expected_dimensions.x); let pos_y = min(pos.y, rect.size.y - expected_dimensions.y); - let margin = Inset { - left: pos_x as f64, - top: pos_y as f64, - right: 0.0, - bottom: 0.0, - }; - let mut main_content_view = room_context_menu.view(cx, ids!(main_content)); - script_apply_eval!(cx, main_content_view, { - margin: #(margin) + room_context_menu.apply_over(cx, live! { + main_content = { margin: { left: (pos_x), top: (pos_y) } } }); self.ui.redraw(cx); continue; @@ -358,14 +378,15 @@ impl MatchEvent for App { if let RoomsListAction::Selected(selected_room) = action.as_widget_action().cast() { // Set the Stack Navigation header to show the name of the newly-selected room. self.ui - .label(cx, ids!(main_content_view.header.content.title_container.title)) + .label(ids!(main_content_view.header.content.title_container.title)) .set_text(cx, &selected_room.display_name()); self.app_state.selected_room = Some(selected_room); // Navigate to the main content view cx.widget_action( - self.ui.widget_uid(), + self.ui.widget_uid(), + &HeapLiveIdPath::default(), StackNavigationAction::Push(id!(main_content_view)) ); self.ui.redraw(cx); @@ -424,11 +445,11 @@ impl MatchEvent for App { match action.as_widget_action().cast() { TooltipAction::HoverIn { text, widget_rect, options } => { // Don't show any tooltips if the message context menu is currently shown. - if self.ui.new_message_context_menu(cx, ids!(new_message_context_menu)).is_currently_shown(cx) { - self.ui.callout_tooltip(cx, ids!(app_tooltip)).hide(cx); + if self.ui.new_message_context_menu(ids!(new_message_context_menu)).is_currently_shown(cx) { + self.ui.callout_tooltip(ids!(app_tooltip)).hide(cx); } else { - self.ui.callout_tooltip(cx, ids!(app_tooltip)).show_with_options( + self.ui.callout_tooltip(ids!(app_tooltip)).show_with_options( cx, &text, widget_rect, @@ -438,7 +459,7 @@ impl MatchEvent for App { continue; } TooltipAction::HoverOut => { - self.ui.callout_tooltip(cx, ids!(app_tooltip)).hide(cx); + self.ui.callout_tooltip(ids!(app_tooltip)).hide(cx); continue; } _ => {} @@ -448,14 +469,14 @@ impl MatchEvent for App { match action.downcast_ref() { Some(JoinLeaveRoomModalAction::Open { kind, show_tip }) => { self.ui - .join_leave_room_modal(cx, ids!(join_leave_modal_inner)) + .join_leave_room_modal(ids!(join_leave_modal_inner)) .set_kind(cx, kind.clone(), *show_tip); - self.ui.modal(cx, ids!(join_leave_modal)).open(cx); + self.ui.modal(ids!(join_leave_modal)).open(cx); continue; } Some(JoinLeaveRoomModalAction::Close { was_internal, .. }) => { if *was_internal { - self.ui.modal(cx, ids!(join_leave_modal)).close(cx); + self.ui.modal(ids!(join_leave_modal)).close(cx); } continue; } @@ -467,22 +488,22 @@ impl MatchEvent for App { // // Note: other verification actions are handled by the verification modal itself. if let Some(VerificationAction::RequestReceived(state)) = action.downcast_ref() { - self.ui.verification_modal(cx, ids!(verification_modal_inner)) + self.ui.verification_modal(ids!(verification_modal_inner)) .initialize_with_data(cx, state.clone()); - self.ui.modal(cx, ids!(verification_modal)).open(cx); + self.ui.modal(ids!(verification_modal)).open(cx); continue; } if let Some(VerificationModalAction::Close) = action.downcast_ref() { - self.ui.modal(cx, ids!(verification_modal)).close(cx); + self.ui.modal(ids!(verification_modal)).close(cx); continue; } match action.downcast_ref() { Some(ImageViewerAction::Show(LoadState::Loading(_, _))) => { - self.ui.modal(cx, ids!(image_viewer_modal)).open(cx); + self.ui.modal(ids!(image_viewer_modal)).open(cx); continue; } Some(ImageViewerAction::Hide) => { - self.ui.modal(cx, ids!(image_viewer_modal)).close(cx); + self.ui.modal(ids!(image_viewer_modal)).close(cx); continue; } _ => {} @@ -493,13 +514,13 @@ impl MatchEvent for App { use crate::tsp::{tsp_verification_modal::{TspVerificationModalAction, TspVerificationModalWidgetRefExt}, TspIdentityAction}; if let Some(TspIdentityAction::ReceivedDidAssociationRequest { details, wallet_db }) = action.downcast_ref() { - self.ui.tsp_verification_modal(cx, ids!(tsp_verification_modal_inner)) + self.ui.tsp_verification_modal(ids!(tsp_verification_modal_inner)) .initialize_with_details(cx, details.clone(), wallet_db.deref().clone()); - self.ui.modal(cx, ids!(tsp_verification_modal)).open(cx); + self.ui.modal(ids!(tsp_verification_modal)).open(cx); continue; } if let Some(TspVerificationModalAction::Close) = action.downcast_ref() { - self.ui.modal(cx, ids!(tsp_verification_modal)).close(cx); + self.ui.modal(ids!(tsp_verification_modal)).close(cx); continue; } } @@ -508,7 +529,7 @@ impl MatchEvent for App { if let Some(InviteAction::ShowInviteConfirmationModal(content_opt)) = action.downcast_ref() { if let Some(content) = content_opt.borrow_mut().take() { invite_confirmation_modal_inner.show(cx, content); - self.ui.modal(cx, ids!(invite_confirmation_modal)).open(cx); + self.ui.modal(ids!(invite_confirmation_modal)).open(cx); } continue; } @@ -517,7 +538,7 @@ impl MatchEvent for App { if let Some(PositiveConfirmationModalAction::Show(content_opt)) = action.downcast_ref() { if let Some(content) = content_opt.borrow_mut().take() { positive_confirmation_modal_inner.show(cx, content); - self.ui.modal(cx, ids!(positive_confirmation_modal)).open(cx); + self.ui.modal(ids!(positive_confirmation_modal)).open(cx); } continue; } @@ -525,8 +546,8 @@ impl MatchEvent for App { // Handle a request to show the delete confirmation modal. if let Some(ConfirmDeleteAction::Show(content_opt)) = action.downcast_ref() { if let Some(content) = content_opt.borrow_mut().take() { - self.ui.confirmation_modal(cx, ids!(delete_confirmation_modal_inner)).show(cx, content); - self.ui.modal(cx, ids!(delete_confirmation_modal)).open(cx); + self.ui.confirmation_modal(ids!(delete_confirmation_modal_inner)).show(cx, content); + self.ui.modal(ids!(delete_confirmation_modal)).open(cx); } continue; } @@ -534,12 +555,12 @@ impl MatchEvent for App { // Handle InviteModalAction to open/close the invite modal. match action.downcast_ref() { Some(InviteModalAction::Open(room_name_id)) => { - self.ui.invite_modal(cx, ids!(invite_modal_inner)).show(cx, room_name_id.clone()); - self.ui.modal(cx, ids!(invite_modal)).open(cx); + self.ui.invite_modal(ids!(invite_modal_inner)).show(cx, room_name_id.clone()); + self.ui.modal(ids!(invite_modal)).open(cx); continue; } Some(InviteModalAction::Close) => { - self.ui.modal(cx, ids!(invite_modal)).close(cx); + self.ui.modal(ids!(invite_modal)).close(cx); continue; } _ => {} @@ -548,13 +569,13 @@ impl MatchEvent for App { // Handle EventSourceModalAction to open/close the event source modal. match action.downcast_ref() { Some(EventSourceModalAction::Open { room_id, event_id, original_json }) => { - self.ui.event_source_modal(cx, ids!(event_source_modal_inner)) + self.ui.event_source_modal(ids!(event_source_modal_inner)) .show(cx, room_id.clone(), event_id.clone(), original_json.clone()); - self.ui.modal(cx, ids!(event_source_modal)).open(cx); + self.ui.modal(ids!(event_source_modal)).open(cx); continue; } Some(EventSourceModalAction::Close) => { - self.ui.modal(cx, ids!(event_source_modal)).close(cx); + self.ui.modal(ids!(event_source_modal)).close(cx); continue; } _ => {} @@ -600,7 +621,7 @@ impl MatchEvent for App { ..Default::default() }, ); - self.ui.modal(cx, ids!(positive_confirmation_modal)).open(cx); + self.ui.modal(ids!(positive_confirmation_modal)).open(cx); } Some(DirectMessageRoomAction::FailedToCreate { user_profile, error }) => { enqueue_popup_notification( @@ -628,40 +649,9 @@ fn clear_all_app_state(cx: &mut Cx) { } impl AppMain for App { - fn script_mod(vm: &mut ScriptVm) -> makepad_widgets::ScriptValue { - // Order matters: base widgets first, then app widgets, then app UI. - makepad_widgets::theme_mod(vm); - // script_eval!(vm, { - // mod.theme = mod.themes.light - // }); - makepad_widgets::widgets_mod(vm); - makepad_code_editor::script_mod(vm); - crate::shared::script_mod(vm); - - #[cfg(feature = "tsp")] - crate::tsp::script_mod(vm); - #[cfg(not(feature = "tsp"))] - crate::tsp_dummy::script_mod(vm); - - crate::settings::script_mod(vm); - // RoomInputBar depends on these Home widgets; preload them before room::script_mod. - crate::home::location_preview::script_mod(vm); - crate::home::tombstone_footer::script_mod(vm); - crate::home::editing_pane::script_mod(vm); - crate::room::script_mod(vm); - crate::join_leave_room_modal::script_mod(vm); - crate::verification_modal::script_mod(vm); - crate::profile::script_mod(vm); - crate::home::script_mod(vm); - crate::login::script_mod(vm); - crate::logout::script_mod(vm); - - self::script_mod(vm) - } - fn handle_event(&mut self, cx: &mut Cx, event: &Event) { if let Event::Shutdown = event { - let window_ref = self.ui.window(cx, ids!(main_window)); + let window_ref = self.ui.window(ids!(main_window)); if let Err(e) = persistence::save_window_state(window_ref, cx) { error!("Failed to save window state. Error: {e}"); } @@ -711,7 +701,7 @@ impl AppMain for App { // We check which overlay views are visible in the order of those views' z-ordering, // such that the top-most views get a chance to handle the event first. - let new_message_context_menu = self.ui.new_message_context_menu(cx, ids!(new_message_context_menu)); + let new_message_context_menu = self.ui.new_message_context_menu(ids!(new_message_context_menu)); let is_interactive_hit = utils::is_interactive_hit_event(event); let is_pane_shown: bool; if new_message_context_menu.is_currently_shown(cx) { @@ -736,11 +726,11 @@ impl App { let show_login = !self.app_state.logged_in; if !show_login { self.ui - .modal(cx, ids!(login_screen_view.login_screen.login_status_modal)) + .modal(ids!(login_screen_view.login_screen.login_status_modal)) .close(cx); } - self.ui.view(cx, ids!(login_screen_view)).set_visible(cx, show_login); - self.ui.view(cx, ids!(home_screen_view)).set_visible(cx, !show_login); + self.ui.view(ids!(login_screen_view)).set_visible(cx, show_login); + self.ui.view(ids!(home_screen_view)).set_visible(cx, !show_login); } /// Navigates to the given `destination_room`, optionally closing the `room_to_close`. @@ -756,7 +746,8 @@ impl App { let widget_uid = self.ui.widget_uid(); move |cx: &mut Cx| { cx.widget_action( - widget_uid, + widget_uid, + &HeapLiveIdPath::default(), DockAction::TabCloseWasPressed(tab_id), ); enqueue_rooms_list_update(RoomsListUpdate::HideRoom { room_id: to_close.clone() }); @@ -764,8 +755,7 @@ impl App { }); let destination_room_id = destination_room.room_id(); - let room_state = cx.get_global::().get_room_state(destination_room_id); - let new_selected_room = match room_state { + let new_selected_room = match cx.get_global::().get_room_state(destination_room_id) { Some(RoomState::Joined) => SelectedRoom::JoinedRoom { room_name_id: destination_room.room_name_id().clone(), }, @@ -802,7 +792,8 @@ impl App { cx.action(NavigationBarAction::GoToHome); } cx.widget_action( - self.ui.widget_uid(), + self.ui.widget_uid(), + &HeapLiveIdPath::default(), RoomsListAction::Selected(new_selected_room), ); // Select and scroll to the destination room in the rooms list. diff --git a/src/home/add_room.rs b/src/home/add_room.rs index 981369897..65c138639 100644 --- a/src/home/add_room.rs +++ b/src/home/add_room.rs @@ -7,42 +7,52 @@ use ruma::{IdParseError, MatrixToUri, MatrixUri, OwnedRoomOrAliasId, OwnedServer use crate::{app::AppStateAction, home::invite_screen::JoinRoomResultAction, room::{FetchedRoomAvatar, FetchedRoomPreview, RoomPreviewAction}, shared::{avatar::AvatarWidgetRefExt, popup_list::{PopupKind, enqueue_popup_notification}}, sliding_sync::{MatrixRequest, submit_async_request}, utils}; -script_mod! { - use mod.prelude.widgets.* - use mod.widgets.* +live_design! { + use link::theme::*; + use link::shaders::*; + use link::widgets::*; + use crate::shared::styles::*; + use crate::shared::helpers::*; + use crate::shared::avatar::*; + use crate::shared::icon_button::*; + use crate::shared::html_or_plaintext::*; // The main view that allows the user to add (join) or explore new rooms/spaces. - mod.widgets.AddRoomScreen = #(AddRoomScreen::register_widget(vm)) { - ..mod.widgets.ScrollYView - + pub AddRoomScreen = {{AddRoomScreen}} { width: Fill, height: Fill, flow: Down, - padding: Inset{top: 5, left: 15, right: 15, bottom: 0}, + padding: {top: 5, left: 15, right: 15, bottom: 0}, + + // show_bg: true + // draw_bg: { + // color: (COLOR_PRIMARY) + // } - title := TitleLabel { - flow: Flow.Right{wrap: true}, - draw_text +: { - text_style: TITLE_TEXT {font_size: 13}, + title = { + flow: RightWrap, + draw_text: { + text_style: {font_size: 13}, color: #000 + wrap: Word } text: "Add/Explore Rooms and Spaces" - draw_text +: { - text_style: theme.font_regular {font_size: 18}, + draw_text: { + text_style: {font_size: 18}, } } - LineH { padding: 10, margin: Inset{top: 10, right: 2} } + { padding: 10, margin: {top: 10, right: 2} } - SubsectionLabel { + { text: "Join an existing room or space:" } // TODO: support showing/hiding this help with a collapsible widget wrapper // (Accordion widget, once it's added to Makepad upstream) - help_info := MessageHtml { + help_info = { padding: 7 width: Fill, height: Fit font_size: 10. @@ -56,84 +66,94 @@ script_mod! { " } - join_room_view := View { + join_room_view = { width: Fill, height: Fit, - margin: Inset{ top: 3, bottom: 4 } - align: Align{y: 0.5} + margin: { top: 3 } + align: {y: 0.5} spacing: 5 flow: Right - room_alias_id_input := RobrixTextInput { - align: Align{y: 0.5} - margin: Inset{top: 0, left: 5, right: 5, bottom: 0}, - padding: Inset{left: 12, right: 12, top: 11, bottom: 0} + room_alias_id_input = { + margin: {top: 0, left: 5, right: 5, bottom: 0}, width: Fill { max: 400 } // same width as the above `help_info` - height: 40 + height: Fit empty_text: "Enter alias, ID, or Matrix link..." } - search_for_room_button := RobrixIconButton { - padding: Inset{top: 10, bottom: 10, left: 12, right: 14} - height: 40 - draw_icon.svg: (ICON_SEARCH) - icon_walk: Walk{width: 16, height: 16} + search_for_room_button = { + padding: {top: 10, bottom: 10, left: 12, right: 14} + height: Fit + margin: { bottom: 4 }, + draw_bg: { + color: (COLOR_ACTIVE_PRIMARY) + } + draw_icon: { + svg_file: (ICON_SEARCH) + color: (COLOR_PRIMARY) + } + draw_text: { + color: (COLOR_PRIMARY) + text_style: {} + } + icon_walk: {width: 16, height: 16} text: "Go" } } - loading_room_view := View { + loading_room_view = { visible: false spacing: 5, padding: 10, width: Fill height: Fit - align: Align{y: 0.5} + align: {y: 0.5} flow: Right - loading_spinner := LoadingSpinner { + loading_spinner = { width: 25, height: 25, - draw_bg +: { + draw_bg: { color: (COLOR_ACTIVE_PRIMARY) - border_size: 3.0 + border_size: 3.0, } } - loading_text := Label { + loading_text = No topic set"), ); - let room_summary = fetched_room_summary.label(cx, ids!(room_summary)); - let join_room_button = fetched_room_summary.button(cx, ids!(join_room_button)); + let room_summary = fetched_room_summary.label(ids!(room_summary)); + let join_room_button = fetched_room_summary.button(ids!(join_room_button)); let join_function = match (&frp.state, &frp.join_rule) { (Some(RoomState::Joined), _) => { room_summary.set_text(cx, &format!("You have already joined this {room_or_space_lc}.")); @@ -724,6 +761,8 @@ impl Widget for AddRoomScreen { AddRoomState::FetchedRoomPreview { .. } => { join_room_button.set_enabled(cx, !matches!(join_function, JoinButtonFunction::None)); self.join_function = join_function; + join_room_button.reset_hover(cx); + fetched_room_summary.button(ids!(cancel_button)).reset_hover(cx); } AddRoomState::Knocked { .. } => { room_summary.set_text(cx, &format!("You have knocked on this {room_or_space_lc} and must now wait for someone to invite you in.")); diff --git a/src/home/edited_indicator.rs b/src/home/edited_indicator.rs index 07fb24f0d..91911a3df 100644 --- a/src/home/edited_indicator.rs +++ b/src/home/edited_indicator.rs @@ -11,33 +11,35 @@ use chrono::{DateTime, Local}; use makepad_widgets::*; use matrix_sdk_ui::timeline::EventTimelineItem; -use crate::utils::unix_time_millis_to_datetime; +use crate::{shared::callout_tooltip::{CalloutTooltipOptions, TooltipAction, TooltipPosition}, utils::unix_time_millis_to_datetime}; -script_mod! { - use mod.prelude.widgets.* - use mod.widgets.* +live_design! { + use link::theme::*; + use link::shaders::*; + use link::widgets::*; + use crate::shared::styles::*; - mod.widgets.EDITED_INDICATOR_FONT_SIZE = 9.5 - mod.widgets.EDITED_INDICATOR_FONT_COLOR = #666666 + pub EDITED_INDICATOR_FONT_SIZE = 9.5 + pub EDITED_INDICATOR_FONT_COLOR = #666666 - mod.widgets.EditedIndicator = #(EditedIndicator::register_widget(vm)) { + pub EditedIndicator = {{EditedIndicator}} { visible: false, // default to hidden width: Fit, height: Fit flow: Right, padding: 0, - margin: Inset{ top: 5 } + margin: { top: 5 } // TODO: re-enable this once we have implemented the edit history modal - // cursor: MouseCursor.Hand, + // cursor: Hand, - edit_html := Html { + edit_html = { width: Fit, height: Fit flow: Right, // do not wrap padding: 0, margin: 0, - font_size: (mod.widgets.EDITED_INDICATOR_FONT_SIZE), + font_size: (EDITED_INDICATOR_FONT_SIZE), font_color: (COLOR_ROBRIX_PURPLE), body: "(edited)", } @@ -45,7 +47,7 @@ script_mod! { } /// A interactive label that indicates a message has been edited. -#[derive(Script, ScriptHook, Widget)] +#[derive(Live, LiveHook, Widget)] pub struct EditedIndicator { #[deref] view: View, #[rust] latest_edit_ts: Option>, @@ -65,7 +67,7 @@ impl Widget for EditedIndicator { // false // }, Hit::FingerHoverOut(_) => { - cx.widget_action(self.widget_uid(), TooltipAction::HoverOut); + cx.widget_action(self.widget_uid(), &scope.path, TooltipAction::HoverOut); false } _ => false, @@ -79,7 +81,8 @@ impl Widget for EditedIndicator { "Last edit time unknown".to_string() }; cx.widget_action( - self.widget_uid(), + self.widget_uid(), + &scope.path, TooltipAction::HoverIn { text, widget_rect: area.rect(cx), @@ -122,11 +125,10 @@ impl EditedIndicatorRef { /// Actions emitted by an `EditedIndicator` widget. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, DefaultNone)] pub enum EditedIndicatorAction { /// The indicator was clicked, and thus we should open /// a modal/dialog showing the message's full edit history. ShowEditHistory, - #[default] None, } diff --git a/src/home/editing_pane.rs b/src/home/editing_pane.rs index ae89492b0..842682adf 100644 --- a/src/home/editing_pane.rs +++ b/src/home/editing_pane.rs @@ -10,107 +10,129 @@ use matrix_sdk::{ }; use matrix_sdk_ui::timeline::{EventTimelineItem, MsgLikeKind, TimelineEventItemId, TimelineItemContent}; -use crate::shared::mentionable_text_input::{MentionableTextInputWidgetExt, MentionableTextInputWidgetRefExt}; +use crate::shared::mentionable_text_input::MentionableTextInputWidgetExt; use crate::{ shared::popup_list::{enqueue_popup_notification, PopupKind}, sliding_sync::{submit_async_request, MatrixRequest, TimelineKind}, }; -script_mod! { - use mod.prelude.widgets.* - use mod.widgets.* +live_design! { + use link::theme::*; + use link::shaders::*; + use link::widgets::*; + use crate::shared::helpers::*; + use crate::shared::styles::*; + use crate::shared::avatar::*; + use crate::shared::icon_button::*; + use crate::shared::mentionable_text_input::MentionableTextInput; - mod.widgets.EditingContent = View { + EditingContent = { width: Fill, - height: Fit{max: FitBound.Rel{base: Base.Full, factor: 0.75}} - align: Align{x: 0.5, y: 1.0}, // centered horizontally, bottom-aligned - padding: Inset{ left: 20, right: 20, top: 10, bottom: 10 } - margin: Inset{top: 2} + height: Fit { max: Rel { base: Full, factor: 0.625 } } + align: {x: 0.5, y: 1.0}, // centered horizontally, bottom-aligned + padding: { left: 20, right: 20, top: 10, bottom: 10 } + margin: {top: 2} spacing: 10, flow: Down, show_bg: false // don't cover up the RoomInputBar - View { + { width: Fill, height: Fit flow: Right - align: Align{y: 0.5} - padding: Inset{left: 5, right: 5} + align: {y: 0.5} + padding: {left: 5, right: 5} - Label { +