Skip to content

Commit

Permalink
feat: use_window_size (#34)
Browse files Browse the repository at this point in the history
* progress: web implementation

* feat: desktop, initial size

* fix: rustfmt

* fix: clippy

* feat: documentation

* revision: derive debug

Co-authored-by: Marc Espin <[email protected]>

---------

Co-authored-by: Marc Espin <[email protected]>
  • Loading branch information
DogeDark and marc2332 authored Apr 19, 2024
1 parent 1feacd3 commit 57c6ff6
Show file tree
Hide file tree
Showing 13 changed files with 259 additions and 11 deletions.
7 changes: 5 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@
"rust-analyzer.cargo.features": [
"desktop-testing"
],
"rust-analyzer.cargo.extraArgs": ["--exclude=color_scheme"]
}
"rust-analyzer.cargo.extraArgs": [
"--exclude=color_scheme"
],
//"rust-analyzer.cargo.target": "wasm32-unknown-unknown",
}
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
resolver = "2"
members = ["sdk", "examples/*"]


[workspace.dependencies]
dioxus-sdk = { path = "./sdk" }
dioxus = { version = "0.5" }
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- [x] i18n
- [x] Utility Hooks
- [x] use_channel
- [x] use_window_size
- [ ] use_interval
- [ ] Camera
- [ ] WiFi
Expand Down
2 changes: 1 addition & 1 deletion examples/channel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
dioxus-sdk = { workspace = true, features = ["utils"] }
dioxus-sdk = { workspace = true, features = ["channel"] }
dioxus = { workspace = true, features = ["web"] }


Expand Down
14 changes: 14 additions & 0 deletions examples/use_window_size/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "use_window_size"
version = "0.1.0"
edition = "2021"

[dependencies]
dioxus-sdk = { workspace = true, features = ["use_window_size"] }
dioxus = { workspace = true }

[features]
web = ["dioxus/web"]
desktop = ["dioxus/desktop"]


7 changes: 7 additions & 0 deletions examples/use_window_size/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# use_window_size

Learn how to use `use_window_size`.

Run:

```dioxus serve```
Binary file added examples/use_window_size/public/favicon.ico
Binary file not shown.
24 changes: 24 additions & 0 deletions examples/use_window_size/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use dioxus::prelude::*;
use dioxus_sdk::utils::window::{get_window_size, use_window_size};

fn main() {
launch(app);
}

fn app() -> Element {
let initial_size = use_signal(get_window_size);
let window_size = use_window_size();

rsx!(
div { style: "text-align: center;",
h1 { "↕️ Window Size Utilities ↔️" }
h3 { "Initial Size" }
p { "Width: {initial_size().width}" }
p { "Height: {initial_size().height}" }

h3 { "Current Size" }
p { "Width: {window_size.width}" }
p { "Height: {window_size.height}" }
}
)
}
39 changes: 33 additions & 6 deletions sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ categories = ["multimedia", "os", "wasm"]
# # # # # # #

[features]
utils = ["dep:async-broadcast", "uuid/v4"]
clipboard = ["dep:copypasta"]
notifications = ["dep:notify-rust"]
geolocation = [
Expand All @@ -42,6 +41,18 @@ color_scheme = [
"dep:wasm-bindgen",
"dep:wasm-bindgen-futures",
]
use_window_size = [
# Shared
"dep:futures-util",

# Desktop
"dep:dioxus-desktop",

# Wasm
"web-sys/Window",
"dep:wasm-bindgen",
]
channel = ["dep:async-broadcast", "uuid/v4"]
i18n = [
# Shared
"dep:serde",
Expand Down Expand Up @@ -70,8 +81,21 @@ storage = [
]

# CI testing
wasm-testing = ["geolocation", "color_scheme", "utils", "i18n"]
desktop-testing = ["clipboard", "notifications", "geolocation", "utils", "i18n"]
wasm-testing = [
"geolocation",
"color_scheme",
"channel",
"use_window_size",
"i18n",
]
desktop-testing = [
"clipboard",
"notifications",
"geolocation",
"channel",
"use_window_size",
"i18n",
]


# # # # # # # # # # # # # # #
Expand All @@ -89,7 +113,7 @@ copypasta = { version = "0.8.2", optional = true }
notify-rust = { version = "4.8.0", optional = true }


# Used by: utils
# Used by: channel
uuid = { version = "1.3.2", optional = true }
async-broadcast = { version = "0.5.1", optional = true }

Expand Down Expand Up @@ -129,22 +153,25 @@ windows = { version = "0.48.0", optional = true }

[target.'cfg(target_family = "wasm")'.dependencies]

# Used by: color_scheme, geolocation
# Used by: color_scheme, geolocation, use_window_size
web-sys = { version = "0.3.60", optional = true }
wasm-bindgen = { version = "0.2.87", optional = true }
wasm-bindgen-futures = { version = "0.4.35", optional = true }

# Used by: Geolocation
js-sys = "0.3.62"

# Used by: utils
# Used by: channel
uuid = { version = "1.3.2", features = ["js"] }


[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# Used by: storage
directories = { version = "4.0.1", optional = true }

# Used by: use_window_size
dioxus-desktop = { workspace = true, optional = true }

# # # # #
# Docs. #
# # # # #
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ cfg_if::cfg_if! {
}

cfg_if::cfg_if! {
if #[cfg(any(feature = "utils"))] {
if #[cfg(any(feature = "channel", feature = "use_window_size"))] {
pub mod utils;
}
}
Expand Down
2 changes: 2 additions & 0 deletions sdk/src/utils/channel/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Channels for moving data around your app.

mod use_channel;
mod use_listen_channel;

Expand Down
14 changes: 13 additions & 1 deletion sdk/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
pub mod channel;
//! A variety of utility functions and hooks.

cfg_if::cfg_if! {
if #[cfg(feature = "channel")] {
pub mod channel;
}
}

cfg_if::cfg_if! {
if #[cfg(feature = "use_window_size")] {
pub mod window;
}
}
157 changes: 157 additions & 0 deletions sdk/src/utils/window.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
//! Utilities for the window.

