This commit is contained in:
TheXamlGuy
2024-04-26 23:05:36 +01:00
parent 9f90ef693d
commit bc55c4649b
206 changed files with 3106 additions and 3204 deletions
-1
View File
@@ -34,4 +34,3 @@ public class NavigationContext(INavigationContextCollection contexts) :
}
}
}
@@ -2,5 +2,4 @@
public record ComponentConfiguration
{
}
@@ -18,7 +18,6 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, THe
TDescription description,
TAction action) : base(provider, factory, mediator, publisher, subscriber, disposer)
{
}
public Task Handle(Changed<TConfiguration> args,
@@ -58,6 +57,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, TAc
Value = valueDelegate.Invoke(configuration);
return base.Activated();
}
public Task Handle(Changed<TConfiguration> args,
CancellationToken cancellationToken = default)
{
-1
View File
@@ -15,7 +15,6 @@ public class ComponentHost(IServiceProvider services,
public void Dispose()
{
}
public async Task StartAsync(CancellationToken cancellationToken = default)
+1 -2
View File
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
namespace Toolkit.Foundation;
@@ -12,7 +12,6 @@ public class ConfigurationChangedHandler<TConfiguration, TValue>(ConfigurationVa
{
if (configurationValue.TryUpdate(configuration, out TValue value))
{
}
}
+1 -2
View File
@@ -1,5 +1,4 @@
namespace Toolkit.Foundation;
namespace Toolkit.Foundation;
public record Create<TValue>(TValue Value);
+1 -1
View File
@@ -144,12 +144,12 @@ public static class Test
services.AddTransient(provider =>
provider.GetRequiredKeyedService<IConfigurationDescriptor<TConfiguration>>(section).Value);
}
});
return builder;
}
}
public class DefaultBuilder :
HostBuilder
{
@@ -56,20 +56,26 @@ public class DictionaryStringObjectJsonConverter :
return date;
}
return reader.GetString();
case JsonTokenType.False:
return false;
case JsonTokenType.True:
return true;
case JsonTokenType.Null:
return null;
case JsonTokenType.Number:
if (reader.TryGetInt64(out var result))
{
return result;
}
return reader.GetDecimal();
case JsonTokenType.StartObject:
return Read(ref reader, null!, options);
case JsonTokenType.StartArray:
List<object?> list = [];
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
@@ -77,6 +83,7 @@ public class DictionaryStringObjectJsonConverter :
list.Add(ExtractValue(ref reader, options));
}
return list;
default:
return default;
}
+2 -2
View File
@@ -1,6 +1,6 @@
using System.Reactive.Disposables;
using System.Collections;
using System.Collections;
using System.Collections.Concurrent;
using System.Reactive.Disposables;
namespace Toolkit.Foundation;
@@ -2,5 +2,4 @@
public interface IComponentConfigurationViewModel
{
}
@@ -2,4 +2,3 @@
public interface IComponentScopeCollection :
IList<ComponentScopeDescriptor>;
@@ -4,4 +4,3 @@ public interface IComponentScopeProvider
{
ComponentScopeDescriptor? Get(string key);
}
+1 -2
View File
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Hosting;
namespace Toolkit.Foundation;
-1
View File
@@ -2,5 +2,4 @@
public interface IContentTemplate
{
}
-1
View File
@@ -5,7 +5,6 @@ public interface IFactory<TParameter, TService>
TService? Create(TParameter value);
}
public interface IFactory<TService>
{
TService? Create();
+6 -8
View File
@@ -1,11 +1,9 @@
namespace Toolkit.Foundation;
namespace Toolkit.Foundation
{
public interface IMediator
{
Task<TResponse?> Handle<TRequest, TResponse>(TRequest request,
CancellationToken cancellationToken = default)
where TRequest : notnull;
Task<object?> Handle(object request, CancellationToken
cancellationToken = default);
Task<object?> Handle(object message, CancellationToken cancellationToken = default);
Task<TResponse?> Handle<TRequest, TResponse>(TRequest request, CancellationToken cancellationToken = default) where TRequest : notnull;
}
}
-1
View File
@@ -4,4 +4,3 @@ public interface INavigation
{
Type Type { get; set; }
}
-1
View File
@@ -7,4 +7,3 @@ public interface INavigationScope
Task NavigateBackAsync(object? context, CancellationToken cancellationToken = default);
}
@@ -9,4 +9,3 @@ public interface IConfirmation
{
Task<bool> Confirm();
}
+1
View File
@@ -19,6 +19,7 @@ public interface IPublisher
object key,
CancellationToken cancellationToken = default)
where TMessage : notnull;
Task PublishUI<TMessage>(object key,
CancellationToken cancellationToken = default)
where TMessage : new();
-6
View File
@@ -1,6 +0,0 @@
namespace Toolkit.Foundation;
public interface IRequest<out TResponse> :
IMessage;
public interface IRequest : IRequest<Unit>;
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Configuration.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.FileProviders.Physical;
+1 -2
View File
@@ -1,5 +1,4 @@
namespace Toolkit.Foundation;
public record KeyAccelerator(VirtualKey Key,
VirtualKey[]? Modifiers = null) :
IRequest;
VirtualKey[]? Modifiers = null);
+1 -1
View File
@@ -27,7 +27,7 @@ public class Mediator(IServiceProvider provider) :
public Task<object?> Handle(object message,
CancellationToken cancellationToken = default)
{
if (message.GetType().GetInterface(typeof(IRequest<>).Name) is Type requestType &&
if (message.GetType().GetInterface(message.GetType().Name) is Type requestType &&
requestType.GetGenericArguments().Length == 1)
{
Type responseType = requestType.GetGenericArguments()[0];
@@ -18,5 +18,3 @@ public class NavigateBackHandler(IComponentScopeProvider provider) :
}
}
}
-7
View File
@@ -1,7 +0,0 @@
namespace Toolkit.Foundation;
public record NavigatingFrom(object Content) :
IRequest<IReadOnlyCollection<object>>;
public record NavigatingTo(object Content) :
IRequest<IReadOnlyCollection<object>>;
-1
View File
@@ -5,4 +5,3 @@ public record Navigation :
{
public required Type Type { get; set; }
}
-1
View File
@@ -101,4 +101,3 @@ public class NavigationScope(IPublisher publisher,
}
}
}
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
using System.Reactive.Disposables;
namespace Toolkit.Foundation;
public partial class ObservableCollectionViewModel<TViewModel> :
ObservableObject,
IObservableCollectionViewModel<TViewModel>,
@@ -113,7 +114,6 @@ public partial class ObservableCollectionViewModel<TViewModel> :
}
catch (InvalidCastException)
{
}
this[index] = item!;
@@ -172,7 +172,6 @@ public partial class ObservableCollectionViewModel<TViewModel> :
}
catch (InvalidCastException)
{
}
Add(item!);
+1
View File
@@ -88,6 +88,7 @@ public class Publisher(ISubscriptionManager subscriptionManager,
where TMessage : notnull =>
Publish(message, args => dispatcher.InvokeAsync(async () => await args()),
key, cancellationToken);
public Task PublishUI<TMessage>(CancellationToken cancellationToken = default)
where TMessage : new() =>
Publish(new TMessage(), args => dispatcher.InvokeAsync(async () => await args()),
+1 -2
View File
@@ -1,5 +1,4 @@
namespace Toolkit.Foundation;
namespace Toolkit.Foundation;
public record Remove<TValue>(TValue Value);
+1 -2
View File
@@ -1,5 +1,4 @@
namespace Toolkit.Foundation;
namespace Toolkit.Foundation;
public record Replace<TValue>(int Index, TValue Value);
+1 -1
View File
@@ -1,3 +1,3 @@
namespace Toolkit.Foundation;
public record StartProcess(string Process) : IRequest;
public record StartProcess(string Process);
+1 -3
View File
@@ -1,6 +1,4 @@
using System.Reflection;
namespace Toolkit.Foundation;
namespace Toolkit.Foundation;
public class SubscriptionManager(SubscriptionCollection subscriptions) :
ISubscriptionManager
-1
View File
@@ -15,7 +15,6 @@ public partial class ValueViewModel<TValue>(IServiceProvider provider,
protected virtual void OnChanged(TValue? value)
{
}
partial void OnValueChanged(TValue? value) => OnChanged(value);
+6 -3
View File
@@ -23,7 +23,6 @@ internal static class ComparisonLogic
}
}
if (leftOperand is IComparable leftComparableOperand &&
rightOperand is IComparable rightComparableOperand)
{
@@ -35,6 +34,7 @@ internal static class ComparisonLogic
case ComparisonConditionType.Equal:
result = Equals(leftOperand, rightOperand);
break;
case ComparisonConditionType.NotEqual:
result = !Equals(leftOperand, rightOperand);
break;
@@ -54,11 +54,9 @@ internal static class ComparisonLogic
}
catch (FormatException)
{
}
catch (InvalidCastException)
{
}
if (convertedOperand == null)
@@ -74,18 +72,23 @@ internal static class ComparisonLogic
case ComparisonConditionType.Equal:
result = comparison == 0;
break;
case ComparisonConditionType.GreaterThan:
result = comparison > 0;
break;
case ComparisonConditionType.GreaterThanOrEqual:
result = comparison >= 0;
break;
case ComparisonConditionType.LessThan:
result = comparison < 0;
break;
case ComparisonConditionType.LessThanOrEqual:
result = comparison <= 0;
break;
case ComparisonConditionType.NotEqual:
result = comparison != 0;
break;
@@ -1,6 +1,5 @@
using Avalonia;
using Avalonia.Metadata;
using Toolkit.UI.Avalonia;
namespace Toolkit.UI.Avalonia;
+3 -1
View File
@@ -51,6 +51,7 @@ public class NavigateAction :
get => GetValue(RouteProperty);
set => SetValue(RouteProperty, value);
}
public string Scope
{
get => GetValue(ScopeProperty);
@@ -67,7 +68,8 @@ public class NavigateAction :
if (control.DataContext is IObservableViewModel observableViewModel)
{
object[] parameters = [.. Parameters ?? Enumerable.Empty<object?>(), ..
object[] parameters = [.. Parameters ?? Enumerable.Empty<object?>(),
..
ParameterBindings is { Count: > 0 } ?
ParameterBindings.Select(binding => new KeyValuePair<string, object>(binding.Key, binding.Value)).ToArray() :
Enumerable.Empty<KeyValuePair<string, object>>()];
+1
View File
@@ -16,6 +16,7 @@ public class ParameterBinding :
get => GetValue(KeyProperty);
set => SetValue(KeyProperty, value);
}
public object Value
{
get => GetValue(ValueProperty);
@@ -63,7 +63,6 @@ public class BlurBehind :
public void Dispose()
{
}
public bool Equals(ICustomDrawOperation? other) =>
@@ -105,11 +104,9 @@ public class BlurBehind :
canvas.DrawRect(0, 0, (float)bounds.Width, (float)bounds.Height, blurSnapPaint);
}
}
}
}
}
}
}
@@ -242,7 +242,6 @@ public class CarouselView :
{
itemVisuals[(newIndex + i - 2 + columnCount) % columnCount].Offset =
new Vector3((float)(offsets[i] - centreOffset), 0, 0);
}
};
@@ -253,6 +252,7 @@ public class CarouselView :
}
}
}
private void OnCollectionChanged(object? sender,
NotifyCollectionChangedEventArgs args) => ArrangeItems(newIndex);
@@ -1,9 +1,9 @@
using Avalonia.Media.Imaging;
using Avalonia.Styling;
using Avalonia;
using SukiUI.Utilities.Background;
using Avalonia.Platform;
using Avalonia;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using Avalonia.Styling;
using SukiUI.Utilities.Background;
namespace Toolkit.UI.Controls.Avalonia;
@@ -1,6 +1,7 @@
using Avalonia.Threading;
namespace Toolkit.UI.Controls.Avalonia;
public class ScopedBatchHelper
{
private DispatcherTimer? timer;
@@ -1,7 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Gma.QrCodeNet.Encoding;
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.DataEncodation;
public static class CharCountIndicatorTable
@@ -1,4 +1,3 @@
using System;
using Gma.QrCodeNet.Encoding.DataEncodation.InputRecognition;
using Gma.QrCodeNet.Encoding.Terminate;
using Gma.QrCodeNet.Encoding.Versions;
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
namespace Gma.QrCodeNet.Encoding.DataEncodation;
public sealed class ECISet
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.DataEncodation;
/// <summary>
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
namespace Gma.QrCodeNet.Encoding.DataEncodation.InputRecognition;
public static class InputRecognise
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.DataEncodation.InputRecognition;
public static class ModeEncodeCheck
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.EncodingRegion;
/// <remarks>ISO/IEC 18004:2000 Chapter 8.7.3 Page 46</remarks>
@@ -1,4 +1,3 @@
using System;
using Gma.QrCodeNet.Encoding.Masking;
namespace Gma.QrCodeNet.Encoding.EncodingRegion;
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.EncodingRegion;
/// <summary>
@@ -1,6 +1,4 @@
using Gma.QrCodeNet.Encoding.ReedSolomon;
using System;
using System.Collections.Generic;
namespace Gma.QrCodeNet.Encoding.ErrorCorrection;
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding;
/// <summary>
@@ -1,4 +1,3 @@
using System;
using Gma.QrCodeNet.Encoding.EncodingRegion;
namespace Gma.QrCodeNet.Encoding.Masking;
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking;
public abstract class Pattern : BitMatrix
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking;
internal class Pattern0 : Pattern
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking;
internal class Pattern1 : Pattern
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking;
internal class Pattern2 : Pattern
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking;
internal class Pattern3 : Pattern
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking;
internal class Pattern4 : Pattern
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking;
internal class Pattern5 : Pattern
@@ -1,4 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking;
internal class Pattern6 : Pattern
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking;
internal class Pattern7 : Pattern
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
namespace Gma.QrCodeNet.Encoding.Masking;
internal class PatternFactory
@@ -1,5 +1,3 @@
using System.Linq;
namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
internal static class MatrixScoreCalculator
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
/// <summary>
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
namespace Gma.QrCodeNet.Encoding.Masking.Scoring;
/// <summary>
@@ -1,5 +1,4 @@
using System.Collections;
using System.Collections.Generic;
namespace Gma.QrCodeNet.Encoding;
@@ -1,7 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Gma.QrCodeNet.Encoding.Positioning.Stencils;
internal class AlignmentPattern : PatternStencilBase
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Positioning.Stencils;
internal class DarkDotAtLeftBottom : PatternStencilBase
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Positioning.Stencils;
internal abstract class PatternStencilBase : BitMatrix
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Positioning.Stencils;
internal class TimingPattern : PatternStencilBase
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.ReedSolomon;
/// <summary>
@@ -1,5 +1,3 @@
using System.Collections.Generic;
namespace Gma.QrCodeNet.Encoding.ReedSolomon;
/// <summary>
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.ReedSolomon;
internal sealed class Polynomial
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.ReedSolomon;
internal sealed class ReedSolomonEncoder
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Terminate;
internal static class Terminator
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding;
public class TriStateMatrix : BitMatrixBase
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Versions;
internal struct ErrorCorrectionBlocks
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Versions;
internal struct QRCodeVersion
@@ -1,4 +1,3 @@
using System;
using Gma.QrCodeNet.Encoding.DataEncodation;
namespace Gma.QrCodeNet.Encoding.Versions;
@@ -1,5 +1,3 @@
using System;
namespace Gma.QrCodeNet.Encoding.Versions;
public static class VersionTable
+22 -7
View File
@@ -1,7 +1,3 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
@@ -10,6 +6,7 @@ using Avalonia.Controls.Primitives;
using Avalonia.Media;
using Avalonia.Threading;
using Gma.QrCodeNet.Encoding;
using System.Collections;
namespace Toolkit.UI.Controls.Avalonia;
@@ -20,18 +17,22 @@ namespace Toolkit.UI.Controls.Avalonia;
public class QrCode : Control
{
#region Properties
/// <summary>
/// Property for the Background brush (i.e. the area that has no data)
/// </summary>
public static readonly StyledProperty<IBrush?> BackgroundProperty = Border.BackgroundProperty.AddOwner<QrCode>();
/// <summary>
/// Property for the Foreground brush (i.e. the actual data)
/// </summary>
public static readonly StyledProperty<IBrush?> ForegroundProperty = TextElement.ForegroundProperty.AddOwner<TemplatedControl>();
/// <summary>
/// Property indicating how rounded the corners will be
/// </summary>
public static readonly StyledProperty<CornerRadius> CornerRadiusProperty = Border.CornerRadiusProperty.AddOwner<QrCode>();
/// <summary>
/// Property indicating the Quiet Zone (distance between the edge of the control and where the data actually starts)
///
@@ -41,6 +42,7 @@ public class QrCode : Control
/// with this as the code itself it not meant for public consumption.
/// </summary>
public static readonly StyledProperty<Thickness> PaddingProperty = Decorator.PaddingProperty.AddOwner<QrCode>();
/// <summary>
/// Property indicating whether the Quiet Zone of 4 modules should be added to the QR Code as additional padding. Default: True
///
@@ -49,12 +51,14 @@ public class QrCode : Control
/// disabled and a fixed <see cref="Padding"/> can be set instead to have more control over the layout.
/// </summary>
public static readonly StyledProperty<bool> IsQuietZoneEnabledProperty = AvaloniaProperty.Register<QrCode, bool>(nameof(IsQuietZoneEnabled), true);
/// <summary>
/// Property indicating the Error Correction Code of the generated data. Default: Medium
///
/// Note: See <see cref="EccLevel" /> for the specific definitions of each value.
/// </summary>
public static readonly StyledProperty<EccLevel> ErrorCorrectionProperty = AvaloniaProperty.Register<QrCode, EccLevel>(nameof(ErrorCorrection), EccLevel.Medium);
/// <summary>
/// Property for the data represented in the QRCode
/// </summary>
@@ -66,52 +70,61 @@ public class QrCode : Control
get => GetValue(BackgroundProperty) ?? Brushes.White;
set => SetValue(BackgroundProperty, value);
}
/// <inheritdoc cref="ForegroundProperty" />
public IBrush Foreground
{
get => GetValue(ForegroundProperty) ?? Brushes.Black;
set => SetValue(ForegroundProperty, value);
}
/// <inheritdoc cref="CornerRadiusProperty" />
public CornerRadius CornerRadius
{
get => GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
}
/// <inheritdoc cref="PaddingProperty" />
public Thickness Padding
{
get => GetValue(PaddingProperty);
set => SetValue(PaddingProperty, value);
}
/// <inheritdoc cref="IsQuietZoneEnabledProperty" />
public bool IsQuietZoneEnabled
{
get => GetValue(IsQuietZoneEnabledProperty);
set => SetValue(IsQuietZoneEnabledProperty, value);
}
/// <inheritdoc cref="ErrorCorrectionProperty" />
public EccLevel ErrorCorrection
{
get => GetValue(ErrorCorrectionProperty);
set => SetValue(ErrorCorrectionProperty, value);
}
/// <inheritdoc cref="DataProperty" />
public string? Data
{
get => GetValue(DataProperty);
set => SetValue(DataProperty, value);
}
#endregion
#endregion Properties
/// <summary>
/// Engine to actually calculate the bit matrix of the QRCode. Currently a Nuget package, but official support may wish to implement and remove such dependency
/// </summary>
private static readonly QrEncoder QrCodeGenerator = new();
/// <summary>
/// A cache of currently set bits in the bit matrix. This is used to potentially speed up processing.
/// </summary>
private readonly Hashtable _setBitsTable = new();
/// <summary>
/// A cache of the last encoded QRCode. This is used to reuse the last generated data whenever a style property like Width, Height or Padding was changed.
/// </summary>
@@ -119,6 +132,7 @@ public class QrCode : Control
// QRCode specs mandate a standard 4-symbol-sized space on each side of the data. We support custom Padding and will ignore this zone when processing
private int QuietZoneCount => IsQuietZoneEnabled ? 4 : 0;
private int QuietMargin => QuietZoneCount * 2;
/// <summary>
@@ -213,7 +227,6 @@ public class QrCode : Control
_oldQrCodeGeometry = null;
InvalidateVisual();
});
}
@@ -694,7 +707,6 @@ public class QrCode : Control
// Render background over the foreground as the geometry has "cut outs" that allow the foreground to show through
context.DrawGeometry(Background, null, newGeometry);
}
}
/// <summary>
@@ -706,14 +718,17 @@ public class QrCode : Control
/// The lowest level of error correction where up to ~7% of data can be be recovered if lost and uses the least amount of symbols to represent the data
/// </summary>
Lowest,
/// <summary>
/// The standard level of error correction where up to ~15% of data can be be recovered if lost and represents a good compromise between a small size and reliability
/// </summary>
Medium,
/// <summary>
/// A high readability level of error correction where up to ~25% of data can be be recovered if lost but requires a larger footprint to represent the data
/// </summary>
Quality,
/// <summary>
/// The maximum level of error correction where up to ~30% of data can be be recovered if lost and represents the maximum achievable reliability
/// </summary>