Skip to content

Here is the fix for dioxus 0.5. I don't use GitLab and am unfamiliar with its interface. Please update

Hi, I would do a merge request but am unfamiliar with GitLab. Here are the fixes for making it compatible with dioxus 0.5, which introduced quite a few breaking changes. The change that breaks Sir is mainly that they got rid of the Scope for the user and are operating it behind the scenes. Also, the render! macro has been deprecated and they moved to using signals for state management.

dioxus_components.rs

use crate::DEFAULT_CSS_COLLECTION;
use dioxus::prelude::*;
use once_cell::sync::Lazy;

use std::collections::HashMap;

use std::sync::{Arc, Mutex};

#[derive(Clone)]
struct StyleListeners(Arc<Mutex<StyleListenersInner>>);

impl StyleListeners {
    fn new() -> Self {
        Self(Arc::new(Mutex::new(StyleListenersInner::new())))
    }
}

struct StyleListenersInner {
    listeners: HashMap<ScopeId, Arc<dyn Fn() + Send + Sync + 'static>>,
}

impl StyleListenersInner {
    fn new() -> Self {
        StyleListenersInner {
            listeners: HashMap::new(),
        }
    }
}

static STYLE_LISTENERS: Lazy<StyleListeners> = Lazy::new(|| StyleListeners::new());

#[derive(Clone)]
struct StyleListener {
    listeners: StyleListeners,
    id: ScopeId,
}

impl StyleListener {
    fn register(
        listeners: StyleListeners,
        id: ScopeId,
        update: Arc<dyn Fn() + Send + Sync + 'static>,
    ) -> Self {
        {
            let mut lock = listeners.0.lock().expect("Could not acquire lock");
            lock.listeners.insert(id, update);
        }

        Self { listeners, id }
    }
}

impl Drop for StyleListener {
    fn drop(&mut self) {
        let mut lock = self.listeners.0.lock().expect("Could not acquire lock");
        lock.listeners.remove(&self.id);
    }
}

/// Registers a style listener – whenever style listeners will be notified, the component will be re-rendered.
fn use_style_listener() {
    let _listener = use_hook(|| {
        StyleListener::register(
            (*STYLE_LISTENERS).clone(),
            current_scope_id().unwrap(),
            schedule_update(),
        )
    });
}

#[doc(hidden)]
pub fn notify_dioxus_listeners() {
    let lock = STYLE_LISTENERS.0.lock().expect("Could not acquire lock");

    for update_fn in lock.listeners.values() {
        (update_fn)();
    }
}

/// A Dioxus component that renders the app's CSS in a `<style>` element.
///
/// (The CSS will come from the `css!` and `global_css!` macros throughout your app)
///
/// The element will be rendered in place. While it would technically be better to keep styles in the `<head>`, putting it elsewhere [is probably fine](https://softwareengineering.stackexchange.com/questions/224422/will-it-be-a-wrong-idea-to-have-style-in-body)
///
/// Example:
/// ```
/// use dioxus::prelude::*;
/// use sir::AppStyle;
///
/// fn App() -> Element {
///     rsx!(AppStyle {})
/// }
/// ```
#[allow(non_snake_case)]
pub fn AppStyle() -> Element {
    let css = DEFAULT_CSS_COLLECTION.get_css();

    use_style_listener();

    // putting style element wherever is probably fine
    // https://softwareengineering.stackexchange.com/questions/224422/will-it-be-a-wrong-idea-to-have-style-in-body
    rsx!( style { "{css}" } )
}

example/dioxus_counter.rs

#![allow(non_snake_case)]

use dioxus::prelude::*;
use sir::{css, global_css, AppStyle};

fn main() {
    dioxus_desktop::launch(App);
}

fn App() -> Element {
    rsx!(
        AppStyle {}
        Counter {}
    )
}

fn Counter() -> Element {
    let mut count = use_signal(|| 0);

    global_css!(
        "
        body {
            background: slategray;
        }
    "
    );

    let container = css!(
        "
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 4px;
    "
    );

    let title = css!("color: white");

    let button = css!(
        "
        border: none;
        padding: 8px 16px;
        border-radius: 4px;
        
        background: deepskyblue;
        transition: background 0.2s ease-out;

        &:hover {
            background: aquamarine;
        }
    "
    );

    rsx!(
        div {
            class: "{container}",
            h1 {
                class: "{title}",
                "Counter: {count}"
            }
            button {
                class: "{button}",
                onclick: move |_| count += 1,
                "Increment"
            }
            button {
                class: "{button}",
                onclick: move |_| count -= 1,
                "Decrement"
            }
        }
    )
}

Cargo.toml

# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.

[package]
edition = "2021"
name = "sir"
version = "0.5.0"
authors = ["Reinis Mazeiks"]
description = "Write SCSS in your component functions"
documentation = "https://docs.rs/sir/latest/sir/"
readme = "Readme.md"
keywords = [
    "css",
    "scss",
    "style",
    "dioxus",
]
categories = [
    "gui",
    "web-programming",
]
license = "MIT OR Apache-2.0"
repository = "https://gitlab.com/dawn_app/sir"

[package.metadata.docs.rs]
features = ["dioxus"]

[[example]]
name = "dioxus_counter"
path = "examples/dioxus_counter.rs"

[dependencies.dioxus]
version = "0.5"
optional = true

[dependencies.once_cell]
version = "1.10.0"

[dependencies.sir-macro]
version = "0.3.0"

[dev-dependencies.dioxus]
version = "0.5"

[dev-dependencies.dioxus-desktop]
version = "0.5"

Note that this was updated from the Sir 0.3 source. I have been maintaining a local copy for myself. Unsure if there were other updates in Sir 0.4 other than changing the dependency version of dioxus. If so, please integrate.

Again, sorry for not doing this as a merge request >.<

Edited by Jasen Kruger