Merge branch 'main' into refactoring-fixes
This commit is contained in:
Коммит
ece9078109
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 40 KiB |
|
@ -52,6 +52,7 @@
|
||||||
<ItemGroup Condition="$(TargetFramework.Contains('-windows'))">
|
<ItemGroup Condition="$(TargetFramework.Contains('-windows'))">
|
||||||
<!-- Required - WinUI does not yet have buildTransitive for everything -->
|
<!-- Required - WinUI does not yet have buildTransitive for everything -->
|
||||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.1.5" />
|
<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" />
|
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.0.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@ namespace AlohaKit.Gallery.ViewModels
|
||||||
new SectionModel(typeof(ButtonView), "Button",
|
new SectionModel(typeof(ButtonView), "Button",
|
||||||
"The Button responds to a tap or click."),
|
"The Button responds to a tap or click."),
|
||||||
|
|
||||||
|
new SectionModel(typeof(CaptchaView), "Captcha",
|
||||||
|
"Displays a distorted word."),
|
||||||
|
|
||||||
new SectionModel(typeof(CheckBoxView), "CheckBox",
|
new SectionModel(typeof(CheckBoxView), "CheckBox",
|
||||||
"CheckBox is a type of button that can either be checked or empty."),
|
"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
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче