Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ public enum CoachmarkAnimationStyle
Spotlight,
Arrow,
Morph
}
}
31 changes: 15 additions & 16 deletions Maui.FreakyUXKit/Maui.FreakyUXKit/Coachmark/FreakyPopupPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
var info = e.Info;
var rect = info.Rect;
var highlightRect = _currentBounds;
float highX = highlightRect.Left + highlightRect.Width / 2;
float highY = highlightRect.Top + highlightRect.Height / 2;
float highX = highlightRect.Left + (highlightRect.Width / 2);
float highY = highlightRect.Top + (highlightRect.Height / 2);

if (CurrentTargetView == null || OverlayView == null)
return;
Expand Down Expand Up @@ -191,7 +191,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
RenderStaticHighlight(canvas, rect, highX, highY, highlightRect);
break;
}

}

private void RenderStaticHighlight(SKCanvas canvas, SKRect rect, float highX, float highY, SKRect highlightRect)
Expand Down Expand Up @@ -293,7 +292,7 @@ private void RenderArrowPointer(SKCanvas canvas, SKRect highlightRect, SKRect ov
// Direction vector and distance from overlay center to highlight center
var dx = highlightCenter.X - overlayCenter.X;
var dy = highlightCenter.Y - overlayCenter.Y;
var totalDistance = MathF.Sqrt(dx * dx + dy * dy);
var totalDistance = MathF.Sqrt((dx * dx) + (dy * dy));
if (totalDistance == 0)
return;

Expand All @@ -303,18 +302,18 @@ private void RenderArrowPointer(SKCanvas canvas, SKRect highlightRect, SKRect ov
var edgePoint = GetClosestPointOnRect(highlightRect, overlayCenter);

// Distance from overlayCenter to edgePoint
var distToEdge = MathF.Sqrt((edgePoint.X - overlayCenter.X) * (edgePoint.X - overlayCenter.X) +
(edgePoint.Y - overlayCenter.Y) * (edgePoint.Y - overlayCenter.Y));
var distToEdge = MathF.Sqrt(((edgePoint.X - overlayCenter.X) * (edgePoint.X - overlayCenter.X)) +
((edgePoint.Y - overlayCenter.Y) * (edgePoint.Y - overlayCenter.Y)));

// Calculate start point - padded 20% away from overlayCenter along direction
var start = new SKPoint(
overlayCenter.X + direction.X * (totalDistance * paddingPercent),
overlayCenter.Y + direction.Y * (totalDistance * paddingPercent));
overlayCenter.X + (direction.X * (totalDistance * paddingPercent)),
overlayCenter.Y + (direction.Y * (totalDistance * paddingPercent)));

// Calculate end point - 20% *before* edgePoint along the direction vector
var end = new SKPoint(
overlayCenter.X + direction.X * (distToEdge * (1 - paddingPercent)),
overlayCenter.Y + direction.Y * (distToEdge * (1 - paddingPercent)));
overlayCenter.X + (direction.X * (distToEdge * (1 - paddingPercent))),
overlayCenter.Y + (direction.Y * (distToEdge * (1 - paddingPercent))));

