Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,25 @@

namespace CodeCasa.AutomationPipelines.Lights.Nodes;

internal class TurnOffThenPassThroughNode : PipelineNode<LightTransition>
/// <summary>
/// A pipeline node that initially outputs <see cref="LightTransition.Off()"/>,
/// then switches to pass-through mode after receiving its first input.
/// </summary>
/// <remarks>
/// This node is useful for scenarios where a light should be turned off,
/// but then forward subsequent inputs from upstream nodes without modification.
/// The pass-through behavior is activated upon receiving the first input.
/// </remarks>
public sealed class TurnOffThenPassThroughNode : PipelineNode<LightTransition>
{
/// <summary>
/// Initializes a new instance of the <see cref="TurnOffThenPassThroughNode"/> class.
/// </summary>
/// <remarks>
/// The initial output is set to <see cref="LightTransition.Off()"/>.
/// Pass-through mode is not enabled in the constructor because the input
/// is immediately set when this node is added to the timeline.
/// </remarks>
public TurnOffThenPassThroughNode()
{
// Note: we cannot simply call ChangeOutputAndTurnOnPassThroughOnNextInput here, as the input will immediately be set when this node is added to the timeline.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ public ILightTransitionReactiveNodeConfigurator<TLight> AddUncoupledDimmer(IDimm
}
return this;


}

/// <inheritdoc/>
public ILightTransitionReactiveNodeConfigurator<TLight> AddNodeSource<TNodeSource>()
where TNodeSource : IObservable<Func<IServiceProvider, IPipelineNode<LightTransition>?>>
{
configurators.Values.ForEach(c => c.AddNodeSource<TNodeSource>());
return this;
}

/// <inheritdoc/>
public ILightTransitionReactiveNodeConfigurator<TLight> AddNodeSource(
Func<IServiceProvider, IObservable<Func<IServiceProvider, IPipelineNode<LightTransition>?>>> nodeFactorySourceFactory)
{
configurators.Values.ForEach(c => c.AddNodeSource(nodeFactorySourceFactory));
return this;
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ public partial interface ILightTransitionReactiveNodeConfigurator<TLight> where
/// <returns>The configurator instance for method chaining.</returns>
ILightTransitionReactiveNodeConfigurator<TLight> AddUncoupledDimmer(IDimmer dimmer, Action<DimmerOptions> dimOptions);

/// <summary>
/// Adds a dynamic node source resolved from the service provider.
/// The node source type must implement <see cref="IObservable{T}"/> where T is a factory function for creating pipeline nodes.
/// Useful for reusable, class-based node sources registered in dependency injection.
/// </summary>
/// <typeparam name="TNodeSource">The type of the node source, which must be an observable that emits node factory functions.</typeparam>
/// <returns>The configurator instance for method chaining.</returns>
ILightTransitionReactiveNodeConfigurator<TLight> AddNodeSource<TNodeSource>()
where TNodeSource : IObservable<Func<IServiceProvider, IPipelineNode<LightTransition>?>>;

/// <summary>
/// Adds a dynamic node source created by a factory function that receives the service provider.
/// Useful for extension methods that need to compose existing DI services to build the observable.
/// </summary>
/// <param name="nodeFactorySourceFactory">A factory function that receives the service provider and returns an observable that emits node factory functions.</param>
/// <returns>The configurator instance for method chaining.</returns>
ILightTransitionReactiveNodeConfigurator<TLight> AddNodeSource(
Func<IServiceProvider, IObservable<Func<IServiceProvider, IPipelineNode<LightTransition>?>>> nodeFactorySourceFactory);

/// <summary>
/// Adds a dynamic node source that activates a new node in the reactive node each time the observable emits a factory.
/// The emitted factory is invoked to create and activate the new pipeline node.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,20 @@ public ILightTransitionReactiveNodeConfigurator<TLight> AddNodeSource(IObservabl
return this;
}

/// <inheritdoc/>
public ILightTransitionReactiveNodeConfigurator<TLight> AddNodeSource<TNodeSource>()
where TNodeSource : IObservable<Func<IServiceProvider, IPipelineNode<LightTransition>?>>
{
return AddNodeSource(ActivatorUtilities.CreateInstance<TNodeSource>(ServiceProvider));
}

/// <inheritdoc/>
public ILightTransitionReactiveNodeConfigurator<TLight> AddNodeSource(
Func<IServiceProvider, IObservable<Func<IServiceProvider, IPipelineNode<LightTransition>?>>> nodeFactorySourceFactory)
{
return AddNodeSource(nodeFactorySourceFactory(ServiceProvider));
}

/// <inheritdoc/>
public ILightTransitionReactiveNodeConfigurator<TLight> AddNodeSource(IObservable<Func<IServiceProvider, IPipelineNode<LightTransition>?>> nodeFactorySource)
{
Expand Down