Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/marc2332/freya
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 committed Jan 31, 2025
2 parents 999543a + e682a2f commit 6fd2961
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 4 deletions.
4 changes: 2 additions & 2 deletions crates/components/src/scroll_views/scroll_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use freya_elements::{
use freya_hooks::{
use_applied_theme,
use_focus,
use_node,
use_node_from_signal,
ScrollBarThemeWith,
};

Expand Down Expand Up @@ -150,7 +150,7 @@ pub fn ScrollView(
let mut scroll_controller =
scroll_controller.unwrap_or_else(|| use_scroll_controller(ScrollConfig::default));
let (mut scrolled_x, mut scrolled_y) = scroll_controller.into();
let (node_ref, size) = use_node();
let (node_ref, size) = use_node_from_signal(|| scroll_controller.layout());

let mut focus = use_focus();
let applied_scrollbar_theme = use_applied_theme!(&scrollbar_theme, scroll_bar);
Expand Down
7 changes: 7 additions & 0 deletions crates/components/src/scroll_views/use_scroll_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use dioxus::prelude::{
Writable,
WritableVecExt,
};
use freya_common::NodeReferenceLayout;

#[derive(Default, PartialEq, Eq)]
pub enum ScrollPosition {
Expand Down Expand Up @@ -57,6 +58,7 @@ pub struct ScrollController {
requests: Signal<Vec<ScrollRequest>>,
x: Signal<i32>,
y: Signal<i32>,
layout: Signal<NodeReferenceLayout>,
}

impl From<ScrollController> for (Signal<i32>, Signal<i32>) {
Expand All @@ -72,6 +74,7 @@ impl ScrollController {
y: Signal::new(y),
requests_subscribers: Signal::new(HashSet::new()),
requests: Signal::new(initial_requests),
layout: Signal::default(),
}
}

Expand All @@ -83,6 +86,10 @@ impl ScrollController {
self.y
}

pub fn layout(&self) -> Signal<NodeReferenceLayout> {
self.layout
}

pub fn use_apply(&mut self, width: f32, height: f32) {
let scope_id = current_scope_id().unwrap();

Expand Down
9 changes: 7 additions & 2 deletions crates/hooks/src/use_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ use tokio::sync::watch::channel;

/// Subscribe to a Node layout changes.
pub fn use_node() -> (AttributeValue, NodeReferenceLayout) {
use_node_from_signal(Signal::default)
}

pub fn use_node_from_signal(
init: impl FnOnce() -> Signal<NodeReferenceLayout>,
) -> (AttributeValue, NodeReferenceLayout) {
let (tx, signal) = use_hook(|| {
let (tx, mut rx) = channel::<NodeReferenceLayout>(NodeReferenceLayout::default());
let mut signal = Signal::new(NodeReferenceLayout::default());

let mut signal = init();
spawn(async move {
while rx.changed().await.is_ok() {
if *signal.peek() != *rx.borrow() {
Expand Down
80 changes: 80 additions & 0 deletions examples/infinite_list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]

use freya::prelude::*;
use reqwest::Url;
use serde::Deserialize;

fn main() {
launch_with_props(app, "Infinite List of Dogs", (500.0, 800.0));
}

async fn fetch_random_dog() -> Option<Url> {
#[derive(Deserialize)]
struct DogApiResponse {
message: String,
}

let res = reqwest::get("https://dog.ceo/api/breeds/image/random")
.await
.ok()?;
let data = res.json::<DogApiResponse>().await.ok()?;
data.message.parse().ok()
}

fn app() -> Element {
let scroll_controller = use_scroll_controller(ScrollConfig::default);
let mut cards = use_signal(|| 5);

use_effect(move || {
let y = scroll_controller.y();
let layout = scroll_controller.layout();
let y = y.read();
let layout = layout.read();
let end = layout.inner.height - layout.area.height();
const MARGIN: i32 = 50;
if -*y > end as i32 - MARGIN {
*cards.write() += 1;
}
});

rsx!(
ScrollView {
scroll_controller,
spacing: "8",
padding: "8",
for i in 0..cards() {
rect {
key: "{i}",
width: "100%",
spacing: "8",
direction: "horizontal",
RandomImage {}
RandomImage {}
}
}
}
)
}

#[component]
fn RandomImage() -> Element {
let url = use_resource(|| async move { fetch_random_dog().await });

rsx!(
rect {
width: "50%",
height: "300",
overflow: "clip",
corner_radius: "8",
if let Some(url) = url.read().clone().flatten() {
NetworkImage {
aspect_ratio: "max",
url
}
}
}
)
}

0 comments on commit 6fd2961

Please sign in to comment.