-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
247 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
using IS4.SFI.Tools; | ||
using System; | ||
using System.IO; | ||
using System.Runtime.ExceptionServices; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace IS4.SFI.Application.Tools | ||
{ | ||
/// <summary> | ||
/// Provides a custom stream with a buffer mapped to external storage. | ||
/// </summary> | ||
public abstract class MappedStream : MemoryStream | ||
{ | ||
bool loaded; | ||
|
||
/// <summary> | ||
/// Pre-loads the data into the stream. | ||
/// </summary> | ||
/// <returns>A task representing the operation.</returns> | ||
protected abstract ValueTask Load(); | ||
|
||
/// <summary> | ||
/// Stores the data into the external storage. | ||
/// </summary> | ||
/// <param name="data">The data in the stream.</param> | ||
/// <returns>A task representing the operation.</returns> | ||
protected abstract ValueTask Store(ArraySegment<byte> data); | ||
|
||
/// <inheritdoc/> | ||
public override void Close() | ||
{ | ||
if(!loaded) | ||
{ | ||
var valueTask = Store(this.GetData()); | ||
if(valueTask.IsCompletedSuccessfully) | ||
{ | ||
return; | ||
}else if(valueTask.IsFaulted) | ||
{ | ||
var task = valueTask.AsTask(); | ||
if(task.Exception.InnerExceptions.Count == 1) | ||
{ | ||
ExceptionDispatchInfo.Capture(task.Exception.InnerException).Throw(); | ||
} | ||
throw task.Exception; | ||
}else try{ | ||
valueTask.AsTask().Wait(); | ||
}catch(SynchronizationLockException) | ||
{ | ||
|
||
}catch(PlatformNotSupportedException) | ||
{ | ||
|
||
} | ||
} | ||
|
||
base.Close(); | ||
} | ||
|
||
private async ValueTask Initialize() | ||
{ | ||
if(!loaded) | ||
{ | ||
loaded = true; | ||
await Load(); | ||
Position = 0; | ||
} | ||
} | ||
|
||
private void InitializeSync() | ||
{ | ||
var valueTask = Initialize(); | ||
if(valueTask.IsCompletedSuccessfully) | ||
{ | ||
return; | ||
}else if(valueTask.IsFaulted) | ||
{ | ||
var task = valueTask.AsTask(); | ||
if(task.Exception.InnerExceptions.Count == 1) | ||
{ | ||
ExceptionDispatchInfo.Capture(task.Exception.InnerException).Throw(); | ||
} | ||
throw task.Exception; | ||
}else{ | ||
valueTask.AsTask().Wait(); | ||
} | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override int Read(byte[] buffer, int offset, int count) | ||
{ | ||
InitializeSync(); | ||
return base.Read(buffer, offset, count); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) | ||
{ | ||
InitializeSync(); | ||
return base.BeginRead(buffer, offset, count, callback, state); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public async override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) | ||
{ | ||
await Initialize(); | ||
return await base.ReadAsync(buffer, offset, count, cancellationToken); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override int ReadByte() | ||
{ | ||
InitializeSync(); | ||
return base.ReadByte(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,57 @@ | ||
using IS4.SFI.Tools; | ||
using IS4.SFI.Application.Tools; | ||
using System; | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using System.Threading.Tasks.Schedulers; | ||
using System.Windows.Forms; | ||
|
||
namespace IS4.SFI.ConsoleApp | ||
{ | ||
internal class ClipboardStream : MemoryStream | ||
internal class ClipboardStream : MappedStream | ||
{ | ||
public override void Close() | ||
static readonly Encoding encoding = Encoding.UTF8; | ||
|
||
readonly TaskScheduler staTaskScheduler = new StaTaskScheduler(1); | ||
|
||
static void SetText(string text) | ||
{ | ||
var array = this.GetData(); | ||
Clipboard.SetText(text, TextDataFormat.UnicodeText); | ||
} | ||
|
||
var text = Encoding.UTF8.GetString(array); | ||
static string GetText() | ||
{ | ||
var text = Clipboard.GetText(TextDataFormat.UnicodeText); | ||
if(String.IsNullOrEmpty(text)) | ||
{ | ||
return Clipboard.GetText(TextDataFormat.Text); | ||
} | ||
return text; | ||
} | ||
|
||
protected async override ValueTask Store(ArraySegment<byte> data) | ||
{ | ||
var text = encoding.GetString(data); | ||
if(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) | ||
{ | ||
Clipboard.SetText(text, TextDataFormat.UnicodeText); | ||
SetText(text); | ||
}else{ | ||
var thread = new Thread(() => Clipboard.SetText(text, TextDataFormat.UnicodeText)); | ||
thread.SetApartmentState(ApartmentState.STA); | ||
thread.Start(); | ||
thread.Join(); | ||
await Task.Factory.StartNew(() => SetText(text), CancellationToken.None, 0, staTaskScheduler); | ||
} | ||
} | ||
|
||
base.Close(); | ||
protected async override ValueTask Load() | ||
{ | ||
string text; | ||
if(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) | ||
{ | ||
text = GetText(); | ||
}else{ | ||
text = await Task.Factory.StartNew(GetText, CancellationToken.None, 0, staTaskScheduler); | ||
} | ||
using var writer = new StreamWriter(this, encoding: encoding, leaveOpen: true); | ||
writer.Write(text); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,34 @@ | ||
using IS4.SFI.Tools; | ||
using IS4.SFI.Application.Tools; | ||
using Microsoft.JSInterop; | ||
using System; | ||
using System.IO; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace IS4.SFI.WebApp | ||
{ | ||
internal class ClipboardStream : MemoryStream | ||
internal class ClipboardStream : MappedStream | ||
{ | ||
static readonly Encoding encoding = Encoding.UTF8; | ||
|
||
readonly IJSInProcessRuntime runtime; | ||
|
||
public ClipboardStream(IJSInProcessRuntime runtime) | ||
{ | ||
this.runtime = runtime; | ||
} | ||
|
||
public override void Close() | ||
protected override ValueTask Store(ArraySegment<byte> data) | ||
{ | ||
var array = this.GetData(); | ||
|
||
var text = Encoding.UTF8.GetString(array); | ||
|
||
runtime.InvokeVoid("navigator.clipboard.writeText", text); | ||
var text = encoding.GetString(data); | ||
return runtime.InvokeVoidAsync("navigator.clipboard.writeText", text); | ||
} | ||
|
||
base.Close(); | ||
protected async override ValueTask Load() | ||
{ | ||
var text = await runtime.InvokeAsync<string>("navigator.clipboard.readText"); | ||
using var writer = new StreamWriter(this, encoding: encoding, leaveOpen: true); | ||
writer.Write(text); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters