mirror of
https://github.com/alexhopeoconnor/dnsmasq-webui.git
synced 2026-10-18 18:01:41 +10:00
UI polish: update check tooltip date, expand/collapse icons, dialog JS
- NavMenu: show short date in update-check tooltip when last check was not today - Settings modal: expand/collapse all sections with bi-arrows-expand/collapse icons - Effective config: add Expand all button (bi-arrows-expand), same icon style as toolbar - Rename settings-modal.js to dialog.js; add config-option-help.js, JS extension helpers - Config option help modal and client settings/dialog wiring updates
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace DnsmasqWebUI.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Safe JS interop helpers that swallow disconnect/cancel/dispose exceptions.
|
||||
/// Use for best-effort or teardown calls; use raw InvokeVoidAsync/InvokeAsync when failure must propagate.
|
||||
/// </summary>
|
||||
public static class JSRuntimeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes a void JS function without throwing on circuit disconnect, cancel, or dispose.
|
||||
/// Returns true if the call succeeded, false otherwise.
|
||||
/// </summary>
|
||||
public static async ValueTask<bool> InvokeVoidAsyncSafe(
|
||||
this IJSRuntime js,
|
||||
string identifier,
|
||||
CancellationToken cancellationToken = default,
|
||||
params object?[]? args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var a = args ?? [];
|
||||
if (cancellationToken == default)
|
||||
await js.InvokeVoidAsync(identifier, a);
|
||||
else
|
||||
await js.InvokeVoidAsync(identifier, cancellationToken, a);
|
||||
return true;
|
||||
}
|
||||
catch (JSDisconnectedException) { return false; }
|
||||
catch (TaskCanceledException) { return false; }
|
||||
catch (ObjectDisposedException) { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a JS function that returns a value, without throwing on circuit disconnect, cancel, or dispose.
|
||||
/// Returns default when the call fails (e.g. circuit gone).
|
||||
/// </summary>
|
||||
public static async ValueTask<T?> InvokeAsyncSafe<T>(
|
||||
this IJSRuntime js,
|
||||
string identifier,
|
||||
CancellationToken cancellationToken = default,
|
||||
params object?[]? args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var a = args ?? [];
|
||||
if (cancellationToken == default)
|
||||
return await js.InvokeAsync<T>(identifier, a);
|
||||
return await js.InvokeAsync<T>(identifier, cancellationToken, a);
|
||||
}
|
||||
catch (JSDisconnectedException) { return default; }
|
||||
catch (TaskCanceledException) { return default; }
|
||||
catch (ObjectDisposedException) { return default; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user