Browse Source

Move all text input to the InputHelperInterop

pull/8963/head
Benedikt Stebner 3 years ago
parent
commit
2e0103a9db
  1. 2
      src/Web/Avalonia.Web.Blazor/AvaloniaView.razor
  2. 38
      src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs
  3. 55
      src/Web/Avalonia.Web.Blazor/Interop/InputHelperInterop.cs
  4. 37
      src/Web/Avalonia.Web.Blazor/webapp/modules/Avalonia/InputHelper.ts

2
src/Web/Avalonia.Web.Blazor/AvaloniaView.razor

@ -16,7 +16,7 @@
<div id="nativeControlsContainer" @ref="_nativeControlsContainer" />
<input id="inputElement" @ref="_inputElement" type="text" @oninput="OnInput"
<input id="inputElement" @ref="_inputElement" type="text"
onpaste="return false;"
oncopy="return false;"
oncut="return false;"

38
src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs

@ -12,6 +12,7 @@ using Avalonia.Web.Blazor.Interop;
using Avalonia.Web.Blazor.Interop.Storage;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
@ -73,6 +74,8 @@ namespace Avalonia.Web.Blazor
public bool IsActive => _client != null;
public bool IsComposing { get; private set; }
internal INativeControlHostImpl GetNativeControlHostImpl()
{
return _nativeControlHost ?? throw new InvalidOperationException("Blazor View wasn't initialized yet");
@ -231,20 +234,6 @@ namespace Avalonia.Web.Blazor
}
}
private void OnInput(ChangeEventArgs e)
{
if (e.Value != null)
{
var inputData = e.Value.ToString();
if (inputData != null)
{
_topLevelImpl.RawTextEvent(inputData);
}
}
_inputHelper?.Clear();
}
[Parameter(CaptureUnmatchedValues = true)]
public IReadOnlyDictionary<string, object>? AdditionalAttributes { get; set; }
@ -261,6 +250,7 @@ namespace Avalonia.Web.Blazor
_inputHelper = new InputHelperInterop(_avaloniaModule, _inputElement);
_inputHelper.CompositionEvent += InputHelperOnCompositionEvent;
_inputHelper.InputEvent += InputHelperOnInputEvent;
HideIme();
_canvasHelper.SetCursor("default");
@ -333,6 +323,16 @@ namespace Avalonia.Web.Blazor
}
}
private void InputHelperOnInputEvent(object? sender, WebInputEventArgs e)
{
if (IsComposing)
{
return;
}
_topLevelImpl.RawTextEvent(e.Data);
}
private void InputHelperOnCompositionEvent(object? sender, WebCompositionEventArgs e)
{
if(_client == null)
@ -344,12 +344,15 @@ namespace Avalonia.Web.Blazor
{
case WebCompositionEventArgs.WebCompositionEventType.Start:
_client.SetPreeditText(null);
IsComposing = true;
break;
case WebCompositionEventArgs.WebCompositionEventType.Update:
_client?.SetPreeditText(e.Data);
break;
case WebCompositionEventArgs.WebCompositionEventType.End:
IsComposing = false;
_client?.SetPreeditText(null);
_topLevelImpl.RawTextEvent(e.Data);
break;
}
}
@ -462,9 +465,12 @@ namespace Avalonia.Web.Blazor
private void SurroundingTextChanged(object? sender, EventArgs e)
{
var surroundingText = _client.SurroundingText;
if(_client != null && IsComposing)
{
var surroundingText = _client.SurroundingText;
_inputHelper?.SetSurroundingText(surroundingText.Text, surroundingText.AnchorOffset, surroundingText.CursorOffset);
_inputHelper?.SetSurroundingText(surroundingText.Text, surroundingText.AnchorOffset, surroundingText.CursorOffset);
}
}
public void SetCursorRect(Rect rect)

55
src/Web/Avalonia.Web.Blazor/Interop/InputHelperInterop.cs

