Skip to content

Commit 838d9a5

Browse files
authored
Merge branch 'main' into MediaElementOptionService
2 parents 1168302 + 064ac34 commit 838d9a5

25 files changed

+824
-213
lines changed

samples/CommunityToolkit.Maui.Sample/MauiProgram.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public static MauiApp CreateMauiApp()
5555
.UseMauiCommunityToolkit(static options =>
5656
{
5757
options.SetShouldEnableSnackbarOnWindows(true);
58+
options.SetPopupDefaults(new DefaultPopupSettings());
59+
options.SetPopupOptionsDefaults(new DefaultPopupOptionsSettings());
5860
})
5961
#else
6062
.UseMauiCommunityToolkit(static options =>
@@ -270,6 +272,7 @@ static void RegisterViewsAndViewModels(in IServiceCollection services)
270272
// Add Popups
271273
services.AddTransientPopup<ApplyToDerivedTypesPopup>();
272274
services.AddTransientPopup<ButtonPopup>();
275+
services.AddTransientPopup<ComplexPopup, ComplexPopupViewModel>();
273276
services.AddTransientPopup<CsharpBindingPopup, CsharpBindingPopupViewModel>();
274277
services.AddTransientPopup<DynamicStyleInheritancePopup>();
275278
services.AddTransientPopup<DynamicStylePopup>();

samples/CommunityToolkit.Maui.Sample/Pages/Views/Popup/PopupsPage.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848

4949
<Button Text="OnDisappearing Popup" Clicked="HandleOnDisappearingPopupClicked" />
5050

51+
<Button Text="Complex Popup" Clicked="HandleComplexPopupClicked" />
52+
5153
</VerticalStackLayout>
5254
</ScrollView>
5355
</ContentPage.Content>

samples/CommunityToolkit.Maui.Sample/Pages/Views/Popup/PopupsPage.xaml.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using CommunityToolkit.Maui.Alerts;
12
using CommunityToolkit.Maui.Extensions;
23
using CommunityToolkit.Maui.Markup;
34
using CommunityToolkit.Maui.Sample.Pages.Views.Popup;
@@ -130,4 +131,35 @@ async void HandleSelfClosingPopupButtonClicked(object? sender, EventArgs e)
130131

131132
await this.ClosePopupAsync();
132133
}
134+
135+
async void HandleComplexPopupClicked(object? sender, EventArgs e)
136+
{
137+
var complexPopupOpenedCancellationTokenSource = new CancellationTokenSource();
138+
var complexPopupOptions = new PopupOptions
139+
{
140+
BindingContext = this.BindingContext,
141+
Shape = new RoundRectangle
142+
{
143+
CornerRadius = new CornerRadius(4),
144+
StrokeThickness = 12,
145+
Stroke = Colors.Orange
146+
}
147+
};
148+
complexPopupOptions.SetBinding<PopupsViewModel, Color>(PopupOptions.PageOverlayColorProperty, static x => x.PageOverlayBackgroundColor);
149+
150+
var popupResultTask = popupService.ShowPopupAsync<ComplexPopup, string>(Navigation, complexPopupOptions, CancellationToken.None);
151+
152+
// Trigger Command in ViewModel to Rotate PopupOptions.PageOverlayColorProperty
153+
BindingContext.ComplexPopupOpenedCommand.Execute(complexPopupOpenedCancellationTokenSource.Token);
154+
155+
var popupResult = await popupResultTask;
156+
await complexPopupOpenedCancellationTokenSource.CancelAsync();
157+
158+
if (!popupResult.WasDismissedByTappingOutsideOfPopup)
159+
{
160+
// Display Popup Result as a Toast
161+
await Toast.Make($"You entered {popupResult.Result}").Show(CancellationToken.None);
162+
}
163+
164+
}
133165
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using CommunityToolkit.Mvvm.ComponentModel;
2+
using CommunityToolkit.Mvvm.Input;
3+
4+
namespace CommunityToolkit.Maui.Sample.ViewModels.Views;
5+
6+
public partial class ComplexPopupViewModel(IPopupService popupService) : ObservableObject
7+
{
8+
readonly IPopupService popupService = popupService;
9+
readonly INavigation navigation = Application.Current?.Windows[0].Page?.Navigation ?? throw new InvalidOperationException("Unable to locate INavigation");
10+
11+
[ObservableProperty, NotifyCanExecuteChangedFor(nameof(ReturnButtonTappedCommand))]
12+
public partial string ReturnText { get; set; } = string.Empty;
13+
14+
bool CanReturnButtonExecute => ReturnText?.Length > 0;
15+
16+
[RelayCommand(CanExecute = nameof(CanReturnButtonExecute))]
17+
async Task OnReturnButtonTapped(CancellationToken token)
18+
{
19+
await popupService.ClosePopupAsync<string>(navigation, ReturnText, token);
20+
}
21+
}

samples/CommunityToolkit.Maui.Sample/ViewModels/Views/Popup/PopupsViewModel.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
using CommunityToolkit.Mvvm.Input;
1+
using CommunityToolkit.Mvvm.ComponentModel;
2+
using CommunityToolkit.Mvvm.Input;
23