canvas.DrawArrow(start, end, ArrowColor.ToSKColor(), ArrowStyle, ArrowStrokeWidth);
}
Expand Down Expand Up @@ -399,16 +398,16 @@ private void DrawShapeStroke(SKCanvas canvas, HighlightShape shape, float center
canvas.DrawCircle(centerX, centerY, radius, paint);
break;
case HighlightShape.Ellipse:
canvas.DrawOval(new SKRect(centerX - width / 2, centerY - height / 2,
centerX + width / 2, centerY + height / 2), paint);
canvas.DrawOval(new SKRect(centerX - (width / 2), centerY - (height / 2),
centerX + (width / 2), centerY + (height / 2)), paint);
break;
case HighlightShape.Rectangle:
canvas.DrawRect(new SKRect(centerX - width / 2, centerY - height / 2,
centerX + width / 2, centerY + height / 2), paint);
canvas.DrawRect(new SKRect(centerX - (width / 2), centerY - (height / 2),
centerX + (width / 2), centerY + (height / 2)), paint);
break;
default: // RoundRectangle
canvas.DrawRoundRect(new SKRoundRect(new SKRect(centerX - width / 2, centerY - height / 2,
centerX + width / 2, centerY + height / 2), CornerRadius), paint);
canvas.DrawRoundRect(new SKRoundRect(new SKRect(centerX - (width / 2), centerY - (height / 2),
centerX + (width / 2), centerY + (height / 2)), CornerRadius), paint);
break;
}
}
Expand Down
1 change: 0 additions & 1 deletion Maui.FreakyUXKit/Maui.FreakyUXKit/Hosting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ public static class Hosting
public static MauiAppBuilder UseFreakyUXKit(this MauiAppBuilder builder)
{
builder
.UseMauiCommunityToolkit()
.UseSkiaSharp();
return builder;
}
Expand Down
29 changes: 29 additions & 0 deletions Maui.FreakyUXKit/Maui.FreakyUXKit/IntroView/FreakyIntroStep.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Windows.Input;
using Microsoft.Maui.Controls.Shapes;
namespace Maui.FreakyUXKit;

public class FreakyIntroStep
{
public string TitleText { get; set; }
public FormattedString TitleFormattedText { get; set; }
public string SubTitleText { get; set; }
public FormattedString SubtitleFormattedText { get; set; }
public ImageSource ImageSource { get; set; }
public Style ImageStyle { get; set; }
public Style TitleLabelStyle { get; set; }
public Style SubtitleLabelStyle { get; set; }
public string LeftButtonText { get; set; }
public ICommand LeftButtonCommand { get; set; }
public bool IsLeftButtonVisible { get; set; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Initialize boolean properties with default values

Boolean properties should be initialized to ensure predictable behavior, especially for visibility properties.

-    public bool IsLeftButtonVisible { get; set; }
+    public bool IsLeftButtonVisible { get; set; } = true;
     public string CenterButtonText { get; set; }
     public ICommand CenterButtonCommand { get; set; }
-    public bool IsCenterButtonVisible { get; set; }
+    public bool IsCenterButtonVisible { get; set; } = true;
     public string RightButtonText { get; set; }
     public ICommand RightButtonCommand { get; set; }
-    public bool IsRightButtonVisible { get; set; }
+    public bool IsRightButtonVisible { get; set; } = true;

Also applies to: 20-20, 23-23

🤖 Prompt for AI Agents
In Maui.FreakyUXKit/Maui.FreakyUXKit/IntroView/FreakyIntroStep.cs at lines 17,
20, and 23, the boolean properties are not explicitly initialized. Initialize
these boolean properties with default values (true or false as appropriate) in
their declarations to ensure predictable behavior, especially for
visibility-related properties.

public string CenterButtonText { get; set; }
public ICommand CenterButtonCommand { get; set; }
public bool IsCenterButtonVisible { get; set; }
public string RightButtonText { get; set; }
public ICommand RightButtonCommand { get; set; }
public bool IsRightButtonVisible { get; set; }
public Brush BottomBackground { get; set; } = Colors.Transparent;
public Brush ImageBackground { get; set; } = Colors.Transparent;
public Brush Background { get; set; } = Brush.Transparent;
public Color BackgroundAnimationColor { get; set; } = Colors.Transparent;
public IShape BottomStrokeShape { get; set; } = new RoundRectangle() { CornerRadius = new CornerRadius(30, 30, 0, 0) };
}
112 changes: 112 additions & 0 deletions Maui.FreakyUXKit/Maui.FreakyUXKit/IntroView/FreakyIntroView.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentView
x:Class="Maui.FreakyUXKit.FreakyIntroView"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Maui.FreakyUXKit"
xmlns:skia="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls"
x:Name="this">
<AbsoluteLayout>
<skia:SKCanvasView
x:Name="canvasView"
AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
AbsoluteLayout.LayoutFlags="All"
IgnorePixelScaling="true"
InputTransparent="True"
PaintSurface="OnPaintSurface" />
<CarouselView
Grid.Row="0"
AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Transparent"
HorizontalScrollBarVisibility="Never"
IndicatorView="indicatorView"
IsScrollAnimated="{Binding IsScrollAnimated, Source={x:Reference this}, x:DataType=local:FreakyIntroView}"
IsSwipeEnabled="{Binding IsSwipeEnabled, Source={x:Reference this}, x:DataType=local:FreakyIntroView}"
ItemsSource="{Binding ItemsSource, Source={x:Reference this}, x:DataType=local:FreakyIntroView}"
ItemsUpdatingScrollMode="KeepLastItemInView"
Loop="False"
Position="{Binding Position, Source={x:Reference this}, x:DataType=local:FreakyIntroView}"
PositionChanged="CarouselView_PositionChanged"
VerticalScrollBarVisibility="Never">
<CarouselView.ItemsLayout>
<LinearItemsLayout
Orientation="Horizontal"
SnapPointsAlignment="Start"
SnapPointsType="MandatorySingle" />
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate x:DataType="local:FreakyIntroStep">
<Grid Background="{Binding Background}" RowDefinitions="3*, 2*">
<Image
Grid.Row="0"
Margin="10"
Background="{Binding ImageBackground}"
Source="{Binding ImageSource}"
Style="{Binding ImageStyle}" />
<Border
Grid.Row="1"
Padding="10"
Background="{Binding BottomBackground}"
StrokeShape="{Binding BottomStrokeShape}"
StrokeThickness="0">
<Grid RowDefinitions="*,Auto">
<VerticalStackLayout Grid.Row="0" Spacing="10">
<Label
FontSize="Large"
FormattedText="{Binding TitleFormattedText}"
HorizontalTextAlignment="Center"
Style="{Binding TitleLabelStyle}"
Text="{Binding TitleText}" />
<Label
FontSize="Medium"
FormattedText="{Binding SubtitleFormattedText}"
HorizontalTextAlignment="Center"
Style="{Binding SubtitleLabelStyle}"
Text="{Binding SubTitleText}" />
</VerticalStackLayout>
<FlexLayout
Grid.Row="1"
AlignItems="Center"
Direction="{Binding ButtonsDirection, Source={x:Reference this}, x:DataType=local:FreakyIntroView}"
HeightRequest="50"
JustifyContent="SpaceBetween"
Wrap="NoWrap">
<Button
Margin="5,0"
Command="{Binding LeftButtonCommand}"
FlexLayout.Grow="1"
IsVisible="{Binding IsLeftButtonVisible}"
Text="{Binding LeftButtonText}" />
<Button
Margin="5,0"
Command="{Binding CenterButtonCommand}"
FlexLayout.Grow="1"
IsVisible="{Binding IsCenterButtonVisible}"
Text="{Binding CenterButtonText}" />
<Button
Margin="5,0"
Command="{Binding RightButtonCommand}"
FlexLayout.Grow="1"
IsVisible="{Binding IsRightButtonVisible}"
Text="{Binding RightButtonText}" />
</FlexLayout>
</Grid>

</Border>
</Grid>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView
x:Name="indicatorView"
AbsoluteLayout.LayoutBounds="0.5,0.85,AutoSize,AutoSize"
AbsoluteLayout.LayoutFlags="PositionProportional"
HideSingle="True"
IndicatorColor="{Binding IndicatorColor, Source={x:Reference this}, x:DataType=local:FreakyIntroView}"
IndicatorSize="{Binding IndicatorSize, Source={x:Reference this}, x:DataType=local:FreakyIntroView}"
IndicatorsShape="{Binding IndicatorsShape, Source={x:Reference this}, x:DataType=local:FreakyIntroView}"
MaximumVisible="{Binding IndicatorMaximumVisible, Source={x:Reference this}, x:DataType=local:FreakyIntroView}"
SelectedIndicatorColor="{Binding SelectedIndicatorColor, Source={x:Reference this}, x:DataType=local:FreakyIntroView}" />
</AbsoluteLayout>
</ContentView>
Loading