@ -1,5 +1,4 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace Avalonia.Web.Blazor.Interop
@ -30,6 +29,19 @@ namespace Avalonia.Web.Blazor.Interop
public string Data { get; }
}
internal class WebInputEventArgs
{
public WebInputEventArgs(string type, string data)
{
Type = type;
Data = data;
}
public string Type { get; }
public string Data { get; }
}
internal class InputHelperInterop
{
@ -39,23 +51,29 @@ namespace Avalonia.Web.Blazor.Interop
private const string HideSymbol = "InputHelper.hide";
private const string ShowSymbol = "InputHelper.show";
private const string StartSymbol = "InputHelper.start";
private const string SetSurroundingTextSymbol = "InputHelper.setSurroundingText";
private readonly AvaloniaModule _module;
private readonly ElementReference _inputElement;
private readonly ActionHelper<string, string> _actionHelper;
private DotNetObjectReference<ActionHelper<string, string>>? callbackReference;
private readonly ActionHelper<string, string> _compositionAction;
private readonly ActionHelper<string, string> _inputAction;
private DotNetObjectReference<ActionHelper<string, string>>? compositionActionReference;
private DotNetObjectReference<ActionHelper<string, string>>? inputActionReference;
public InputHelperInterop(AvaloniaModule module, ElementReference inputElement)
{
_module = module;
_inputElement = inputElement;
_actionHelper = new ActionHelper<string, string>(OnCompositionEvent);
_compositionAction = new ActionHelper<string, string>(OnCompositionEvent);
_inputAction = new ActionHelper<string, string>(OnInputEvent);
Start();
}
public event EventHandler<WebCompositionEventArgs>? CompositionEvent;
public event EventHandler<WebCompositionEventArgs>? CompositionEvent;
public event EventHandler<WebInputEventArgs>? InputEvent;
private void OnCompositionEvent(string type, string data)
{
@ -63,6 +81,12 @@ namespace Avalonia.Web.Blazor.Interop
CompositionEvent?.Invoke(this, new WebCompositionEventArgs(type, data));
}
private void OnInputEvent(string type, string data)
{
Console.WriteLine($"InputEvent Handler Helper {InputEvent == null} ");
InputEvent?.Invoke(this, new WebInputEventArgs(type, data));
}
public void Clear() => _module.Invoke(ClearSymbol, _inputElement);
public void Focus() => _module.Invoke(FocusSymbol, _inputElement);
@ -75,12 +99,21 @@ namespace Avalonia.Web.Blazor.Interop
private void Start()
{
if(callbackReference != null)
if(compositionActionReference != null)
{
return;
callbackReference = DotNetObjectReference.Create(_actionHelper);
}
compositionActionReference = DotNetObjectReference.Create(_compositionAction);
_module.Invoke(StartSymbol, _inputElement, callbackReference);
inputActionReference = DotNetObjectReference.Create(_inputAction);
_module.Invoke(StartSymbol, _inputElement, compositionActionReference, inputActionReference);
}
public void SetSurroundingText(string text, int start, int end)
{
_module.Invoke(SetSurroundingTextSymbol, _inputElement, text, start, end);
}
}
}

37
src/Web/Avalonia.Web.Blazor/webapp/modules/Avalonia/InputHelper.ts

@ -1,13 +1,18 @@
export class InputHelper {
static callback?: DotNet.DotNetObject;
static inputCallback?: DotNet.DotNetObject;
static compositionCallback?: DotNet.DotNetObject
public static start(inputElement: HTMLInputElement, callback: DotNet.DotNetObject)
{
InputHelper.callback = callback;
public static start(inputElement: HTMLInputElement, compositionCallback: DotNet.DotNetObject, inputCallback: DotNet.DotNetObject)
{
InputHelper.compositionCallback = compositionCallback;
inputElement.addEventListener('compositionstart', InputHelper.onCompositionEvent);
inputElement.addEventListener('compositionupdate', InputHelper.onCompositionEvent);
inputElement.addEventListener('compositionend', InputHelper.onCompositionEvent);
inputElement.addEventListener('compositionend', InputHelper.onCompositionEvent);
InputHelper.inputCallback = inputCallback;
inputElement.addEventListener('input', InputHelper.onInputEvent);
}
public static clear(inputElement: HTMLInputElement) {
@ -30,9 +35,18 @@
inputElement.style.display = 'block';
}
public static setSurroundingText(inputElement: HTMLInputElement, text: string, start: number, end: number) {
if (!inputElement) {
return;
}
inputElement.value = text;
inputElement.setSelectionRange(start, end);
}
private static onCompositionEvent(ev: CompositionEvent)
{
if(!InputHelper.callback)
if(!InputHelper.compositionCallback)
return;
switch (ev.type)
@ -40,9 +54,18 @@
case "compositionstart":
case "compositionupdate":
case "compositionend":
InputHelper.callback.invokeMethod('Invoke', ev.type, ev.data);
InputHelper.compositionCallback.invokeMethod('Invoke', ev.type, ev.data);
break;
}
}
private static onInputEvent(ev: Event) {
if (!InputHelper.inputCallback)
return;
var inputEvent = ev as InputEvent;
InputHelper.inputCallback.invokeMethod('Invoke', ev.type, inputEvent.data);
}
}

Loading…
Cancel
Save