34
namespace CommunityToolkit.Maui.Sample.ViewModels.Views;
45

56
public partial class PopupsViewModel(IPopupService popupService) : BaseViewModel
67
{
78
static INavigation currentNavigation => Application.Current?.Windows[0].Page?.Navigation ?? throw new InvalidOperationException($"{nameof(Page.Navigation)} not found");
89

10+
[ObservableProperty]
11+
public partial Color PageOverlayBackgroundColor { get; set; } = Colors.Orange.WithAlpha(0.2f);
12+
913
[RelayCommand]
1014
void OnCsharpBindingPopup()
1115
{
@@ -28,4 +32,15 @@ Task OnShowPopupContent(CancellationToken token)
2832
{
2933
return popupService.ShowPopupAsync<PopupContentViewModel>(currentNavigation, cancellationToken: token);
3034
}
35+
36+
[RelayCommand]
37+
async Task OnComplexPopupOpened(CancellationToken token)
38+
{
39+
// Rotate the PopupOptions.PageOverlayBackgroundColor every second
40+
while (!token.IsCancellationRequested)
41+
{
42+
PageOverlayBackgroundColor = Color.FromRgba(Random.Shared.NextDouble(), Random.Shared.NextDouble(), Random.Shared.NextDouble(), 0.2f);
43+
await Task.Delay(TimeSpan.FromSeconds(1), CancellationToken.None);
44+
}
45+
}
3146
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<mct:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
5+
xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
6+
xmlns:vm="clr-namespace:CommunityToolkit.Maui.Sample.ViewModels.Views"
7+
xmlns:system="clr-namespace:System;assembly=System.Runtime"
8+
x:Class="CommunityToolkit.Maui.Sample.Views.Popups.ComplexPopup"
9+
x:DataType="vm:ComplexPopupViewModel"
10+
x:TypeArguments="system:String">
11+
12+
<mct:Popup.Resources>
13+
<mct:AppThemeColor Light="Black" Dark="Black" x:Key="TextColor" />
14+
</mct:Popup.Resources>
15+
16+
<VerticalStackLayout Spacing="12">
17+
18+
<Label Text="Complex Popup"
19+
TextColor="{mct:AppThemeResource TextColor}"
20+
FontSize="24"
21+
HorizontalTextAlignment="Center"
22+
VerticalTextAlignment="Center"
23+
HorizontalOptions="Center"
24+
VerticalOptions="Center"
25+
FontAttributes="Bold" />
26+
27+
<Label x:Name="DescriptionLabel"
28+
Text="This text will change upon the Opened event firing"
29+
TextColor="{mct:AppThemeResource TextColor}"
30+
HorizontalTextAlignment="Center"
31+
VerticalTextAlignment="Center"
32+
HorizontalOptions="Center"
33+
VerticalOptions="Center"
34+
LineBreakMode="WordWrap" />
35+
36+
<Entry Placeholder="Enter text here then click Return"
37+
HorizontalOptions="Center"
38+
VerticalOptions="Center"
39+
Text="{Binding ReturnText, Mode=OneWayToSource}"
40+
TextColor="{mct:AppThemeResource TextColor}"/>
41+
42+
<Button Text="Return"
43+
HorizontalOptions="Center"
44+
VerticalOptions="Center"
45+
Command="{Binding ReturnButtonTappedCommand}" />
46+
47+
</VerticalStackLayout>
48+
49+
</mct:Popup>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using CommunityToolkit.Maui.Sample.ViewModels.Views;
2+
using CommunityToolkit.Maui.Views;
3+
4+
namespace CommunityToolkit.Maui.Sample.Views.Popups;
5+
6+
public partial class ComplexPopup : Popup<string>
7+
{
8+
public ComplexPopup(ComplexPopupViewModel viewModel)
9+
{
10+
InitializeComponent();
11+
12+
CanBeDismissedByTappingOutsideOfPopup = false;
13+
14+
BindingContext = viewModel;
15+
Opened += HandlePopupOpened;
16+
}
17+
18+
async void HandlePopupOpened(object? sender, EventArgs e)
19+
{
20+
// Delay for one second to ensure the user sees the previous text
21+
await Task.Delay(TimeSpan.FromSeconds(1));
22+
DescriptionLabel.Text = "This Popup demonstrates constructor injection to pass in a value using Dependency Injection using PopupService, demonstrates how to use the Opened event to trigger an action once the Popup appears, demonstrates how to bind to PopupOptions, and demonstrates how to return a result.";
23+
}
24+
}

src/CommunityToolkit.Maui.UnitTests/BaseTest.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ protected virtual void Dispose(bool isDisposing)
8484
options.SetShouldSuppressExceptionsInAnimations(false);
8585
options.SetShouldSuppressExceptionsInBehaviors(false);
8686
options.SetShouldSuppressExceptionsInConverters(false);
87+
options.SetPopupDefaults(new DefaultPopupSettings());
88+
options.SetPopupOptionsDefaults(new DefaultPopupOptionsSettings());
8789

8890
// Restore default MediaElementOptions
8991
var mediaElementOptions = new MediaElementOptions();

src/CommunityToolkit.Maui.UnitTests/BaseViewTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ static void InitializeServicesAndSetMockApplication(out IServiceProvider service
7474
#endregion
7575

7676
#region Register Services for PopupServiceTests
77-
7877
appBuilder.Services.AddTransientPopup<LongLivedSelfClosingPopup, LongLivedMockPageViewModel>();
7978
appBuilder.Services.AddTransientPopup<ShortLivedSelfClosingPopup, ShortLivedMockPageViewModel>();
8079
appBuilder.Services.AddTransientPopup<GarbageCollectionHeavySelfClosingPopup, MockPageViewModel>();

src/CommunityToolkit.Maui.UnitTests/Extensions/AppBuilderExtensionsTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public void ConfirmOptionsDefaultValue()
2121
Assert.False(Options.ShouldSuppressExceptionsInBehaviors);
2222
Assert.False(Options.ShouldSuppressExceptionsInConverters);
2323
Assert.False(isAndroidDialogFragmentServiceInitialized);
24+
Assert.Equal(Options.DefaultPopupSettings, new DefaultPopupSettings());
25+
Assert.Equal(Options.DefaultPopupOptionsSettings, new DefaultPopupOptionsSettings());
2426

2527
Core.AppBuilderExtensions.ShouldUseStatusBarBehaviorOnAndroidModalPageOptionCompleted -= HandleShouldUseStatusBarBehaviorOnAndroidModalPageOptionCompleted;
2628

@@ -50,6 +52,8 @@ public void ConfirmDefaultValueRemainWhenOptionsNull()
5052
Assert.False(Options.ShouldSuppressExceptionsInBehaviors);
5153
Assert.False(Options.ShouldSuppressExceptionsInConverters);
5254
Assert.True(isAndroidDialogFragmentServiceInitialized);
55+
Assert.Equal(Options.DefaultPopupSettings, new DefaultPopupSettings());
56+
Assert.Equal(Options.DefaultPopupOptionsSettings, new DefaultPopupOptionsSettings());
5357

5458
void HandleShouldUseStatusBarBehaviorOnAndroidModalPageOptionCompleted(object? sender, EventArgs e)
5559
{
@@ -88,6 +92,25 @@ public void UseMauiCommunityToolkit_ShouldAssignValues()
8892
// Arrange
8993
var builder = MauiApp.CreateBuilder();
9094
bool isAndroidDialogFragmentServiceInitialized = false;
95+
var defaultPopupSettings = new DefaultPopupSettings
96+
{
97+
CanBeDismissedByTappingOutsideOfPopup = true,
98+
BackgroundColor = Colors.Orange,
99+
HorizontalOptions = LayoutOptions.End,
100+
VerticalOptions = LayoutOptions.Start,
101+
Margin = 72,
102+
Padding = 4
103+
};
104+
105+
var defaultPopupOptionsSettings = new DefaultPopupOptionsSettings
106+
{
107+
CanBeDismissedByTappingOutsideOfPopup = true,
108+
OnTappingOutsideOfPopup = () => Console.WriteLine("Hello World"),
109+
PageOverlayColor = Colors.Green,
110+
Shadow = null,
111+
Shape = null
112+
};
113+
91114
Core.AppBuilderExtensions.ShouldUseStatusBarBehaviorOnAndroidModalPageOptionCompleted += HandleShouldUseStatusBarBehaviorOnAndroidModalPageOptionCompleted;
92115

93116
// Act
@@ -98,6 +121,8 @@ public void UseMauiCommunityToolkit_ShouldAssignValues()
98121
options.SetShouldSuppressExceptionsInBehaviors(!Options.ShouldSuppressExceptionsInBehaviors);
99122
options.SetShouldSuppressExceptionsInConverters(!Options.ShouldSuppressExceptionsInConverters);
100123
options.SetShouldUseStatusBarBehaviorOnAndroidModalPage(!Core.Options.ShouldUseStatusBarBehaviorOnAndroidModalPage);
124+
options.SetPopupDefaults(defaultPopupSettings);
125+
options.SetPopupOptionsDefaults(defaultPopupOptionsSettings);
101126
});
102127

103128
// Assert
@@ -107,6 +132,8 @@ public void UseMauiCommunityToolkit_ShouldAssignValues()
107132
Assert.True(Options.ShouldSuppressExceptionsInBehaviors);
108133
Assert.True(Options.ShouldSuppressExceptionsInConverters);
109134
Assert.False(isAndroidDialogFragmentServiceInitialized);
135+
Assert.Equal(defaultPopupSettings, Options.DefaultPopupSettings);
136+
Assert.Equal(defaultPopupOptionsSettings, Options.DefaultPopupOptionsSettings);
110137

111138
Core.AppBuilderExtensions.ShouldUseStatusBarBehaviorOnAndroidModalPageOptionCompleted -= HandleShouldUseStatusBarBehaviorOnAndroidModalPageOptionCompleted;
112139

0 commit comments

Comments
 (0)