mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-17 06:38:00 +00:00
Bring the drop position into .NET and add the DOM hit test
This commit is contained in:
6 files changed
+128
-2
No files matched your search
@@ -71,6 +71,40 @@ public static class JsRuntimeExtensions
|
||||
return await jsRuntime.TryInvokeVoidAsync(identifier, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls a JavaScript function which returns a value, unless the circuit is known to be disconnected.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The two parts of the result answer two different questions, and callers must keep them apart.
|
||||
/// Whether the browser ran the function at all comes first: a call which never arrived says nothing
|
||||
/// about the page, so nobody may act on an answer they did not get. What the function returned is the
|
||||
/// second question, and there a null is a legitimate answer -- it means the browser looked and found
|
||||
/// nothing.
|
||||
/// </remarks>
|
||||
/// <param name="jsRuntime">The JS runtime to call.</param>
|
||||
/// <param name="circuitState">The circuit of the caller.</param>
|
||||
/// <param name="identifier">The name of the JavaScript function.</param>
|
||||
/// <param name="args">The arguments for the JavaScript function.</param>
|
||||
/// <returns>Whether the browser ran the function, and what it returned.</returns>
|
||||
public static async ValueTask<(bool WasInvoked, TValue? Value)> TryInvokeAsync<TValue>(this IJSRuntime jsRuntime, CircuitStateService circuitState, string identifier, params object?[]? args)
|
||||
{
|
||||
if (!circuitState.IsConnected)
|
||||
{
|
||||
LOGGER.LogDebug("The JS call '{Identifier}' was skipped because the browser connection of the circuit '{CircuitId}' is down.", identifier, circuitState.CircuitId);
|
||||
return (false, default);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return (true, await jsRuntime.InvokeAsync<TValue>(identifier, args));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LogInvocationFailure(exception, identifier);
|
||||
return (false, default);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls a function of a JavaScript module which returns nothing, and tolerates a circuit which is
|
||||
/// already gone. See the remarks on the JS runtime variant of this method.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>
|
||||
/// The cursor position of a drag and drop event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The coordinates are viewport-relative CSS pixels, on every platform. The Rust runtime has already
|
||||
/// dealt with the platform differences -- device pixels on Windows, logical points on macOS and Linux --
|
||||
/// so these numbers can be handed to the browser for a hit test without any further conversion.
|
||||
/// </remarks>
|
||||
/// <param name="X">The distance from the left edge of the viewport, in CSS pixels.</param>
|
||||
/// <param name="Y">The distance from the top edge of the viewport, in CSS pixels.</param>
|
||||
public readonly record struct DropPosition(double X, double Y);
|
||||
@@ -5,7 +5,8 @@ namespace AIStudio.Tools.Rust;
|
||||
/// </summary>
|
||||
/// <param name="EventType">The type of the Tauri event.</param>
|
||||
/// <param name="Payload">The payload of the Tauri event.</param>
|
||||
public readonly record struct TauriEvent(TauriEventType EventType, List<string> Payload)
|
||||
/// <param name="Position">Where the cursor was, for the drag and drop events which know it.</param>
|
||||
public readonly record struct TauriEvent(TauriEventType EventType, List<string> Payload, DropPosition? Position = null)
|
||||
{
|
||||
/// <summary>
|
||||
/// Attempts to parse the first payload element as a shortcut.
|
||||
@@ -29,6 +30,28 @@ public readonly record struct TauriEvent(TauriEventType EventType, List<string>
|
||||
return TryParseSnakeCase(this.Payload[0], out shortcut);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the cursor position of a drag and drop event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The coordinates are viewport-relative CSS pixels, ready for a hit test in the browser. Only the
|
||||
/// drag and drop events carry them, which is why the caller has to ask instead of assuming.
|
||||
/// </remarks>
|
||||
/// <param name="x">The distance from the left edge of the viewport, in CSS pixels.</param>
|
||||
/// <param name="y">The distance from the top edge of the viewport, in CSS pixels.</param>
|
||||
/// <returns>True if the event carried a position, false otherwise.</returns>
|
||||
public bool TryGetDropPosition(out double x, out double y)
|
||||
{
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
if (this.Position is not { } position)
|
||||
return false;
|
||||
|
||||
x = position.X;
|
||||
y = position.Y;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a portal shortcut change and its effective display name.
|
||||
/// </summary>
|
||||
|
||||
@@ -13,6 +13,7 @@ public enum TauriEventType
|
||||
WINDOW_NOT_FOCUSED,
|
||||
|
||||
FILE_DROP_HOVERED,
|
||||
FILE_DROP_OVER,
|
||||
FILE_DROP_DROPPED,
|
||||
FILE_DROP_CANCELED,
|
||||
|
||||
|
||||
@@ -46,7 +46,14 @@ public partial class RustService
|
||||
and not TauriEventType.UNKNOWN
|
||||
and not TauriEventType.PING)
|
||||
{
|
||||
this.logger!.LogDebug("Received Tauri event {EventType} with {NumPayloadItems} payload items.", tauriEvent.EventType, tauriEvent.Payload.Count);
|
||||
//
|
||||
// Log every event but the drag-over ones: those arrive about ten times per
|
||||
// second for as long as a drag lasts, and one line each would bury everything
|
||||
// else in the log.
|
||||
//
|
||||
if(tauriEvent.EventType is not TauriEventType.FILE_DROP_OVER)
|
||||
this.logger!.LogDebug("Received Tauri event {EventType} with {NumPayloadItems} payload items.", tauriEvent.EventType, tauriEvent.Payload.Count);
|
||||
|
||||
await MessageBus.INSTANCE.SendMessage(null, Event.TAURI_EVENT_RECEIVED, tauriEvent);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user