You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.4 KiB
106 lines
3.4 KiB
// Copyright (c) MudBlazor 2021
|
|
// MudBlazor licenses this file to you under the MIT license.
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using Microsoft.AspNetCore.Components.Web;
|
|
using Microsoft.JSInterop;
|
|
|
|
namespace Connected.Services;
|
|
|
|
/// <summary>
|
|
/// This transient service binds itself to a parent element to observe the keys of one of its children.
|
|
/// It can call preventDefault or stopPropagation directly on the JavaScript side for single key strokes / key combinations as per configuration.
|
|
/// Furthermore, you can precisely subscribe single keystrokes or combinations and only the subscribed ones will be forwarded into .NET
|
|
/// </summary>
|
|
public class KeyInterceptor : IKeyInterceptor, IDisposable
|
|
{
|
|
private bool _isDisposed = false;
|
|
|
|
private readonly DotNetObjectReference<KeyInterceptor> _dotNetRef;
|
|
private readonly IJSRuntime _jsRuntime;
|
|
private bool _isObserving;
|
|
private string _elementId;
|
|
|
|
[DynamicDependency(nameof(OnKeyDown))]
|
|
[DynamicDependency(nameof(OnKeyUp))]
|
|
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(KeyboardEvent))]
|
|
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(KeyboardEventArgs))]
|
|
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(KeyOptions))]
|
|
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(KeyInterceptorOptions))]
|
|
public KeyInterceptor(IJSRuntime jsRuntime)
|
|
{
|
|
_dotNetRef = DotNetObjectReference.Create(this);
|
|
_jsRuntime = jsRuntime;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Connect to the ancestor element of the element(s) that should be observed
|
|
/// </summary>
|
|
/// <param name="elementId">Ancestor html element id</param>
|
|
/// <param name="options">Define here the descendant(s) by setting TargetClass and the keystrokes to be monitored / suppressed</param>
|
|
public async Task Connect(string elementId, KeyInterceptorOptions options)
|
|
{
|
|
if (_isObserving || _isDisposed)
|
|
return;
|
|
_elementId = elementId;
|
|
_isObserving = await _jsRuntime.InvokeVoidAsyncWithErrorHandling("mudKeyInterceptor.connect", _dotNetRef, elementId, options);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update behavior of a registered keyoption
|
|
/// The keystrike to update has to be monitored previously
|
|
/// </summary>
|
|
/// <param name="option">Define KeyOption to update</param>
|
|
public async Task UpdateKey(KeyOptions option)
|
|
{
|
|
await _jsRuntime.InvokeVoidAsync($"mudKeyInterceptor.updatekey", _elementId, option);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disconnect from the previously connected ancestor and its descendants
|
|
/// </summary>
|
|
public async Task Disconnect()
|
|
{
|
|
try
|
|
{
|
|
await _jsRuntime.InvokeVoidAsync($"mudKeyInterceptor.disconnect", _elementId);
|
|
}
|
|
catch (Exception) { /*ignore*/ }
|
|
_isObserving = false;
|
|
}
|
|
|
|
[JSInvokable]
|
|
public void OnKeyDown(KeyboardEventArgs args)
|
|
{
|
|
KeyDown?.Invoke(args);
|
|
}
|
|
|
|
[JSInvokable]
|
|
public void OnKeyUp(KeyboardEventArgs args)
|
|
{
|
|
KeyUp?.Invoke(args);
|
|
}
|
|
|
|
public event KeyboardEvent KeyDown;
|
|
public event KeyboardEvent KeyUp;
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (!disposing || _isDisposed)
|
|
return;
|
|
_isDisposed = true;
|
|
KeyDown = null;
|
|
KeyUp = null;
|
|
Disconnect().AndForget();
|
|
_dotNetRef.Dispose();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
}
|