Skip to content

Commit

Permalink
Added feature: Deferred props
Browse files Browse the repository at this point in the history
  • Loading branch information
mergehez committed Oct 10, 2024
1 parent 424d809 commit 0b81d41
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 11 deletions.
3 changes: 3 additions & 0 deletions InertiaNetCore/Inertia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public static class Inertia

public static LazyProp<T> Lazy<T>(Func<T?> callback) => _factory.Lazy(callback);
public static LazyProp<T> Lazy<T>(Func<Task<T?>> callback) => _factory.Lazy(callback);

public static DeferredProp<T> Defer<T>(Func<T?> callback, string? group = null) => _factory.Defer(callback, group);
public static DeferredProp<T> Defer<T>(Func<Task<T?>> callback, string? group = null) => _factory.Defer(callback, group);

public static AlwaysProp<T> Always<T>(Func<T?> callback) => _factory.Always(callback);
public static AlwaysProp<T> Always<T>(Func<Task<T?>> callback) => _factory.Always(callback);
Expand Down
11 changes: 6 additions & 5 deletions InertiaNetCore/Models/InertiaPage.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
namespace InertiaNetCore.Models;

public readonly record struct InertiaPage()
public readonly record struct InertiaPage
{
public InertiaProps Props { get; init; } = default!;
public string Component { get; init; } = default!;
public string? Version { get; init; } = null;
public string Url { get; init; } = default!;
public required InertiaProps Props { get; init; }
public required Dictionary<string, List<string>> DeferredProps { get; init; }
public required string Component { get; init; }
public required string? Version { get; init; }
public required string Url { get; init; }
}
2 changes: 1 addition & 1 deletion InertiaNetCore/Models/InertiaProps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal async Task<InertiaProps> ToProcessedProps(List<string>? partials)

foreach (var (key, value) in this)
{
if(partials is null && value is ILazyProp)
if(partials is null && value is IIgnoreFirstProp)
continue;

if(partials is not null && value is not IAlwaysProp && !partials.Contains(key, StringComparer.InvariantCultureIgnoreCase))
Expand Down
16 changes: 16 additions & 0 deletions InertiaNetCore/Response.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Text.Json;
using InertiaNetCore.Extensions;
using InertiaNetCore.Models;
using InertiaNetCore.Utils;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
Expand All @@ -21,6 +22,7 @@ public async Task ExecuteResultAsync(ActionContext context)
Version = version,
Url = context.HttpContext.RequestedUri(),
Props = await GetFinalProps(context),
DeferredProps = GetDeferredProps(context),
};

if (!context.HttpContext.IsInertiaRequest())
Expand Down Expand Up @@ -70,6 +72,20 @@ private async Task<InertiaProps> GetFinalProps(ActionContext context)
return finalProps;
}

private Dictionary<string, List<string>> GetDeferredProps(ActionContext context)
{
if (context.IsInertiaPartialComponent(component))
return [];

return props
.Where(prop => prop.Value is IDeferredProp)
.GroupBy(prop => (prop.Value as IDeferredProp)!.Group)
.ToDictionary(
g => g.Key ?? g.Select(x => x.Key).First(),
g => g.Select(x => x.Key).ToList()
);
}

private static Dictionary<string, string> GetErrors(ActionContext context)
{
var sessionErrors = context.HttpContext.Session.GetString("errors");
Expand Down
2 changes: 2 additions & 0 deletions InertiaNetCore/ResponseFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ public void Flash(string key, string? value)

public LazyProp<T> Lazy<T>(Func<T?> callback) => new(callback);
public LazyProp<T> Lazy<T>(Func<Task<T?>> callback) => new(callback);
public DeferredProp<T> Defer<T>(Func<T?> callback, string? group) => new(callback, group);
public DeferredProp<T> Defer<T>(Func<Task<T?>> callback, string? group) => new(callback, group);
public AlwaysProp<T> Always<T>(Func<T?> callback) => new(callback);
public AlwaysProp<T> Always<T>(Func<Task<T?>> callback) => new(callback);
}
20 changes: 20 additions & 0 deletions InertiaNetCore/Utils/DeferProp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace InertiaNetCore.Utils;

/// <summary>
/// Deferred props allow you to defer the loading of certain page data until after the initial page render.
/// This can be useful for improving the perceived performance of your app by allowing the initial page render to happen as quickly as possible.
/// </summary>
public class DeferredProp<T> : InvokableProp<T>, IDeferredProp
{
public string? Group { get; }

public DeferredProp(Func<T?> callback, string? group) : base(callback)
{
Group = group;
}

public DeferredProp(Func<Task<T?>> callbackAsync, string? group) : base(callbackAsync)
{
Group = group;
}
}
14 changes: 10 additions & 4 deletions InertiaNetCore/Utils/Interfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@

namespace InertiaNetCore.Utils;

public interface IViteBuilder
{
HtmlString ReactRefresh();
HtmlString Input(string path);
}

internal interface IInvokableProp
{
internal Task<object?> InvokeToObject();
}

internal interface IAlwaysProp;

internal interface ILazyProp;
internal interface IIgnoreFirstProp;

internal interface ILazyProp : IIgnoreFirstProp;

public interface IViteBuilder
internal interface IDeferredProp : IIgnoreFirstProp
{
HtmlString ReactRefresh();
HtmlString Input(string path);
string? Group { get; }
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,6 @@ export default defineConfig({

## Work in progress

- [ ] Deferred props
- [x] Deferred props
- [ ] Merging props
- [ ] History encryption

0 comments on commit 0b81d41

Please sign in to comment.