Merge pull request #4255 from leptos-rs/4254

Revert recent broken changes
This commit is contained in:
Greg Johnston
2025-08-26 17:09:01 -04:00
committed by GitHub
5 changed files with 25 additions and 134 deletions

View File

@@ -1,18 +1,14 @@
use crate::{
children::ChildrenFn, component, control_flow::Show, show::IntoCondition,
IntoView,
};
use crate::{children::ChildrenFn, component, control_flow::Show, IntoView};
use core::time::Duration;
use leptos_dom::helpers::TimeoutHandle;
use leptos_macro::view;
use reactive_graph::{
diagnostics::SpecialNonReactiveZone,
effect::RenderEffect,
owner::{on_cleanup, StoredValue},
signal::RwSignal,
traits::{GetValue, Set, SetValue},
traits::{Get, GetUntracked, GetValue, Set, SetValue},
wrappers::read::Signal,
};
use std::marker::PhantomData;
use tachys::prelude::*;
/// A component that will show its children when the `when` condition is `true`.
@@ -50,16 +46,14 @@ use tachys::prelude::*;
/// }
/// # }
/// ```
///
/// Please note, that unlike `Show`, `AnimatedShow` does not support a `fallback` prop.
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
#[component]
pub fn AnimatedShow<M>(
pub fn AnimatedShow(
/// The components Show wraps
children: ChildrenFn,
/// When true the children are shown.
/// It accepts a closure that returns a boolean value as well as a boolean signal or plain boolean value.
when: impl IntoCondition<M>,
/// If the component should show or not
#[prop(into)]
when: Signal<bool>,
/// Optional CSS class to apply if `when == true`
#[prop(optional)]
show_class: &'static str,
@@ -68,26 +62,17 @@ pub fn AnimatedShow<M>(
hide_class: &'static str,
/// The timeout after which the component will be unmounted if `when == false`
hide_delay: Duration,
/// Marker for generic parameters. Ignore this.
#[prop(optional)]
_marker: PhantomData<M>,
) -> impl IntoView {
let when = when.into_condition();
// Silence warnings about using signals in non-reactive contexts.
#[cfg(debug_assertions)]
let z = SpecialNonReactiveZone::enter();
let handle: StoredValue<Option<TimeoutHandle>> = StoredValue::new(None);
let cls = RwSignal::new(if when.run() { show_class } else { hide_class });
let show = RwSignal::new(when.run());
#[cfg(debug_assertions)]
drop(z);
let cls = RwSignal::new(if when.get_untracked() {
show_class
} else {
hide_class
});
let show = RwSignal::new(when.get_untracked());
let eff = RenderEffect::new(move |_| {
if when.run() {
if when.get() {
// clear any possibly active timer
if let Some(h) = handle.get_value() {
h.clear();
@@ -115,8 +100,8 @@ pub fn AnimatedShow<M>(
});
view! {
<Show when=show>
<div class=cls>{children()}</div>
<Show when=move || show.get() fallback=|| ()>
<div class=move || cls.get()>{children()}</div>
</Show>
}
}

View File

@@ -27,7 +27,6 @@ pub fn AutoReload(
None => options.reload_port,
};
let protocol = match options.reload_ws_protocol {
leptos_config::ReloadWSProtocol::Auto => "null",
leptos_config::ReloadWSProtocol::WS => "'ws://'",
leptos_config::ReloadWSProtocol::WSS => "'wss://'",
};

View File

@@ -1,9 +1,4 @@
let host = window.location.hostname;
if (protocol === null) {
protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
}
let ws = new WebSocket(`${protocol}${host}:${reload_port}/live_reload`);
ws.onmessage = (ev) => {
let msg = JSON.parse(ev.data);

View File

@@ -1,71 +1,26 @@
use crate::{
children::{TypedChildrenFn, ViewFn},
prelude::{FunctionMarker, SignalMarker},
IntoView,
};
use leptos_macro::component;
use reactive_graph::{computed::ArcMemo, traits::Get};
use std::{marker::PhantomData, sync::Arc};
use tachys::either::Either;
/// Shows its children whenever the condition `when` prop is `true`.
/// Otherwise it renders the `fallback` prop, which defaults to the empty view.
///
/// The prop `when` can be a closure that returns a bool, a signal of type bool, or a boolean value.
///
/// ## Usage
///
/// ```
/// # use leptos::prelude::*;
/// #
/// # #[component]
/// # pub fn Demo() -> impl IntoView {
/// let (condition, set_condition) = signal(true);
///
/// view! {
/// <Show when=condition>
/// <p>"Hello, world!"</p>
/// </Show>
/// }
/// # }
/// ```
///
/// Or with a closure as the `when` condition:
///
/// ```
/// # use leptos::prelude::*;
/// #
/// # #[component]
/// # pub fn Demo() -> impl IntoView {
/// let (condition, set_condition) = signal(true);
///
/// view! {
/// <Show when=move || condition.get()>
/// <p>"Hello, world!"</p>
/// </Show>
/// }
/// # }
/// ```
#[component]
pub fn Show<M, C>(
pub fn Show<W, C>(
/// The children will be shown whenever the condition in the `when` closure returns `true`.
children: TypedChildrenFn<C>,
/// When true the children are shown, otherwise the fallback.
/// It accepts a closure that returns a boolean value as well as a boolean signal or plain boolean value.
when: impl IntoCondition<M>,
/// A closure that returns a bool that determines whether this thing runs
when: W,
/// A closure that returns what gets rendered if the when statement is false. By default this is the empty view.
#[prop(optional, into)]
fallback: ViewFn,
/// Marker for generic parameters. Ignore this.
#[prop(optional)]
_marker: PhantomData<M>,
) -> impl IntoView
where
W: Fn() -> bool + Send + Sync + 'static,
C: IntoView + 'static,
{
let when = when.into_condition();
let memoized_when = ArcMemo::new(move |_| when.run());
let memoized_when = ArcMemo::new(move |_| when());
let children = children.into_inner();
move || match memoized_when.get() {
@@ -73,44 +28,3 @@ where
false => Either::Right(fallback.run()),
}
}
/// A closure that returns a bool. Can be converted from a closure, a signal, or a boolean value.
pub struct Condition(Arc<dyn Fn() -> bool + Send + Sync + 'static>);
impl Condition {
/// Evaluates the condition and returns its result.
pub fn run(&self) -> bool {
(self.0)()
}
}
/// Trait to convert various types into a `Condition`.
/// Implemented for closures, signals, and boolean values.
pub trait IntoCondition<M> {
/// Does the conversion
fn into_condition(self) -> Condition;
}
impl<S> IntoCondition<SignalMarker> for S
where
S: Get<Value = bool> + Send + Sync + 'static,
{
fn into_condition(self) -> Condition {
Condition(Arc::new(move || self.get()))
}
}
impl<F> IntoCondition<FunctionMarker> for F
where
F: Fn() -> bool + Send + Sync + 'static,
{
fn into_condition(self) -> Condition {
Condition(Arc::new(self))
}
}
impl IntoCondition<Condition> for Condition {
fn into_condition(self) -> Condition {
self
}
}

View File

@@ -153,7 +153,7 @@ impl LeptosOptions {
None => None,
},
reload_ws_protocol: ws_from_str(
env_w_default("LEPTOS_RELOAD_WS_PROTOCOL", "auto")?.as_str(),
env_w_default("LEPTOS_RELOAD_WS_PROTOCOL", "ws")?.as_str(),
)?,
not_found_path: env_w_default("LEPTOS_NOT_FOUND_PATH", "/404")?
.into(),
@@ -283,24 +283,22 @@ impl TryFrom<String> for Env {
pub enum ReloadWSProtocol {
WS,
WSS,
Auto,
}
impl Default for ReloadWSProtocol {
fn default() -> Self {
Self::Auto
Self::WS
}
}
fn ws_from_str(input: &str) -> Result<ReloadWSProtocol, LeptosConfigError> {
let sanitized = input.to_lowercase();
match sanitized.as_ref() {
"auto" => Ok(ReloadWSProtocol::Auto),
"ws" | "WS" => Ok(ReloadWSProtocol::WS),
"wss" | "WSS" => Ok(ReloadWSProtocol::WSS),
_ => Err(LeptosConfigError::EnvVarError(format!(
"{input} is not a supported websocket protocol. Use only `auto`, \
`ws` or `wss`.",
"{input} is not a supported websocket protocol. Use only `ws` or \
`wss`.",
))),
}
}