use dioxus::prelude::*;
use futures_util::stream::StreamExt;
use std::sync::Once;

#[allow(dead_code)]
static INIT: Once = Once::new();

/// Stores the width and height of a window, screen, or viewport.
#[derive(Clone, Copy, Debug)]
pub struct WindowSize {
/// The horizontal size in pixels.
pub width: u32,
/// The vertical size in pixels.
pub height: u32,
}

/// A hook for receiving the size of the Window.
///
/// The initial window size will be returned with this hook and
/// updated continously as the window is resized.
///
/// # Example
///
/// ```rust
/// use dioxus::prelude::*;
/// use dioxus_sdk::utils::window::use_window_size;
///
/// fn App() -> Element {
/// let size = use_window_size();
///
/// rsx! {
/// p { "Width: {size.width}" }
/// p { "Height: {size.height}" }
/// }
/// }
/// ```
pub fn use_window_size() -> WindowSize {
let mut window_size = use_signal(get_window_size);

// Initialize the handler
let tx = use_coroutine(|mut rx: UnboundedReceiver<WindowSize>| async move {
while let Some(data) = rx.next().await {
window_size.set(data);
}
});

listen(tx);

*window_size.read_unchecked()
}

// Listener for the web implementation.
#[cfg(target_arch = "wasm32")]
fn listen(tx: Coroutine<WindowSize>) {
use wasm_bindgen::{closure::Closure, JsCast, JsValue};

INIT.call_once(|| {
let window = web_sys::window().expect("no wasm window found; are you in wasm?");
let window2 = window.clone();

// We will fail silently for conversion errors.
let on_resize = Closure::wrap(Box::new(move || {
let height = window2
.inner_height()
.unwrap_or(JsValue::from_f64(0.0))
.as_f64()
.unwrap_or(0.0) as u32;

let width = window2
.inner_width()
.unwrap_or(JsValue::from_f64(0.0))
.as_f64()
.unwrap_or(0.0) as u32;

tx.send(WindowSize { width, height });
}) as Box<dyn FnMut()>);

let on_resize_cb = on_resize.as_ref().clone();
on_resize.forget();
window.set_onresize(Some(on_resize_cb.unchecked_ref()));
});
}

// Listener for anything but the web implementation.
#[cfg(not(target_arch = "wasm32"))]
fn listen(tx: Coroutine<WindowSize>) {
use dioxus_desktop::{tao::event::Event, use_wry_event_handler, WindowEvent};

use_wry_event_handler(move |event, _| {
if let Event::WindowEvent {
event: WindowEvent::Resized(size),
..
} = event
{
tx.send(WindowSize {
width: size.width,
height: size.height,
});
}
});
}

/// Get the size of the current window.
///
/// This function will return the current size of the window.
///
/// ```rust
/// use dioxus::prelude::*;
/// use dioxus_sdk::utils::window::get_window_size;
///
/// fn App() -> Element {
/// let size = use_signal(get_window_size);
///
/// rsx! {
/// p { "Width: {size().width}" }
/// p { "Height: {size().height}" }
/// }
/// }
/// ```
pub fn get_window_size() -> WindowSize {
get_window_size_platform()
}

// Web implementation of size getter.
#[cfg(target_arch = "wasm32")]
fn get_window_size_platform() -> WindowSize {
use wasm_bindgen::JsValue;
let window = web_sys::window().expect("no wasm window found; are you in wasm?");

// We will fail silently for conversion errors.
let height = window
.inner_height()
.unwrap_or(JsValue::from_f64(0.0))
.as_f64()
.unwrap_or(0.0) as u32;

let width = window
.inner_width()
.unwrap_or(JsValue::from_f64(0.0))
.as_f64()
.unwrap_or(0.0) as u32;

WindowSize { width, height }
}

// Desktop implementation of size getter.
#[cfg(not(target_arch = "wasm32"))]
fn get_window_size_platform() -> WindowSize {
let window = dioxus_desktop::window();
let size = window.inner_size();
WindowSize {
width: size.width,
height: size.height,
}
}

0 comments on commit 57c6ff6

Please sign in to comment.