Skip to content

Commit

Permalink
Merge pull request #15 from stavroskasidis/release/2.0
Browse files Browse the repository at this point in the history
Release/2.0
  • Loading branch information
stavroskasidis authored Jul 12, 2023
2 parents 447607a + 0cf2d8d commit ce606e5
Show file tree
Hide file tree
Showing 76 changed files with 2,776 additions and 889 deletions.
8 changes: 5 additions & 3 deletions BlazorDialog.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29123.89
# Visual Studio Version 17
VisualStudioVersion = 17.6.33829.357
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDialog", "BlazorDialog\BlazorDialog.csproj", "{D6A05A5B-2A9D-43A8-B949-272147D62E52}"
EndProject
Expand All @@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.gitattributes = .gitattributes
.gitignore = .gitignore
build.ps1 = build.ps1
Directory.Build.props = Directory.Build.props
global.json = global.json
README.md = README.md
EndProjectSection
EndProject
Expand All @@ -28,7 +30,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDialog.BlazorTestApp.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDialog.BlazorTestApp.Client", "TestApps\Wasm\BlazorDialog.BlazorTestApp.Client\BlazorDialog.BlazorTestApp.Client.csproj", "{90954557-FBC5-4942-AB51-828A4D00A3F1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorDialog.BlazorServerTestApp", "TestApps\Server\BlazorDialog.BlazorServerTestApp\BlazorDialog.BlazorServerTestApp.csproj", "{A8D3328C-CBCC-4EDE-88BB-F77FD113ACCC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorDialog.BlazorServerTestApp", "TestApps\Server\BlazorDialog.BlazorServerTestApp\BlazorDialog.BlazorServerTestApp.csproj", "{A8D3328C-CBCC-4EDE-88BB-F77FD113ACCC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
8 changes: 3 additions & 5 deletions BlazorDialog/BlazorDialog.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
<IsPackable>true</IsPackable>


Expand All @@ -16,7 +14,7 @@
<Copyright />
<PackageTags>blazor blazor-component blazor-dialog dialog modal blazor-modal blazordialog blazormodaldialog blazormodal razor razor-components razorcomponents</PackageTags>
<VersionSuffix>$(VersionSuffix)</VersionSuffix>
<Version>1.6.0</Version>
<Version>2.0.0</Version>
<Version Condition=" '$(VersionSuffix)' != '' ">$(Version)-$(VersionSuffix)</Version>
<Product>BlazorDialog</Product>
</PropertyGroup>
Expand All @@ -35,7 +33,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Components" Version="$(MSPackagesVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="$(MSPackagesVersion)" />
</ItemGroup>
</Project>
22 changes: 21 additions & 1 deletion BlazorDialog/BlazorDialogService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -24,6 +25,25 @@ public async Task HideDialog(string dialogId, object result)
await _blazorDialogStore.GetById(dialogId).Hide(result);
}

public Task ShowComponentAsDialog(ComponentAsDialogOptions options)
{
return ShowComponentAsDialog<object>(options);
}

public async Task<TResult> ShowComponentAsDialog<TResult>(ComponentAsDialogOptions options)
{
var id = Guid.NewGuid().ToString();
var tcs = new TaskCompletionSource();

await _blazorDialogStore.RegisterComponentDialog(id, new ComponentDialog
{
Options = options,
RenderTaskCompletionSource = tcs
});
await tcs.Task; //wait for dialog to render
return await ShowDialog<TResult>(id);
}

public async Task ShowDialog(string dialogId)
{
await ShowDialog<object>(dialogId, null);
Expand Down
32 changes: 31 additions & 1 deletion BlazorDialog/BlazorDialogStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Linq;
using System.Threading.Tasks;

namespace BlazorDialog
{
internal class BlazorDialogStore : IBlazorDialogStore
{
private Dictionary<string, Dialog> registeredDialogs = new Dictionary<string, Dialog>();
private Dictionary<string, ComponentDialog> registeredComponentDialogs = new Dictionary<string, ComponentDialog>();
public event Func<Task> OnComponentAsDialogsChanged;

public Dialog GetById(string id)
{
Expand All @@ -22,7 +25,8 @@ public Dialog GetById(string id)

public int GetVisibleDialogsCount()
{
return registeredDialogs.Count(x => x.Value.GetVisibility());
return registeredDialogs.Count(x => x.Value.GetVisibility()) +
registeredComponentDialogs.Count;
}

public void Register(Dialog blazorDialog)
Expand All @@ -34,12 +38,38 @@ public void Register(Dialog blazorDialog)
registeredDialogs[blazorDialog.Id] = blazorDialog;
}

public async Task RegisterComponentDialog(string id, ComponentDialog options)
{
registeredComponentDialogs[id] = options;
if(OnComponentAsDialogsChanged != null)
{
await OnComponentAsDialogsChanged.Invoke();
}
}

public void Unregister(Dialog blazorDialog)
{
if (blazorDialog.Id != null && registeredDialogs.ContainsKey(blazorDialog.Id))
{
registeredDialogs.Remove(blazorDialog.Id);
}
}

public async Task UnregisterComponentDialog(string id)
{
if(registeredComponentDialogs.ContainsKey(id))
{
registeredComponentDialogs.Remove(id);
if (OnComponentAsDialogsChanged != null)
{
await OnComponentAsDialogsChanged.Invoke();
}
}
}

public Dictionary<string, ComponentDialog> GetComponentsAsDialogs()
{
return registeredComponentDialogs;
}
}
}
15 changes: 15 additions & 0 deletions BlazorDialog/Components/Dialog.razor
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@
/// </summary>
[Parameter] public string CssClass { get; set; }

/// <summary>
/// An event that is triggered after the dialog renders.
/// </summary>
[Parameter] public EventCallback<bool> OnAfterRender { get; set; }

protected TaskCompletionSource<object> taskCompletionSource;
internal Action<object> OnDialogHide;
protected void NotifyDialogHidden(object result) => OnDialogHide?.Invoke(result);
Expand Down Expand Up @@ -284,4 +289,14 @@
{
return this.isShowing;
}


protected override Task OnAfterRenderAsync(bool firstRender)
{
if (OnAfterRender.HasDelegate)
{
OnAfterRender.InvokeAsync(firstRender);
}
return base.OnAfterRenderAsync(firstRender);
}
}
45 changes: 45 additions & 0 deletions BlazorDialog/Components/DialogOutput.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
@inject IBlazorDialogStore store
@namespace BlazorDialog
@implements IDisposable
@foreach (var dialog in store.GetComponentsAsDialogs())
{
if (!dialog.Value.Options.IsCustom)
{
<Dialog Id="@dialog.Key" @key="dialog.Key" Animation="dialog.Value.Options.Animation" BaseZIndex="dialog.Value.Options.BaseZIndex"
Centered="dialog.Value.Options.Centered" CssClass="@dialog.Value.Options.CssClass" Size="dialog.Value.Options.Size"
OnAfterRender="EventUtil.AsNonRenderingEventCallback((bool firstLoad) => OnAfterDialogRender(firstLoad, dialog))">
<DynamicComponent Type="dialog.Value.Options.ComponentType" Parameters="dialog.Value.Options.Parameters"></DynamicComponent>
</Dialog>
}
else
{
<Dialog Id="@dialog.Key" @key="dialog.Key" IsCustom="dialog.Value.Options.IsCustom" OnAfterRender="EventUtil.AsNonRenderingEventCallback((bool firstLoad) => OnAfterDialogRender(firstLoad, dialog))">
<DynamicComponent Type="dialog.Value.Options.ComponentType" Parameters="dialog.Value.Options.Parameters"></DynamicComponent>
</Dialog>
}
}

@code {
protected override void OnInitialized()
{
store.OnComponentAsDialogsChanged += Refresh;
}

public void Dispose()
{
store.OnComponentAsDialogsChanged -= Refresh;
}

protected async Task Refresh()
{
await InvokeAsync(StateHasChanged);
}

protected async Task OnAfterDialogRender(bool firstLoad, KeyValuePair<string,ComponentDialog> dialog)
{
if (firstLoad)
{
dialog.Value.RenderTaskCompletionSource.SetResult();
}
}
}
41 changes: 41 additions & 0 deletions BlazorDialog/EventUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BlazorDialog
{
//Source: https://gist.github.com/SteveSandersonMS/8a19d8e992f127bb2d2a315ec6c5a373
//Issue: https://github.com/dotnet/aspnetcore/issues/18919
internal static class EventUtil
{
// The repetition in here is because of the four combinations of handlers (sync/async * with/without arg)
public static Action AsNonRenderingEventHandler(Action callback)
=> new SyncReceiver(callback).Invoke;
public static Action<TValue> AsNonRenderingEventHandler<TValue>(Action<TValue> callback)
=> new SyncReceiver<TValue>(callback).Invoke;
public static Func<Task> AsNonRenderingEventHandler(Func<Task> callback)
=> new AsyncReceiver(callback).Invoke;
public static Func<TValue, Task> AsNonRenderingEventHandler<TValue>(Func<TValue, Task> callback)
=> new AsyncReceiver<TValue>(callback).Invoke;
public static EventCallback AsNonRenderingEventCallback(Action callback) => new(new ReceiverBase(), callback);
public static EventCallback<T> AsNonRenderingEventCallback<T>(Action<T> callback) => new(new ReceiverBase(), callback);
public static EventCallback AsNonRenderingEventCallback(Func<Task> callback) => new(new ReceiverBase(), callback);
public static EventCallback<T> AsNonRenderingEventCallback<T>(Func<T, Task> callback) => new(new ReceiverBase(), callback);

record SyncReceiver(Action callback) : ReceiverBase { public void Invoke() => callback(); }
record SyncReceiver<T>(Action<T> callback) : ReceiverBase { public void Invoke(T arg) => callback(arg); }
record AsyncReceiver(Func<Task> callback) : ReceiverBase { public Task Invoke() => callback(); }
record AsyncReceiver<T>(Func<T, Task> callback) : ReceiverBase { public Task Invoke(T arg) => callback(arg); }

// By implementing IHandleEvent, we can override the event handling logic on a per-handler basis
// The logic here just calls the callback without triggering any re-rendering
record ReceiverBase : IHandleEvent
{
public Task HandleEventAsync(EventCallbackWorkItem item, object arg) => item.InvokeAsync(arg);
}

}
}
7 changes: 6 additions & 1 deletion BlazorDialog/IBlazorDialogService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using System;
using System.Threading.Tasks;

namespace BlazorDialog
{
Expand All @@ -10,5 +12,8 @@ public interface IBlazorDialogService
Task ShowDialog(string dialogId, object input);
Task<TResult> ShowDialog<TResult>(string dialogId);
Task<TResult> ShowDialog<TResult>(string dialogId, object input);

Task ShowComponentAsDialog(ComponentAsDialogOptions options);
Task<TResult> ShowComponentAsDialog<TResult>(ComponentAsDialogOptions options);
}
}
66 changes: 65 additions & 1 deletion BlazorDialog/IBlazorDialogStore.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,79 @@
using System;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace BlazorDialog
{
public class ComponentAsDialogOptions
{
public ComponentAsDialogOptions(Type componentType)
{
ComponentType = componentType;
}

/// <summary>
/// The type of the rendered component
/// </summary>
public Type ComponentType { get; protected set; }

/// <summary>
/// The parameters of the rendered component.
/// </summary>
public Dictionary<string, object> Parameters { get; set; } = new();

/// <summary>
/// If set to true then all default html/css is removed. Use when custom dialog implementations are needed.
/// </summary>
public bool IsCustom { get; set; }

/// <summary>
/// Allows you to change the appearing animation. Ignored when the dialog is <see cref="Dialog.IsCustom" />.
/// </summary>
public DialogAnimation Animation { get; set; } = DialogAnimation.None;

/// <summary>
/// The base z-index of the dialog when shown. Default: 1050
/// </summary>
public int BaseZIndex { get; set; } = 1050;

/// <summary>
/// Allows you to set the positioning of the dialog from the top. Ignored when the dialog is <see cref="Dialog.IsCustom" />.
/// </summary>
public bool Centered { get; set; }

/// <summary>
/// Adds a custom css class to the wrapper of the dialog.
/// </summary>
public string? CssClass { get; set; }

/// <summary>
/// Allows you to set the dialog size. Ignored when the dialog is <see cref="Dialog.IsCustom" />.
/// </summary>
public DialogSize Size { get; set; } = DialogSize.Normal;
}

public class ComponentDialog
{
public ComponentAsDialogOptions Options { get; set; }
public TaskCompletionSource RenderTaskCompletionSource { get; set; }
}

public interface IBlazorDialogStore
{

void Register(Dialog blazorDialog);
void Unregister(Dialog blazorDialog);
Dialog GetById(string id);
int GetVisibleDialogsCount();

Task RegisterComponentDialog(string id, ComponentDialog compDialog);
Task UnregisterComponentDialog(string id);

Dictionary<string, ComponentDialog> GetComponentsAsDialogs();

event Func<Task> OnComponentAsDialogsChanged;

}
}
1 change: 1 addition & 0 deletions BlazorDialog/_Imports.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
Loading

0 comments on commit ce606e5

Please sign in to comment.