Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ported Json Web Token Encoder Decoder to DevToys 2.0 #1078

Merged
merged 10 commits into from
Mar 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<PackageVersion Include="GirCore.Adw-1" Version="$(GirCore)" />
<PackageVersion Include="GirCore.Gtk-4.0" Version="$(GirCore)" />
<PackageVersion Include="GirCore.WebKit-6.0" Version="$(GirCore)" />
<PackageVersion Include="Markdig" Version="0.33.0" />
<PackageVersion Include="Markdig" Version="0.34.0" />
<PackageVersion Include="Markdown.ColorCode" Version="2.1.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="$(DotNetVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebView" Version="$(DotNetVersion)" />
Expand All @@ -28,6 +28,7 @@
<PackageVersion Include="Microsoft.Extensions.Logging" Version="$(DotNetVersion)" Condition="'$(UseMaui)' != 'true'" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(DotNetVersion)" Condition="'$(UseMaui)' != 'true'" />
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="$(DotNetVersion)" Condition="'$(UseMaui)' != 'true'" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.2.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageVersion Include="Microsoft.TypeScript.MSBuild" Version="5.3.2" />
Expand All @@ -38,13 +39,14 @@
<PackageVersion Include="Nuke.Common" Version="8.0.0" />
<PackageVersion Include="OneOf" Version="3.0.263" />
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.3" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="7.2.0" />
<PackageVersion Include="System.Text.Json" Version="$(DotNetVersion)" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageVersion Include="System.ComponentModel.Composition" Version="$(DotNetVersion)" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageVersion Include="xunit" Version="$(XUnit)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="$(XUnit)" />
<PackageVersion Include="YamlDotNet" Version="13.0.0" />
<PackageVersion Include="YamlDotNet" Version="13.7.1" />
<PackageVersion Include="ZXing.Net" Version="0.16.9" />
<PackageVersion Include="ZXing.Net.Bindings.ImageSharp.V3" Version="0.16.15" />
</ItemGroup>
Expand Down
105 changes: 97 additions & 8 deletions src/app/dev/DevToys.Api/Core/ResultInfo.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,107 @@
namespace DevToys.Api;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace DevToys.Api;

/// <summary>
/// Record to contain both whether the task was a success and the resulting data
/// </summary>
/// <typeparam name="T">Type of the result</typeparam>
/// <param name="Data">The resulting data or the task</param>
/// <param name="HasSucceeded">Whether the task succeeded</param>
public record ResultInfo<T>(T Data, bool HasSucceeded = true);
public record ResultInfo<T>
{
/// <summary>
/// The resulting data or the task
/// </summary>
public T? Data { get; }

/// <summary>
/// Whether the task succeeded
/// </summary>
public bool HasSucceeded { get; }

/// <summary>
/// Error message to display
/// </summary>
public string? ErrorMessage { get; }

/// <summary>
/// Record to contain both whether the task was a success and the resulting data
/// </summary>
/// <param name="data">The resulting data or the task</param>
/// <param name="hasSucceeded">Whether the task succeeded</param>
public ResultInfo(T data, bool hasSucceeded = true)
{
Data = data;
HasSucceeded = hasSucceeded;
}

/// <summary>
/// Record to contain both whether the task was a success and the resulting data
/// </summary>
/// <param name="data">The resulting data or the task</param>
/// <param name="errorMessage">The error message</param>
/// <param name="hasSucceeded">Whether the task succeeded</param>
public ResultInfo(T data, string errorMessage, bool hasSucceeded = false)
{
Data = data;
HasSucceeded = hasSucceeded;
ErrorMessage = errorMessage;
}
}

/// <summary>
/// Record to contain both whether the task was a success and the resulting data
/// </summary>
/// <typeparam name="T">Type of the result</typeparam>
/// <typeparam name="U">Type of the severity</typeparam>
/// <param name="Data">The resulting data or the task</param>
/// <param name="Severity">The severity of the result</param>
public record ResultInfo<T, U>(T Data, U Severity);
/// <typeparam name="ResultInfoSeverity">The severity of the result</typeparam>
public record ResultInfo<T, ResultInfoSeverity>
{
/// <summary>
/// The resulting data or the task
/// </summary>
public T? Data { get; }

/// <summary>
/// Severity of the result
/// </summary>
public ResultInfoSeverity Severity { get; }

/// <summary>
/// Error message to display
/// </summary>
public string? ErrorMessage { get; }

/// <summary>
/// Record to contain both whether the task was a success and the resulting data
/// </summary>
/// <param name="data">The resulting data or the task</param>
/// <param name="severity">The severity of the result</param>
public ResultInfo(T data, ResultInfoSeverity severity)
{
Data = data;
Severity = severity;
}

/// <summary>
/// Record to contain both whether the task was a success and the resulting data
/// </summary>
/// <param name="errorMessage">The error message</param>
/// <param name="severity">The severity of the result</param>
public ResultInfo(string errorMessage, ResultInfoSeverity severity)
{
Severity = severity;
ErrorMessage = errorMessage;
}

/// <summary>
/// Record to contain both whether the task was a success and the resulting data
/// </summary>
/// <param name="data">The resulting data or the task</param>
/// <param name="errorMessage">The error message</param>
/// <param name="severity">The severity of the result</param>
public ResultInfo(T data, string errorMessage, ResultInfoSeverity severity)
{
Data = data;
Severity = severity;
ErrorMessage = errorMessage;
}
}
8 changes: 8 additions & 0 deletions src/app/dev/DevToys.Api/Core/ResultInfoSeverity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DevToys.Api;

public enum ResultInfoSeverity
{
Success,
Warning,
Error
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ public interface IUIMultiLineTextInput : IUISingleLineTextInput
/// </summary>
IReadOnlyList<UIHighlightedTextSpan> HighlightedSpans { get; }

/// <summary>
/// Gets the list of tooltip to display on word hover.
/// </summary>
IReadOnlyList<UIHoverTooltip> HoverTooltips { get; }

/// <summary>
/// Gets the programming language name to use when colorizing the text in the control.
/// </summary>
Expand All @@ -33,6 +38,11 @@ public interface IUIMultiLineTextInput : IUISingleLineTextInput
/// </summary>
TextSpan Selection { get; }

/// <summary>
/// Raised when <see cref="HoverTooltips"/> is changed.
/// </summary>
event EventHandler? HoverTooltipChanged;

/// <summary>
/// Raised when <see cref="HighlightedSpans"/> is changed.
/// </summary>
Expand Down Expand Up @@ -62,6 +72,7 @@ public interface IUIMultiLineTextInput : IUISingleLineTextInput
[DebuggerDisplay($"Id = {{{nameof(Id)}}}, Text = {{{nameof(Text)}}}, SyntaxColorizationLanguageName = {{{nameof(SyntaxColorizationLanguageName)}}}")]
internal class UIMultilineTextInput : UISingleLineTextInput, IUIMultiLineTextInput
{
private IReadOnlyList<UIHoverTooltip>? _hoverTooltip;
private IReadOnlyList<UIHighlightedTextSpan>? _highlightedSpans;
private string? _syntaxColorizationLanguageName;
private bool _isExtendableToFullScreen;
Expand All @@ -79,6 +90,12 @@ public IReadOnlyList<UIHighlightedTextSpan> HighlightedSpans
internal set => SetPropertyValue(ref _highlightedSpans, value, HighlightedSpansChanged);
}

public IReadOnlyList<UIHoverTooltip> HoverTooltips
{
get => _hoverTooltip ?? Array.Empty<UIHoverTooltip>();
internal set => SetPropertyValue(ref _hoverTooltip, value, HoverTooltipChanged);
}

public string SyntaxColorizationLanguageName
{
get => _syntaxColorizationLanguageName ?? string.Empty;
Expand Down Expand Up @@ -122,6 +139,7 @@ internal set
}
}

public event EventHandler? HoverTooltipChanged;
public event EventHandler? HighlightedSpansChanged;
public event EventHandler? SyntaxColorizationLanguageNameChanged;
public event EventHandler? IsExtendableToFullScreenChanged;
Expand Down Expand Up @@ -176,6 +194,15 @@ public static IUIMultiLineTextInput Highlight(this IUIMultiLineTextInput element
return element;
}

/// <summary>
/// Sets the list of tooltips to display on Word hover in the text document.
/// </summary>
public static IUIMultiLineTextInput HoverTooltip(this IUIMultiLineTextInput element, params UIHoverTooltip[] tooltips)
{
((UIMultilineTextInput)element).HoverTooltips = tooltips;
return element;
}

/// <summary>
/// Sets the programming language name to use to colorize the text in the control.
/// </summary>
Expand Down
26 changes: 26 additions & 0 deletions src/app/dev/DevToys.Api/Tool/GUI/Components/UIHoverTooltip.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace DevToys.Api;

/// <summary>
/// Represents the Tooltip to display on hover
/// </summary>
public record UIHoverTooltip
{
/// <summary>
/// Contain the position of the span to search
/// </summary>
public TextSpan Span { get; }

/// <summary>
/// Contain the information we want to display on hover
/// </summary>
public string Description { get; }

/// <summary>
/// Create a new isntance of the <see cref="UIHoverTooltip"/> class.
/// </summary>
public UIHoverTooltip(TextSpan span, string description)
{
Span = span;
Description = description;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@
background-color: var(--card-background-color-secondary);
@include transition(transform 250ms cubic-bezier(1, 1, 0, 1));
transform: translateY(-100%);

.expander-card {
background-color: transparent;
}
}

&[aria-expanded='true'] {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using DevToys.Blazor.Components.Monaco;
using DevToys.Blazor.Components.Monaco.Editor;
Expand Down Expand Up @@ -519,6 +520,13 @@ internal async Task<ComputedEditorOptions> GetOptionsAsync()
internal ValueTask<EditorOptions> GetRawOptionsAsync()
=> JSRuntime.InvokeAsync<EditorOptions>("devtoys.MonacoEditor.getRawOptions", Id);

/// <summary>
/// Get value of the current model attached to this editor.
/// See <see cref="TextModel.GetWordAtPosition(Position)"/>
/// </summary>
internal ValueTask<WordAtPosition> GetWordAtPositionAsync(string position)
=> JSRuntime.InvokeAsync<WordAtPosition>("devtoys.MonacoEditor.getWordAtPosition", position);

/// <summary>
/// Get value of the current model attached to this editor.
/// See <see cref="TextModel.GetValue(EndOfLinePreference?, bool?)"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
namespace DevToys.Blazor.Components.UIElements;
using DevToys.Api;

namespace DevToys.Blazor.Components.UIElements;

public partial class UIGridPresenter : ComponentBase
{
[Parameter]
public IUIGrid UIGrid { get; set; } = default!;

protected override void OnInitialized()
{
base.OnInitialized();

UIGrid.CellsChanged += UIGrid_CellsChanged;
}

public void Dispose()
{
UIGrid.CellsChanged += UIGrid_CellsChanged;
}

private void UIGrid_CellsChanged(object? sender, EventArgs e)
{
StateHasChanged();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using DevToys.Blazor.Components.Monaco;
using DevToys.Blazor.Components.Monaco.Editor;
using Microsoft.VisualBasic;
using Range = DevToys.Blazor.Components.Monaco.Range;

namespace DevToys.Blazor.Components.UIElements;

Expand All @@ -26,6 +28,7 @@ protected override void OnInitialized()
UIMultiLineTextInput.IsReadOnlyChanged += UIMultiLineTextInput_IsReadOnlyChanged;
UIMultiLineTextInput.SelectionChanged += UIMultiLineTextInput_SelectionChanged;
UIMultiLineTextInput.HighlightedSpansChanged += UIMultiLineTextInput_HighlightedSpansChanged;
UIMultiLineTextInput.HoverTooltipChanged += UIMultiLineTextInput_HoverTooltipChanged;
}

public override ValueTask DisposeAsync()
Expand All @@ -35,6 +38,7 @@ public override ValueTask DisposeAsync()
UIMultiLineTextInput.IsReadOnlyChanged -= UIMultiLineTextInput_IsReadOnlyChanged;
UIMultiLineTextInput.SelectionChanged -= UIMultiLineTextInput_SelectionChanged;
UIMultiLineTextInput.HighlightedSpansChanged -= UIMultiLineTextInput_HighlightedSpansChanged;
UIMultiLineTextInput.HoverTooltipChanged -= UIMultiLineTextInput_HoverTooltipChanged;

return base.DisposeAsync();
}
Expand Down Expand Up @@ -133,6 +137,52 @@ private async void UIMultiLineTextInput_HighlightedSpansChanged(object? sender,
}
}

private async void UIMultiLineTextInput_HoverTooltipChanged(object? sender, EventArgs e)
{
await _monacoInitializationAwaiter.Task;

using (await _semaphore.WaitAsync(CancellationToken.None))
{
TextModel model = await _monacoEditor.GetModelAsync();

if (model is not null)
{
var decorations = new ModelDeltaDecoration[UIMultiLineTextInput.HoverTooltips.Count];

for (int i = 0; i < decorations.Length; i++)
{
UIHoverTooltip hoverTooltip = UIMultiLineTextInput.HoverTooltips[i];
Position selectionStartPosition = await model.GetPositionAtAsync(JSRuntime, hoverTooltip.Span.StartPosition);
Position selectionEndPosition = await model.GetPositionAtAsync(JSRuntime, hoverTooltip.Span.EndPosition);

decorations[i]
= new ModelDeltaDecoration
{
Range = new Monaco.Range
{
StartLineNumber = selectionStartPosition.LineNumber,
StartColumn = selectionStartPosition.Column,
EndLineNumber = selectionEndPosition.LineNumber,
EndColumn = selectionEndPosition.Column
},
Options = new ModelDecorationOptions
{
HoverMessage = new[]
{
new MarkdownString()
{
Value = hoverTooltip.Description
}
}
}
};
}

await _monacoEditor.ReplaceAllDecorationsByAsync(decorations);
}
}
}

private async Task OnMonacoEditorTextChangedAsync(ModelContentChangedEvent ev)
{
if (ev.Changes is not null)
Expand Down
Loading