Merge branch 'main' into refactoring-fixes
This commit is contained in:
Коммит
ece9078109
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 40 KiB |
|
@ -52,6 +52,7 @@
|
|||
<ItemGroup Condition="$(TargetFramework.Contains('-windows'))">
|
||||
<!-- Required - WinUI does not yet have buildTransitive for everything -->
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.1.5" />
|
||||
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.0.3.1" />
|
||||
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ namespace AlohaKit.Gallery.ViewModels
|
|||
new SectionModel(typeof(ButtonView), "Button",
|
||||
"The Button responds to a tap or click."),
|
||||
|
||||
new SectionModel(typeof(CaptchaView), "Captcha",
|
||||
"Displays a distorted word."),
|
||||
|
||||
new SectionModel(typeof(CheckBoxView), "CheckBox",
|
||||
"CheckBox is a type of button that can either be checked or empty."),
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="AlohaKit.Gallery.Views.CaptchaView"
|
||||
xmlns:controls="clr-namespace:AlohaKit.Controls;assembly=AlohaKit"
|
||||
Title="Captcha">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<!-- DESCRIPTION -->
|
||||
<StackLayout
|
||||
Style="{StaticResource SectionContainerStyle}">
|
||||
<Label
|
||||
Text="Displays a distorted word."/>
|
||||
</StackLayout>
|
||||
<!-- FEATURES -->
|
||||
<StackLayout
|
||||
Grid.Row="1"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource LightBackgroundSecondaryColor}, Dark={StaticResource DarkBackgroundSecondaryColor}}"
|
||||
Style="{StaticResource SectionContainerStyle}">
|
||||
<Label
|
||||
Text="Features"
|
||||
Style="{StaticResource SectionTitleStyle}"/>
|
||||
<Label
|
||||
Text="- Can manage the word complexity."/>
|
||||
<Label
|
||||
Text="- All the colors can be customized."/>
|
||||
</StackLayout>
|
||||
<!-- SETTINGS -->
|
||||
<StackLayout
|
||||
Grid.Row="2"
|
||||
Style="{StaticResource SectionContainerStyle}">
|
||||
<Label
|
||||
Text="Settings"
|
||||
Style="{StaticResource SectionTitleStyle}"/>
|
||||
<StackLayout
|
||||
Orientation="Horizontal"
|
||||
Margin="0, 6">
|
||||
<Label
|
||||
Text="TextColor"
|
||||
VerticalOptions="Center"
|
||||
Style="{StaticResource SettingsTextStyle}"/>
|
||||
<Entry
|
||||
x:Name="TextColorEntry"
|
||||
Placeholder="TextColor"
|
||||
Text="#000000"
|
||||
TextColor="White"
|
||||
TextChanged="OnTextColorEntryTextChanged"
|
||||
Style="{StaticResource SettingsEntryStyle}"/>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<controls:Captcha
|
||||
Grid.Row="3"
|
||||
x:Name="Captcha"/>
|
||||
</Grid>
|
||||
</ContentPage>
|
|
@ -0,0 +1,42 @@
|
|||
namespace AlohaKit.Gallery.Views;
|
||||
|
||||
public partial class CaptchaView : ContentPage
|
||||
{
|
||||
public CaptchaView()
|
||||
{
|
||||
InitializeComponent();
|
||||
UpdateColors();
|
||||
}
|
||||
|
||||
void OnTextColorEntryTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
UpdateColors();
|
||||
}
|
||||
|
||||
void UpdateColors()
|
||||
{
|
||||
var textColor = GetColorFromString(TextColorEntry.Text);
|
||||
|
||||
if (textColor != null)
|
||||
{
|
||||
TextColorEntry.BackgroundColor = textColor;
|
||||
|
||||
Captcha.TextColor = textColor;
|
||||
}
|
||||
}
|
||||
|
||||
Color GetColorFromString(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
return Color.FromArgb(value[0].Equals('#') ? value : $"#{value}");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
namespace AlohaKit.Controls
|
||||
{
|
||||
public class Captcha : GraphicsView
|
||||
{
|
||||
public Captcha()
|
||||
{
|
||||
HeightRequest = 50;
|
||||
WidthRequest = 150;
|
||||
|
||||
Drawable = CaptchaDrawable = new CaptchaDrawable();
|
||||
}
|
||||
|
||||
public CaptchaDrawable CaptchaDrawable { get; set; }
|
||||
|
||||
public static readonly BindableProperty LevelProperty =
|
||||
BindableProperty.Create(nameof(Level), typeof(CaptchaLevel), typeof(Captcha), CaptchaLevel.Normal,
|
||||
propertyChanged: (bindableObject, oldValue, newValue) =>
|
||||
{
|
||||
if (newValue != null && bindableObject is Captcha captcha)
|
||||
{
|
||||
captcha.UpdateLevel();
|
||||
}
|
||||
});
|
||||
|
||||
public CaptchaLevel Level
|
||||
{
|
||||
get => (CaptchaLevel)GetValue(LevelProperty);
|
||||
set => SetValue(LevelProperty, value);
|
||||
}
|
||||
|
||||
public static readonly BindableProperty TextColorProperty =
|
||||
BindableProperty.Create(nameof(TextColor), typeof(Color), typeof(Captcha), Colors.Black,
|
||||
propertyChanged: (bindableObject, oldValue, newValue) =>
|
||||
{
|
||||
if (newValue != null && bindableObject is Captcha captcha)
|
||||
{
|
||||
captcha.UpdateTextColor();
|
||||
}
|
||||
});
|
||||
|
||||
public Color TextColor
|
||||
{
|
||||
get => (Color)GetValue(TextColorProperty);
|
||||
set => SetValue(TextColorProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnParentChanged()
|
||||
{
|
||||
base.OnParentChanged();
|
||||
|
||||
if (Parent != null)
|
||||
{
|
||||
UpdateLevel();
|
||||
UpdateTextColor();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateLevel()
|
||||
{
|
||||
if (CaptchaDrawable == null)
|
||||
return;
|
||||
|
||||
if (CaptchaDrawable.Level != Level)
|
||||
{
|
||||
CaptchaDrawable.Level = Level;
|
||||
|
||||
var word = GenerateRandomWord(GetWordLength(Level));
|
||||
CaptchaDrawable.Word = word;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateTextColor()
|
||||
{
|
||||
if (CaptchaDrawable == null)
|
||||
return;
|
||||
|
||||
CaptchaDrawable.TextColor = TextColor;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
string GenerateRandomWord(int length)
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
const string chars = "abcdefghijklmnopqrstuvwxyz" +
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
|
||||
"0123456789";
|
||||
|
||||
return new string(Enumerable.Repeat(chars, length)
|
||||
.Select(s => s[random.Next(s.Length)]).ToArray());
|
||||
}
|
||||
|
||||
int GetWordLength(CaptchaLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case CaptchaLevel.Weak:
|
||||
return 4;
|
||||
default:
|
||||
case CaptchaLevel.Normal:
|
||||
return 6;
|
||||
case CaptchaLevel.Strong:
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
namespace AlohaKit.Controls
|
||||
{
|
||||
public class CaptchaDrawable : IDrawable
|
||||
{
|
||||
public string Word { get; set; }
|
||||
public CaptchaLevel Level { get; set; }
|
||||
public Color TextColor { get; set; }
|
||||
|
||||
public void Draw(ICanvas canvas, RectF dirtyRect)
|
||||
{
|
||||
DrawText(canvas, dirtyRect);
|
||||
DrawArtifacts(canvas, dirtyRect);
|
||||
}
|
||||
|
||||
void DrawText(ICanvas canvas, RectF dirtyRect)
|
||||
{
|
||||
canvas.SaveState();
|
||||
|
||||
var height = dirtyRect.Height;
|
||||
var width = dirtyRect.Width;
|
||||
|
||||
int minLetterDistanceY = 0;
|
||||
int maxLetterDistanceY = (int)height / Word.Length;
|
||||
|
||||
int minLetterDistanceX = 6;
|
||||
int maxLetterDistanceX = (int)width / Word.Length;
|
||||
|
||||
var coordRandom = new Random();
|
||||
|
||||
var letterPoint = new PointF(coordRandom.Next(minLetterDistanceY, maxLetterDistanceX), height / 2);
|
||||
|
||||
foreach (var l in Word)
|
||||
{
|
||||
letterPoint.Y += coordRandom.Next(0, maxLetterDistanceY);
|
||||
|
||||
canvas.FontSize = 24;
|
||||
canvas.FontColor = TextColor;
|
||||
|
||||
canvas.DrawString(l.ToString(), letterPoint.X, letterPoint.Y,HorizontalAlignment.Center);
|
||||
|
||||
letterPoint.X += coordRandom.Next(minLetterDistanceX, maxLetterDistanceX);
|
||||
}
|
||||
|
||||
canvas.RestoreState();
|
||||
}
|
||||
|
||||
void DrawArtifacts(ICanvas canvas, RectF dirtyRect)
|
||||
{
|
||||
canvas.SaveState();
|
||||
|
||||
var randomLines = new Random();
|
||||
|
||||
for (var i = 0; i < GetArtifactLength(Level); i++)
|
||||
{
|
||||
var x1 = randomLines.Next(0, (int)dirtyRect.Width);
|
||||
var y1 = randomLines.Next(0, (int)dirtyRect.Height);
|
||||
var x2 = randomLines.Next(0, (int)dirtyRect.Width);
|
||||
var y2 = randomLines.Next(0, (int)dirtyRect.Height);
|
||||
|
||||
canvas.StrokeColor = TextColor.WithAlpha(0.8f);
|
||||
|
||||
var randomStrokeSize = new Random();
|
||||
canvas.StrokeSize = randomStrokeSize.Next(1, GetArtifactWidth(Level));
|
||||
|
||||
var p1 = new PointF(x1, y1);
|
||||
var p2 = new PointF(x2, y2);
|
||||
|
||||
canvas.DrawLine(p1, p2);
|
||||
}
|
||||
|
||||
canvas.RestoreState();
|
||||
}
|
||||
|
||||
int GetArtifactLength(CaptchaLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case CaptchaLevel.Weak:
|
||||
return 4;
|
||||
default:
|
||||
case CaptchaLevel.Normal:
|
||||
return 6;
|
||||
case CaptchaLevel.Strong:
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
int GetArtifactWidth(CaptchaLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case CaptchaLevel.Weak:
|
||||
return 2;
|
||||
default:
|
||||
case CaptchaLevel.Normal:
|
||||
return 3;
|
||||
case CaptchaLevel.Strong:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace AlohaKit.Controls
|
||||
{
|
||||
public enum CaptchaLevel
|
||||
{
|
||||
Weak,
|
||||
Normal,
|
||||
Strong
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче