13 changed files with 590 additions and 143 deletions
@ -0,0 +1,46 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices.JavaScript; |
|||
|
|||
namespace Avalonia.Web.Interop; |
|||
|
|||
internal static partial class InputHelper |
|||
{ |
|||
//[JSImport("InputHelper.subscribePointerEvents", "avalonia.ts")]
|
|||
//public static partial void SubscribePointerEvents(
|
|||
// JSObject htmlElement,
|
|||
// [JSMarshalAs<JSType.Function<JSType.Number, JSType.Number, JSType.Number, JSType.Number, JSType.Number, JSType.Boolean>>]
|
|||
// Func<double, double, double, double, int, bool> wheel);
|
|||
|
|||
[JSImport("InputHelper.subscribeKeyboardEvents", "avalonia.ts")] |
|||
public static partial void SubscribeKeyboardEvents( |
|||
JSObject htmlElement, |
|||
[JSMarshalAs<JSType.Function<JSType.String, JSType.String, JSType.Number, JSType.Boolean>>] |
|||
Func<string, string, int, bool> keyDown, |
|||
[JSMarshalAs<JSType.Function<JSType.String, JSType.String, JSType.Number, JSType.Boolean>>] |
|||
Func<string, string, int, bool> keyUp); |
|||
|
|||
[JSImport("InputHelper.subscribeInputEvents", "avalonia.ts")] |
|||
public static partial void SubscribeInputEvents( |
|||
JSObject htmlElement, |
|||
[JSMarshalAs<JSType.Function<JSType.String, JSType.Boolean>>] |
|||
Func<string, bool> input); |
|||
|
|||
|
|||
[JSImport("InputHelper.clearInput", "avalonia.ts")] |
|||
public static partial void ClearInputElement(JSObject htmlElement); |
|||
|
|||
[JSImport("InputHelper.isInputElement", "avalonia.ts")] |
|||
public static partial void IsInputElement(JSObject htmlElement); |
|||
|
|||
[JSImport("InputHelper.focusElement", "avalonia.ts")] |
|||
public static partial void FocusElement(JSObject htmlElement); |
|||
|
|||
[JSImport("InputHelper.setCursor", "avalonia.ts")] |
|||
public static partial void SetCursor(JSObject htmlElement, string kind); |
|||
|
|||
[JSImport("InputHelper.hide", "avalonia.ts")] |
|||
public static partial void HideElement(JSObject htmlElement); |
|||
|
|||
[JSImport("InputHelper.show", "avalonia.ts")] |
|||
public static partial void ShowElement(JSObject htmlElement); |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices.JavaScript; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Avalonia.Web.Storage; |
|||
|
|||
/// <summary>
|
|||
/// Set of FileSystemWritableFileStream and Blob methods.
|
|||
/// </summary>
|
|||
internal static partial class StreamHelper |
|||
{ |
|||
[JSImport("StreamHelper.seek", "avalonia.ts")] |
|||
public static partial void Seek(JSObject stream, [JSMarshalAs<JSType.Number>] long position); |
|||
|
|||
[JSImport("StreamHelper.truncate", "avalonia.ts")] |
|||
public static partial void Truncate(JSObject stream, [JSMarshalAs<JSType.Number>] long position); |
|||
|
|||
[JSImport("StreamHelper.write", "avalonia.ts")] |
|||
public static partial void Write(JSObject stream, [JSMarshalAs<JSType.MemoryView>] Span<byte> data); |
|||
|
|||
[JSImport("StreamHelper.write", "avalonia.ts")] |
|||
public static partial Task WriteAsync(JSObject stream, [JSMarshalAs<JSType.MemoryView>] ArraySegment<byte> data); |
|||
|
|||
[JSImport("StreamHelper.close", "avalonia.ts")] |
|||
public static partial void Close(JSObject stream); |
|||
|
|||
[JSImport("StreamHelper.close", "avalonia.ts")] |
|||
public static partial Task CloseAsync(JSObject stream); |
|||
|
|||
[JSImport("StreamHelper.size", "avalonia.ts")] |
|||
[return: JSMarshalAs<JSType.Number>] |
|||
public static partial long Size(JSObject stream); |
|||
|
|||
[JSImport("StreamHelper.byteLength", "avalonia.ts")] |
|||
[return: JSMarshalAs<JSType.Number>] |
|||
public static partial long ByteLength(JSObject stream); |
|||
|
|||
[JSImport("StreamHelper.sliceToArray", "avalonia.ts")] |
|||
[return: JSMarshalAs<JSType.MemoryView>] |
|||
public static partial Span<byte> Slice(JSObject stream, [JSMarshalAs<JSType.Number>] long offset, int count); |
|||
|
|||
public static async Task<ArraySegment<byte>> SliceAsync(JSObject stream, long offset, int count) |
|||
{ |
|||
using var buffer = await SliceToBufferAsync(stream, offset, count); |
|||
return BufferToArray(buffer); |
|||
} |
|||
|
|||
[JSImport("StreamHelper.slice", "avalonia.ts")] |
|||
[return: JSMarshalAs<JSType.Promise<JSType.Object>>] |
|||
private static partial Task<JSObject> SliceToBufferAsync(JSObject stream, [JSMarshalAs<JSType.Number>] long offset, int count); |
|||
|
|||
[JSImport("StreamHelper.toArray", "avalonia.ts")] |
|||
[return: JSMarshalAs<JSType.MemoryView>] |
|||
private static partial ArraySegment<byte> BufferToArray(JSObject stream); |
|||
} |
|||
@ -0,0 +1,129 @@ |
|||
using System.Collections.Generic; |
|||
|
|||
using Avalonia.Input; |
|||
|
|||
namespace Avalonia.Web |
|||
{ |
|||
internal static class Keycodes |
|||
{ |
|||
public static Dictionary<string, Key> KeyCodes = new() |
|||
{ |
|||
{ "Escape", Key.Escape }, |
|||
{ "Digit1", Key.D1 }, |
|||
{ "Digit2", Key.D2 }, |
|||
{ "Digit3", Key.D3 }, |
|||
{ "Digit4", Key.D4 }, |
|||
{ "Digit5", Key.D5 }, |
|||
{ "Digit6", Key.D6 }, |
|||
{ "Digit7", Key.D7 }, |
|||
{ "Digit8", Key.D8 }, |
|||
{ "Digit9", Key.D9 }, |
|||
{ "Digit0", Key.D0 }, |
|||
{ "Minus", Key.OemMinus }, |
|||
//{ "Equal" , Key. },
|
|||
{ "Backspace", Key.Back }, |
|||
{ "Tab", Key.Tab }, |
|||
{ "KeyQ", Key.Q }, |
|||
{ "KeyW", Key.W }, |
|||
{ "KeyE", Key.E }, |
|||
{ "KeyR", Key.R }, |
|||
{ "KeyT", Key.T }, |
|||
{ "KeyY", Key.Y }, |
|||
{ "KeyU", Key.U }, |
|||
{ "KeyI", Key.I }, |
|||
{ "KeyO", Key.O }, |
|||
{ "KeyP", Key.P }, |
|||
{ "BracketLeft", Key.OemOpenBrackets }, |
|||
{ "BracketRight", Key.OemCloseBrackets }, |
|||
{ "Enter", Key.Enter }, |
|||
{ "ControlLeft", Key.LeftCtrl }, |
|||
{ "KeyA", Key.A }, |
|||
{ "KeyS", Key.S }, |
|||
{ "KeyD", Key.D }, |
|||
{ "KeyF", Key.F }, |
|||
{ "KeyG", Key.G }, |
|||
{ "KeyH", Key.H }, |
|||
{ "KeyJ", Key.J }, |
|||
{ "KeyK", Key.K }, |
|||
{ "KeyL", Key.L }, |
|||
{ "Semicolon", Key.OemSemicolon }, |
|||
{ "Quote", Key.OemQuotes }, |
|||
//{ "Backquote" , Key. },
|
|||
{ "ShiftLeft", Key.LeftShift }, |
|||
{ "Backslash", Key.OemBackslash }, |
|||
{ "KeyZ", Key.Z }, |
|||
{ "KeyX", Key.X }, |
|||
{ "KeyC", Key.C }, |
|||
{ "KeyV", Key.V }, |
|||
{ "KeyB", Key.B }, |
|||
{ "KeyN", Key.N }, |
|||
{ "KeyM", Key.M }, |
|||
{ "Comma", Key.OemComma }, |
|||
{ "Period", Key.OemPeriod }, |
|||
//{ "Slash" , Key. },
|
|||
{ "ShiftRight", Key.RightShift }, |
|||
{ "NumpadMultiply", Key.Multiply }, |
|||
{ "AltLeft", Key.LeftAlt }, |
|||
{ "Space", Key.Space }, |
|||
{ "CapsLock", Key.CapsLock }, |
|||
{ "F1", Key.F1 }, |
|||
{ "F2", Key.F2 }, |
|||
{ "F3", Key.F3 }, |
|||
{ "F4", Key.F4 }, |
|||
{ "F5", Key.F5 }, |
|||
{ "F6", Key.F6 }, |
|||
{ "F7", Key.F7 }, |
|||
{ "F8", Key.F8 }, |
|||
{ "F9", Key.F9 }, |
|||
{ "F10", Key.F10 }, |
|||
{ "NumLock", Key.NumLock }, |
|||
{ "ScrollLock", Key.Scroll }, |
|||
{ "Numpad7", Key.NumPad7 }, |
|||
{ "Numpad8", Key.NumPad8 }, |
|||
{ "Numpad9", Key.NumPad9 }, |
|||
{ "NumpadSubtract", Key.Subtract }, |
|||
{ "Numpad4", Key.NumPad4 }, |
|||
{ "Numpad5", Key.NumPad5 }, |
|||
{ "Numpad6", Key.NumPad6 }, |
|||
{ "NumpadAdd", Key.Add }, |
|||
{ "Numpad1", Key.NumPad1 }, |
|||
{ "Numpad2", Key.NumPad2 }, |
|||
{ "Numpad3", Key.NumPad3 }, |
|||
{ "Numpad0", Key.NumPad0 }, |
|||
{ "NumpadDecimal", Key.Decimal }, |
|||
{ "Unidentified", Key.NoName }, |
|||
//{ "IntlBackslash" , Key.bac },
|
|||
{ "F11", Key.F11 }, |
|||
{ "F12", Key.F12 }, |
|||
//{ "IntlRo" , Key.Ro },
|
|||
//{ "Unidentified" , Key. },
|
|||
{ "Convert", Key.ImeConvert }, |
|||
{ "KanaMode", Key.KanaMode }, |
|||
{ "NonConvert", Key.ImeNonConvert }, |
|||
//{ "Unidentified" , Key. },
|
|||
{ "NumpadEnter", Key.Enter }, |
|||
{ "ControlRight", Key.RightCtrl }, |
|||
{ "NumpadDivide", Key.Divide }, |
|||
{ "PrintScreen", Key.PrintScreen }, |
|||
{ "AltRight", Key.RightAlt }, |
|||
//{ "Unidentified" , Key. },
|
|||
{ "Home", Key.Home }, |
|||
{ "ArrowUp", Key.Up }, |
|||
{ "PageUp", Key.PageUp }, |
|||
{ "ArrowLeft", Key.Left }, |
|||
{ "ArrowRight", Key.Right }, |
|||
{ "End", Key.End }, |
|||
{ "ArrowDown", Key.Down }, |
|||
{ "PageDown", Key.PageDown }, |
|||
{ "Insert", Key.Insert }, |
|||
{ "Delete", Key.Delete }, |
|||
//{ "Unidentified" , Key. },
|
|||
{ "AudioVolumeMute", Key.VolumeMute }, |
|||
{ "AudioVolumeDown", Key.VolumeDown }, |
|||
{ "AudioVolumeUp", Key.VolumeUp }, |
|||
//{ "NumpadEqual" , Key. },
|
|||
{ "Pause", Key.Pause }, |
|||
{ "NumpadComma", Key.OemComma } |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,100 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Runtime.InteropServices.JavaScript; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Avalonia.Web.Storage; |
|||
|
|||
internal class BlobReadableStream : Stream |
|||
{ |
|||
private JSObject? _jSReference; |
|||
private long _position; |
|||
private readonly long _length; |
|||
|
|||
public BlobReadableStream(JSObject jsStreamReference) |
|||
{ |
|||
_jSReference = jsStreamReference; |
|||
_position = 0; |
|||
_length = StreamHelper.ByteLength(JSReference); |
|||
} |
|||
|
|||
private JSObject JSReference => _jSReference ?? throw new ObjectDisposedException(nameof(JSWriteableStream)); |
|||
|
|||
public override bool CanRead => true; |
|||
|
|||
public override bool CanSeek => false; |
|||
|
|||
public override bool CanWrite => false; |
|||
|
|||
public override long Length => _length; |
|||
|
|||
public override long Position |
|||
{ |
|||
get => _position; |
|||
set => throw new NotSupportedException(); |
|||
} |
|||
|
|||
public override void Flush() { } |
|||
|
|||
public override long Seek(long offset, SeekOrigin origin) |
|||
{ |
|||
return _position = origin switch |
|||
{ |
|||
SeekOrigin.Current => _position + offset, |
|||
SeekOrigin.End => _length + offset, |
|||
_ => offset |
|||
}; |
|||
} |
|||
|
|||
public override void SetLength(long value) |
|||
=> throw new NotSupportedException(); |
|||
|
|||
public override void Write(byte[] buffer, int offset, int count) |
|||
=> throw new NotSupportedException(); |
|||
|
|||
public override int Read(byte[] buffer, int offset, int count) |
|||
=> Read(buffer.AsSpan(offset, count)); |
|||
|
|||
public override int Read(Span<byte> buffer) |
|||
{ |
|||
var numBytesToRead = (int)Math.Min(buffer.Length, Length - _position); |
|||
var bytesRead = StreamHelper.Slice(JSReference, _position, numBytesToRead); |
|||
if (bytesRead.Length != numBytesToRead) |
|||
{ |
|||
throw new EndOfStreamException("Failed to read the requested number of bytes from the stream."); |
|||
} |
|||
|
|||
_position += bytesRead.Length; |
|||
bytesRead.CopyTo(buffer); |
|||
|
|||
return bytesRead.Length; |
|||
} |
|||
|
|||
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) |
|||
=> await ReadAsync(buffer.AsMemory(offset, count), cancellationToken); |
|||
|
|||
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default) |
|||
{ |
|||
var numBytesToRead = (int)Math.Min(buffer.Length, Length - _position); |
|||
var bytesRead = await StreamHelper.SliceAsync(JSReference, _position, numBytesToRead); |
|||
if (bytesRead.Count != numBytesToRead) |
|||
{ |
|||
throw new EndOfStreamException("Failed to read the requested number of bytes from the stream."); |
|||
} |
|||
|
|||
_position += bytesRead.Count; |
|||
bytesRead.AsMemory().CopyTo(buffer); |
|||
|
|||
return bytesRead.Count; |
|||
} |
|||
|
|||
protected override void Dispose(bool disposing) |
|||
{ |
|||
if (_jSReference is { } jsReference) |
|||
{ |
|||
_jSReference = null; |
|||
jsReference.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,136 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Runtime.InteropServices.JavaScript; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Avalonia.Web.Storage; |
|||
|
|||
// Loose wrapper implementaion of a stream on top of FileAPI FileSystemWritableFileStream
|
|||
internal sealed class JSWriteableStream : Stream |
|||
{ |
|||
private JSObject? _jSReference; |
|||
|
|||
// Unfortunatelly we can't read current length/position, so we need to keep it C#-side only.
|
|||
private long _length, _position; |
|||
|
|||
internal JSWriteableStream(JSObject jSReference, long initialLength) |
|||
{ |
|||
_jSReference = jSReference; |
|||
_length = initialLength; |
|||
} |
|||
|
|||
private JSObject JSReference => _jSReference ?? throw new ObjectDisposedException(nameof(JSWriteableStream)); |
|||
|
|||
public override bool CanRead => false; |
|||
|
|||
public override bool CanSeek => true; |
|||
|
|||
public override bool CanWrite => true; |
|||
|
|||
public override long Length => _length; |
|||
|
|||
public override long Position |
|||
{ |
|||
get => _position; |
|||
set => Seek(_position, SeekOrigin.Begin); |
|||
} |
|||
|
|||
public override void Flush() |
|||
{ |
|||
// no-op
|
|||
} |
|||
|
|||
public override int Read(byte[] buffer, int offset, int count) |
|||
{ |
|||
throw new NotSupportedException(); |
|||
} |
|||
|
|||
public override long Seek(long offset, SeekOrigin origin) |
|||
{ |
|||
var position = origin switch |
|||
{ |
|||
SeekOrigin.Current => _position + offset, |
|||
SeekOrigin.End => _length + offset, |
|||
_ => offset |
|||
}; |
|||
StreamHelper.Seek(JSReference, position); |
|||
return position; |
|||
} |
|||
|
|||
public override void SetLength(long value) |
|||
{ |
|||
_length = value; |
|||
|
|||
// See https://docs.w3cub.com/dom/filesystemwritablefilestream/truncate
|
|||
// If the offset is smaller than the size, it remains unchanged. If the offset is larger than size, the offset is set to that size
|
|||
if (_position > _length) |
|||
{ |
|||
_position = _length; |
|||
} |
|||
|
|||
StreamHelper.Truncate(JSReference, value); |
|||
} |
|||
|
|||
public override void Write(byte[] buffer, int offset, int count) |
|||
{ |
|||
StreamHelper.Write(JSReference, buffer.AsSpan(offset, count)); |
|||
} |
|||
|
|||
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) |
|||
{ |
|||
if (offset != 0 || count != buffer.Length) |
|||
{ |
|||
// TODO, we need to pass prepared buffer to the JS
|
|||
// Can't use ArrayPool as it can return bigger array than requested
|
|||
// Can't use Span/Memory, as it's not supported by JS interop yet.
|
|||
// Alternatively we can pass original buffer and offset+count, so it can be trimmed on the JS side (but is it more efficient tho?)
|
|||
buffer = buffer.AsMemory(offset, count).ToArray(); |
|||
} |
|||
return WriteAsyncInternal(buffer, cancellationToken); |
|||
} |
|||
|
|||
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default) |
|||
{ |
|||
return new ValueTask(WriteAsyncInternal(buffer.ToArray(), cancellationToken)); |
|||
} |
|||
|
|||
private Task WriteAsyncInternal(byte[] buffer, CancellationToken _) |
|||
{ |
|||
_position += buffer.Length; |
|||
|
|||
return StreamHelper.WriteAsync(JSReference, buffer); |
|||
} |
|||
|
|||
protected override void Dispose(bool disposing) |
|||
{ |
|||
if (_jSReference is { } jsReference) |
|||
{ |
|||
_jSReference = null; |
|||
try |
|||
{ |
|||
StreamHelper.Close(JSReference); |
|||
} |
|||
finally |
|||
{ |
|||
jsReference.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public override async ValueTask DisposeAsync() |
|||
{ |
|||
if (_jSReference is { } jsReference) |
|||
{ |
|||
_jSReference = null; |
|||
try |
|||
{ |
|||
await StreamHelper.CloseAsync(JSReference); |
|||
} |
|||
finally |
|||
{ |
|||
jsReference.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,107 @@ |
|||
enum RawInputModifiers |
|||
{ |
|||
None = 0, |
|||
Alt = 1, |
|||
Control = 2, |
|||
Shift = 4, |
|||
Meta = 8, |
|||
|
|||
LeftMouseButton = 16, |
|||
RightMouseButton = 32, |
|||
MiddleMouseButton = 64, |
|||
XButton1MouseButton = 128, |
|||
XButton2MouseButton = 256, |
|||
KeyboardMask = Alt | Control | Shift | Meta, |
|||
|
|||
PenInverted = 512, |
|||
PenEraser = 1024, |
|||
PenBarrelButton = 2048 |
|||
} |
|||
|
|||
export class InputHelper { |
|||
public static subscribeKeyboardEvents( |
|||
element: HTMLInputElement, |
|||
keyDownCallback: (code: string, key: string, modifiers: RawInputModifiers) => boolean, |
|||
keyUpCallback: (code: string, key: string, modifiers: RawInputModifiers) => boolean, |
|||
) { |
|||
const keyDownHandler = (args: Event) => { |
|||
const keyArgs = <KeyboardEvent>args; |
|||
if (keyDownCallback(keyArgs.code, keyArgs.key, this.getModifiers(keyArgs))) { |
|||
args.preventDefault(); |
|||
} |
|||
}; |
|||
element.addEventListener("keydown", keyDownHandler); |
|||
|
|||
const keyUpHandler = (args: Event) => { |
|||
const keyArgs = <KeyboardEvent>args; |
|||
if (keyUpCallback(keyArgs.code, keyArgs.key, this.getModifiers(keyArgs))) { |
|||
args.preventDefault(); |
|||
} |
|||
}; |
|||
element.addEventListener("keyup", keyUpHandler); |
|||
|
|||
return () => { |
|||
element.removeEventListener("keydown", keyDownHandler); |
|||
element.removeEventListener("keyup", keyUpHandler); |
|||
}; |
|||
} |
|||
|
|||
public static subscribeInputEvents( |
|||
element: HTMLInputElement, |
|||
inputCallback: (value: string) => boolean |
|||
) { |
|||
const inputHandler = (args: Event) => { |
|||
if (inputCallback((args as any).value)) { |
|||
args.preventDefault(); |
|||
} |
|||
}; |
|||
element.addEventListener("input", inputHandler); |
|||
|
|||
return () => { |
|||
element.removeEventListener("input", inputHandler); |
|||
}; |
|||
} |
|||
|
|||
public static clearInput(inputElement: HTMLInputElement) { |
|||
inputElement.value = ""; |
|||
} |
|||
|
|||
public static isInputElement(element: HTMLInputElement | HTMLElement): element is HTMLInputElement { |
|||
return (element as HTMLInputElement).setSelectionRange !== undefined; |
|||
} |
|||
|
|||
public static focusElement(inputElement: HTMLElement) { |
|||
inputElement.focus(); |
|||
|
|||
if (this.isInputElement(inputElement)) { |
|||
(inputElement as HTMLInputElement).setSelectionRange(0, 0); |
|||
} |
|||
} |
|||
|
|||
public static setCursor(inputElement: HTMLInputElement, kind: string) { |
|||
inputElement.style.cursor = kind; |
|||
} |
|||
|
|||
public static hide(inputElement: HTMLInputElement) { |
|||
inputElement.style.display = 'none'; |
|||
} |
|||
|
|||
public static show(inputElement: HTMLInputElement) { |
|||
inputElement.style.display = 'block'; |
|||
} |
|||
|
|||
private static getModifiers(args: KeyboardEvent): RawInputModifiers { |
|||
var modifiers = RawInputModifiers.None; |
|||
|
|||
if (args.ctrlKey) |
|||
modifiers |= RawInputModifiers.Control; |
|||
if (args.altKey) |
|||
modifiers |= RawInputModifiers.Alt; |
|||
if (args.shiftKey) |
|||
modifiers |= RawInputModifiers.Shift; |
|||
if (args.metaKey) |
|||
modifiers |= RawInputModifiers.Meta; |
|||
|
|||
return modifiers; |
|||
} |
|||
} |
|||
@ -1,124 +0,0 @@ |
|||
var __async = (__this, __arguments, generator) => { |
|||
return new Promise((resolve, reject) => { |
|||
var fulfilled = (value) => { |
|||
try { |
|||
step(generator.next(value)); |
|||
} catch (e) { |
|||
reject(e); |
|||
} |
|||
}; |
|||
var rejected = (value) => { |
|||
try { |
|||
step(generator.throw(value)); |
|||
} catch (e) { |
|||
reject(e); |
|||
} |
|||
}; |
|||
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); |
|||
step((generator = generator.apply(__this, __arguments)).next()); |
|||
}); |
|||
}; |
|||
|
|||
// modules/avalonia/canvas.ts
|
|||
var Canvas = class { |
|||
constructor(useGL, element) { |
|||
this.renderLoopEnabled = false; |
|||
this.renderLoopRequest = 0; |
|||
if (useGL) { |
|||
const ctx = Canvas.createWebGLContext(element); |
|||
if (!ctx) { |
|||
console.error(`Failed to create WebGL context: err ${ctx}`); |
|||
return; |
|||
} |
|||
var GL = globalThis.AvaloniaGL; |
|||
GL.makeContextCurrent(ctx); |
|||
var GLctx = GL.currentContext.GLctx; |
|||
const fbo = GLctx.getParameter(GLctx.FRAMEBUFFER_BINDING); |
|||
this.glInfo = { |
|||
context: ctx, |
|||
fboId: fbo ? fbo.id : 0, |
|||
stencil: GLctx.getParameter(GLctx.STENCIL_BITS), |
|||
sample: 0, |
|||
depth: GLctx.getParameter(GLctx.DEPTH_BITS) |
|||
}; |
|||
} |
|||
} |
|||
static createCanvas(element) { |
|||
var canvas = document.createElement("canvas"); |
|||
element.appendChild(canvas); |
|||
return canvas; |
|||
} |
|||
static initGL(element, elementId) { |
|||
console.log("inside initGL"); |
|||
var view = Canvas.init(true, element, elementId); |
|||
if (!view || !view.glInfo) |
|||
return null; |
|||
return view.glInfo; |
|||
} |
|||
static init(useGL, element, elementId) { |
|||
var htmlCanvas = element; |
|||
if (!htmlCanvas) { |
|||
console.error(`No canvas element was provided.`); |
|||
return null; |
|||
} |
|||
if (!Canvas.elements) |
|||
Canvas.elements = /* @__PURE__ */ new Map(); |
|||
Canvas.elements.set(elementId, element); |
|||
const view = new Canvas(useGL, element); |
|||
htmlCanvas.SKHtmlCanvas = view; |
|||
return view; |
|||
} |
|||
static Foo(canvas) { |
|||
const ctx = canvas.getContext("2d"); |
|||
ctx.fillStyle = "#FF0000"; |
|||
ctx.fillRect(0, 0, 150, 75); |
|||
} |
|||
static createWebGLContext(htmlCanvas) { |
|||
const contextAttributes = { |
|||
alpha: 1, |
|||
depth: 1, |
|||
stencil: 8, |
|||
antialias: 0, |
|||
premultipliedAlpha: 1, |
|||
preserveDrawingBuffer: 0, |
|||
preferLowPowerToHighPerformance: 0, |
|||
failIfMajorPerformanceCaveat: 0, |
|||
majorVersion: 2, |
|||
minorVersion: 0, |
|||
enableExtensionsByDefault: 1, |
|||
explicitSwapControl: 0, |
|||
renderViaOffscreenBackBuffer: 1 |
|||
}; |
|||
var GL = globalThis.AvaloniaGL; |
|||
let ctx = GL.createContext(htmlCanvas, contextAttributes); |
|||
if (!ctx && contextAttributes.majorVersion > 1) { |
|||
console.warn("Falling back to WebGL 1.0"); |
|||
contextAttributes.majorVersion = 1; |
|||
contextAttributes.minorVersion = 0; |
|||
ctx = GL.createContext(htmlCanvas, contextAttributes); |
|||
} |
|||
return ctx; |
|||
} |
|||
}; |
|||
|
|||
// modules/avalonia/runtime.ts
|
|||
var AvaloniaRuntime = class { |
|||
constructor(dotnetAssembly, api) { |
|||
this.dotnetAssembly = dotnetAssembly; |
|||
api.setModuleImports("avalonia.ts", { |
|||
Canvas |
|||
}); |
|||
} |
|||
}; |
|||
|
|||
// modules/avalonia.ts
|
|||
function createAvaloniaRuntime(api) { |
|||
return __async(this, null, function* () { |
|||
const dotnetAssembly = yield api.getAssemblyExports("Avalonia.Web.dll"); |
|||
return new AvaloniaRuntime(dotnetAssembly, api); |
|||
}); |
|||
} |
|||
export { |
|||
createAvaloniaRuntime |
|||
}; |
|||
//# sourceMappingURL=avalonia.js.map
|
|||
@ -1,10 +0,0 @@ |
|||
// modules/storage.ts
|
|||
var StorageProvider = class { |
|||
static isFileApiSupported() { |
|||
return globalThis.showOpenFilePicker !== void 0; |
|||
} |
|||
}; |
|||
export { |
|||
StorageProvider |
|||
}; |
|||
//# sourceMappingURL=storage.js.map
|
|||
Loading…
Reference in new issue