diff --git a/samples/XCT.Sample/Pages/Base/BasePage.cs b/samples/XCT.Sample/Pages/Base/BasePage.cs index 8e7a5071f..5d24e0070 100644 --- a/samples/XCT.Sample/Pages/Base/BasePage.cs +++ b/samples/XCT.Sample/Pages/Base/BasePage.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using System.Windows.Input; using Xamarin.CommunityToolkit.ObjectModel; using Xamarin.CommunityToolkit.Sample.Models; @@ -9,7 +10,13 @@ namespace Xamarin.CommunityToolkit.Sample.Pages public class BasePage : ContentPage { public BasePage() => - NavigateCommand = CommandFactory.Create(sectionModel => Navigation.PushAsync(PreparePage(sectionModel))); + NavigateCommand = CommandFactory.Create(sectionModel => + { + if (sectionModel != null) + return Navigation.PushAsync(PreparePage(sectionModel)); + + return Task.CompletedTask; + }); public Color DetailColor { get; set; } diff --git a/samples/XCT.Sample/Pages/TestCases/MediaElementSourcePage.xaml.cs b/samples/XCT.Sample/Pages/TestCases/MediaElementSourcePage.xaml.cs index 35799ea00..55352ae45 100644 --- a/samples/XCT.Sample/Pages/TestCases/MediaElementSourcePage.xaml.cs +++ b/samples/XCT.Sample/Pages/TestCases/MediaElementSourcePage.xaml.cs @@ -12,6 +12,6 @@ class MediaElementViewModel : BindableObject { public string VideoAsString { get; set; } = "https://tipcalculator.appwithkiss.com/video/Hint_1_2_EN_12.mov"; - public MediaSource VideoAsMediaSource => MediaSource.FromUri(VideoAsString); + public MediaSource? VideoAsMediaSource => MediaSource.FromUri(VideoAsString); } } \ No newline at end of file diff --git a/samples/XCT.Sample/Resx/AppResources.Designer.cs b/samples/XCT.Sample/Resx/AppResources.Designer.cs index 150cb2cf6..2f28eebc9 100644 --- a/samples/XCT.Sample/Resx/AppResources.Designer.cs +++ b/samples/XCT.Sample/Resx/AppResources.Designer.cs @@ -10,48 +10,35 @@ namespace Xamarin.CommunityToolkit.Sample.Resx { using System; + using System.Reflection; - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class AppResources { - private static global::System.Resources.ResourceManager resourceMan; + private static System.Resources.ResourceManager resourceMan; - private static global::System.Globalization.CultureInfo resourceCulture; + private static System.Globalization.CultureInfo resourceCulture; - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal AppResources() { } - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Resources.ResourceManager ResourceManager { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public static System.Resources.ResourceManager ResourceManager { get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Xamarin.CommunityToolkit.Sample.Resx.AppResources", typeof(AppResources).Assembly); + if (object.Equals(null, resourceMan)) { + System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Xamarin.CommunityToolkit.Sample.Resx.AppResources", typeof(AppResources).Assembly); resourceMan = temp; } return resourceMan; } } - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Globalization.CultureInfo Culture { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + public static System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -60,45 +47,30 @@ public class AppResources { } } - /// - /// Looks up a localized string similar to Change language below, hit Save and see the texts in this page change. This will not affect the rest of the application, it just serves as a demo.. - /// public static string ChangeLanguage { get { return ResourceManager.GetString("ChangeLanguage", resourceCulture); } } - /// - /// Looks up a localized string similar to English. - /// public static string English { get { return ResourceManager.GetString("English", resourceCulture); } } - /// - /// Looks up a localized string similar to Save. - /// - public static string Save { + public static string Spanish { get { - return ResourceManager.GetString("Save", resourceCulture); + return ResourceManager.GetString("Spanish", resourceCulture); } } - /// - /// Looks up a localized string similar to Spanish. - /// - public static string Spanish { + public static string Save { get { - return ResourceManager.GetString("Spanish", resourceCulture); + return ResourceManager.GetString("Save", resourceCulture); } } - /// - /// Looks up a localized string similar to App version: {0}. - /// public static string Version { get { return ResourceManager.GetString("Version", resourceCulture); diff --git a/samples/XCT.Sample/ViewModels/Converters/ItemSelectedEventArgsViewModel.cs b/samples/XCT.Sample/ViewModels/Converters/ItemSelectedEventArgsViewModel.cs index 6569e2053..101fb04ab 100644 --- a/samples/XCT.Sample/ViewModels/Converters/ItemSelectedEventArgsViewModel.cs +++ b/samples/XCT.Sample/ViewModels/Converters/ItemSelectedEventArgsViewModel.cs @@ -16,6 +16,6 @@ public class ItemSelectedEventArgsViewModel }; public ICommand ItemSelectedCommand { get; } = - CommandFactory.Create(person => Application.Current.MainPage.DisplayAlert("Item Tapped: ", person.Name, "Cancelf")); + CommandFactory.Create(person => Application.Current.MainPage.DisplayAlert("Item Tapped: ", person?.Name, "Cancel")); } } \ No newline at end of file diff --git a/samples/XCT.Sample/ViewModels/Converters/ItemTappedEventArgsViewModel.cs b/samples/XCT.Sample/ViewModels/Converters/ItemTappedEventArgsViewModel.cs index 42500cfd7..eedfb6995 100644 --- a/samples/XCT.Sample/ViewModels/Converters/ItemTappedEventArgsViewModel.cs +++ b/samples/XCT.Sample/ViewModels/Converters/ItemTappedEventArgsViewModel.cs @@ -15,7 +15,7 @@ public class ItemTappedEventArgsViewModel }; public ICommand ItemTappedCommand { get; } = - CommandFactory.Create(person => Application.Current.MainPage.DisplayAlert("Item Tapped: ", person.Name, "Cancel")); + CommandFactory.Create(person => Application.Current.MainPage.DisplayAlert("Item Tapped: ", person?.Name, "Cancel")); } public class Person diff --git a/samples/XCT.Sample/ViewModels/Views/PopupControlViewModel.cs b/samples/XCT.Sample/ViewModels/Views/PopupControlViewModel.cs index 85e924594..5a42b7ffd 100644 --- a/samples/XCT.Sample/ViewModels/Views/PopupControlViewModel.cs +++ b/samples/XCT.Sample/ViewModels/Views/PopupControlViewModel.cs @@ -35,7 +35,7 @@ async void OnDisplayPopup(Type popupType) { var view = (VisualElement)Activator.CreateInstance(popupType); - if (view is Popup popup) + if (view is Popup popup) { var result = await Navigation.ShowPopupAsync(popup); await Application.Current.MainPage.DisplayAlert("Popup Result", result, "OKAY"); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Converters/ByteArrayToImageSourceConverter_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Converters/ByteArrayToImageSourceConverter_Tests.cs index a30e013ee..83be6ff6d 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Converters/ByteArrayToImageSourceConverter_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Converters/ByteArrayToImageSourceConverter_Tests.cs @@ -22,7 +22,7 @@ public void ByteArrayToImageSourceConverter() var result = byteArrayToImageSourceConverter.Convert(byteArray, typeof(ByteArrayToImageSourceConverter), null, CultureInfo.CurrentCulture); - Assert.True(StreamEquals(GetStreamFromImageSource((ImageSource)result), memoryStream)); + Assert.True(StreamEquals(GetStreamFromImageSource((ImageSource?)result), memoryStream)); } [Theory] @@ -34,28 +34,32 @@ public void InvalidConverterValuesReturnsNull(object value) Assert.Throws(() => byteArrayToImageSourceConverter.Convert(value, typeof(ByteArrayToImageSourceConverter), null, CultureInfo.CurrentCulture)); } - Stream GetStreamFromImageSource(ImageSource imageSource) + Stream? GetStreamFromImageSource(ImageSource? imageSource) { - var streamImageSource = (StreamImageSource)imageSource; + var streamImageSource = (StreamImageSource?)imageSource; var cancellationToken = System.Threading.CancellationToken.None; - var task = streamImageSource.Stream(cancellationToken); - return task.Result; + var task = streamImageSource?.Stream(cancellationToken); + return task?.Result; } - bool StreamEquals(Stream a, Stream b) + bool StreamEquals(Stream? a, Stream? b) { if (a == b) return true; - if (a == null || - b == null || - a.Length != b.Length) + if (a == null + || b == null + || a.Length != b.Length) + { return false; + } for (var i = 0; i < a.Length; i++) + { if (a.ReadByte() != b.ReadByte()) return false; + } return true; } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/DelegateWeakEventManager_Delegate_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/DelegateWeakEventManager_Delegate_Tests.cs index 417cca45c..2b424fd2a 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/DelegateWeakEventManager_Delegate_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/DelegateWeakEventManager_Delegate_Tests.cs @@ -58,7 +58,9 @@ void HandleDelegateTest(object sender, PropertyChangedEventArgs e) } // Act +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. propertyChangedWeakEventManager.RaiseEvent(null, new PropertyChangedEventArgs("Test"), nameof(PropertyChanged)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. // Assert Assert.True(didEventFire); @@ -173,7 +175,9 @@ public void WeakEventManagerDelegate_UnassignedEventManager() void HandleDelegateTest(object sender, PropertyChangedEventArgs e) => didEventFire = true; // Act +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. unassignedEventManager.RaiseEvent(null, null, nameof(PropertyChanged)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. // Assert Assert.False(didEventFire); @@ -205,9 +209,7 @@ public void WeakEventManagerDelegate_AddEventHandler_NullHandler() // Act // Assert -#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference Assert.Throws(() => propertyChangedWeakEventManager.AddEventHandler(null)); -#pragma warning restore CS8625 } [Fact] @@ -231,9 +233,7 @@ public void WeakEventManagerDelegate_AddEventHandler_EmptyEventName() // Act // Assert -#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference Assert.Throws(() => propertyChangedWeakEventManager.AddEventHandler(null, string.Empty)); -#pragma warning restore CS8625 } [Fact] @@ -244,9 +244,7 @@ public void WeakEventManagerDelegate_AddEventHandler_WhitespaceEventName() // Act // Assert -#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference Assert.Throws(() => propertyChangedWeakEventManager.AddEventHandler(null, " ")); -#pragma warning restore CS8625 } [Fact] @@ -257,9 +255,7 @@ public void WeakEventManagerDelegate_RemoveEventHandler_NullHandler() // Act // Assert -#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference Assert.Throws(() => propertyChangedWeakEventManager.RemoveEventHandler(null)); -#pragma warning restore CS8625 } [Fact] @@ -283,9 +279,7 @@ public void WeakEventManagerDelegate_RemoveEventHandler_EmptyEventName() // Act // Assert -#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference Assert.Throws(() => propertyChangedWeakEventManager.RemoveEventHandler(null, string.Empty)); -#pragma warning restore CS8625 } [Fact] @@ -296,9 +290,7 @@ public void WeakEventManagerDelegate_RemoveEventHandler_WhiteSpaceEventName() // Act // Assert -#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference Assert.Throws(() => propertyChangedWeakEventManager.RemoveEventHandler(null, " ")); -#pragma warning restore CS8625 } } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/DelegateWeakEventManager_EventHandler_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/DelegateWeakEventManager_EventHandler_Tests.cs index aabdcea8a..41197a627 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/DelegateWeakEventManager_EventHandler_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/DelegateWeakEventManager_EventHandler_Tests.cs @@ -52,7 +52,9 @@ void HandleTestEvent(object? sender, EventArgs e) } // Act +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. TestWeakEventManager.RaiseEvent(null, new EventArgs(), nameof(TestEvent)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. // Assert Assert.True(didEventFire); @@ -145,7 +147,9 @@ public void WeakEventManager_UnassignedEvent() void HandleTestEvent(object? sender, EventArgs e) => didEventFire = true; // Act +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. TestWeakEventManager.RaiseEvent(null, null, nameof(TestEvent)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. // Assert Assert.False(didEventFire); @@ -162,7 +166,9 @@ public void WeakEventManager_UnassignedEventManager() void HandleTestEvent(object? sender, EventArgs e) => didEventFire = true; // Act +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. unassignedEventManager.RaiseEvent(null, null, nameof(TestEvent)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. // Assert Assert.False(didEventFire); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/WeakEventManager_ActionT_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/WeakEventManager_ActionT_Tests.cs index d03445aaa..65fae73ca 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/WeakEventManager_ActionT_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/WeakEventManager_ActionT_Tests.cs @@ -140,7 +140,9 @@ public void WeakEventManagerActionT_AddEventHandler_NullHandler() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => actionEventManager.AddEventHandler(nullAction, nameof(ActionEvent))); +#pragma warning restore CS8604 // Possible null reference argument. } @@ -152,7 +154,9 @@ public void WeakEventManagerActionT_AddEventHandler_NullEventName() // Act // Assert +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => actionEventManager.AddEventHandler(s => { var temp = s; }, null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] @@ -164,7 +168,9 @@ public void WeakEventManagerActionT_AddEventHandler_EmptyEventName() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => actionEventManager.AddEventHandler(nullAction, string.Empty)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -187,7 +193,9 @@ public void WeakEventManagerActionT_RemoveEventHandler_NullHandler() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => actionEventManager.RemoveEventHandler(nullAction)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -198,7 +206,9 @@ public void WeakEventManagerActionT_RemoveEventHandler_NullEventName() // Act // Assert +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => actionEventManager.RemoveEventHandler(s => { var temp = s; }, null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/WeakEventManager_EventHandlerT_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/WeakEventManager_EventHandlerT_Tests.cs index 0247f9962..898746144 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/WeakEventManager_EventHandlerT_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Helpers/WeakEventManagerTests/WeakEventManager_EventHandlerT_Tests.cs @@ -61,7 +61,9 @@ void HandleTestEvent(object? sender, string e) } // Act +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. TestStringWeakEventManager.RaiseEvent(null, stringEventArg, nameof(TestStringEvent)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. // Assert Assert.True(didEventFire); @@ -125,7 +127,7 @@ public void WeakEventManager_NullEventManager() // Assert #pragma warning disable CS8602 //Dereference of a possible null reference - Assert.Throws(() => unassignedEventManager.RaiseEvent(null, string.Empty, nameof(TestEvent))); + Assert.Throws(() => unassignedEventManager.RaiseEvent(this, string.Empty, nameof(TestEvent))); #pragma warning restore CS8602 } @@ -174,9 +176,9 @@ public void WeakEventManagerT_AddEventHandler_NullHandler() // Act // Assert -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - Assert.Throws(() => TestStringWeakEventManager.AddEventHandler((EventHandler)null)); -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. + Assert.Throws(() => TestStringWeakEventManager.AddEventHandler((EventHandler?)null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] @@ -187,7 +189,9 @@ public void WeakEventManagerT_AddEventHandler_NullEventName() // Act // Assert +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => TestStringWeakEventManager.AddEventHandler(s => { var temp = s; }, null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] @@ -220,9 +224,9 @@ public void WeakEventManagerT_RemoveEventHandler_NullHandler() // Act // Assert -#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. - Assert.Throws(() => TestStringWeakEventManager.RemoveEventHandler((EventHandler)null)); -#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. + Assert.Throws(() => TestStringWeakEventManager.RemoveEventHandler((EventHandler?)null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] @@ -233,7 +237,9 @@ public void WeakEventManagerT_RemoveEventHandler_NullEventName() // Act // Assert +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => TestStringWeakEventManager.AddEventHandler(s => { var temp = s; }, null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncCommandTests/AsyncCommand_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncCommandTests/AsyncCommand_Tests.cs index 53ddb4f9d..0c17a19d2 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncCommandTests/AsyncCommand_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncCommandTests/AsyncCommand_Tests.cs @@ -153,7 +153,9 @@ public void AsyncCommand_NoParameter_NoCanExecute_Test() { // Arrange Func? canExecute = null; +#pragma warning disable CS8604 // Possible null reference argument. var command = new AsyncCommand(NoParameterTask, canExecute); +#pragma warning restore CS8604 // Possible null reference argument. // Act @@ -171,7 +173,7 @@ public void AsyncCommand_RaiseCanExecuteChanged_MainThreadCreation_MainThreadExe var command = new AsyncCommand(NoParameterTask, commandCanExecute); command.CanExecuteChanged += handleCanExecuteChanged; - bool commandCanExecute(object parameter) => canCommandExecute; + bool commandCanExecute(object? parameter) => canCommandExecute; Assert.False(command.CanExecute(null)); @@ -204,7 +206,7 @@ public void AsyncCommand_RaiseCanExecuteChanged_MainThreadCreation_MainThreadExe var command = new AsyncCommand(NoParameterTask, commandCanExecute); command.CanExecuteChanged += handleCanExecuteChanged; - bool commandCanExecute(object parameter) => canCommandExecute; + bool commandCanExecute(object? parameter) => canCommandExecute; Assert.False(command.CanExecute(null)); @@ -236,7 +238,7 @@ public async Task AsyncCommand_RaiseCanExecuteChanged_MainThreadCreation_Backgro var command = new AsyncCommand(NoParameterTask, commandCanExecute); command.CanExecuteChanged += handleCanExecuteChanged; - bool commandCanExecute(object parameter) => canCommandExecute; + bool commandCanExecute(object? parameter) => canCommandExecute; Assert.False(command.CanExecute(null)); @@ -276,7 +278,7 @@ public async Task AsyncCommand_RaiseCanExecuteChanged_BackgroundThreadCreation_M command = new AsyncCommand(NoParameterTask, commandCanExecute); command.CanExecuteChanged += handleCanExecuteChanged; - bool commandCanExecute(object parameter) => canCommandExecute; + bool commandCanExecute(object? parameter) => canCommandExecute; Assert.False(command.CanExecute(null)); @@ -313,7 +315,7 @@ public async Task AsyncCommand_ChangeCanExecute_Test() var command = new AsyncCommand(NoParameterTask, commandCanExecute); command.CanExecuteChanged += handleCanExecuteChanged; - bool commandCanExecute(object parameter) => canCommandExecute; + bool commandCanExecute(object? parameter) => canCommandExecute; Assert.False(command.CanExecute(null)); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncValueCommandTests/AsyncValueCommand_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncValueCommandTests/AsyncValueCommand_Tests.cs index 1e83d0c7b..48686f86a 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncValueCommandTests/AsyncValueCommand_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncValueCommandTests/AsyncValueCommand_Tests.cs @@ -176,7 +176,9 @@ public void AsyncValueCommandNoParameter_NoCanExecute_Test() { // Arrange Func? canExecute = null; +#pragma warning disable CS8604 // Possible null reference argument. var command = new AsyncValueCommand(NoParameterTask, canExecute); +#pragma warning restore CS8604 // Possible null reference argument. // Act @@ -196,7 +198,7 @@ public async Task AsyncValueCommand_RaiseCanExecuteChanged_Test() var command = new AsyncValueCommand(NoParameterTask, commandCanExecute); command.CanExecuteChanged += handleCanExecuteChanged; - bool commandCanExecute(object parameter) => canCommandExecute; + bool commandCanExecute(object? parameter) => canCommandExecute; Assert.False(command.CanExecute(null)); @@ -234,7 +236,7 @@ public async Task AsyncValueCommand_ChangeCanExecute_Test() var command = new AsyncValueCommand(NoParameterTask, commandCanExecute); command.CanExecuteChanged += handleCanExecuteChanged; - bool commandCanExecute(object parameter) => canCommandExecute; + bool commandCanExecute(object? parameter) => canCommandExecute; Assert.False(command.CanExecute(null)); @@ -246,10 +248,8 @@ public async Task AsyncValueCommand_ChangeCanExecute_Test() Assert.False(didCanExecuteChangeFire); // Act -#pragma warning disable CS0618 // Type or member is obsolete command.ChangeCanExecute(); await handleCanExecuteChangedTCS.Task; -#pragma warning restore CS0618 // Type or member is obsolete // Assert Assert.True(didCanExecuteChangeFire); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncValueCommandTests/BaseAsyncValueCommandTests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncValueCommandTests/BaseAsyncValueCommandTests.cs index a92271fca..064659102 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncValueCommandTests/BaseAsyncValueCommandTests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/AsyncValueCommandTests/BaseAsyncValueCommandTests.cs @@ -9,7 +9,7 @@ public abstract class BaseAsyncValueCommandTests : BaseCommandTests protected new ValueTask IntParameterTask(int delay) => ValueTaskDelay(delay); - protected new ValueTask StringParameterTask(string text) => ValueTaskDelay(Delay); + protected new ValueTask StringParameterTask(string? text) => ValueTaskDelay(Delay); protected new ValueTask NoParameterImmediateNullReferenceExceptionTask() => throw new NullReferenceException(); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/BaseCommandTests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/BaseCommandTests.cs index 12ac5912d..1e5d88ba6 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/BaseCommandTests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/BaseCommandTests.cs @@ -15,7 +15,7 @@ public abstract class BaseCommandTests protected Task IntParameterTask(int delay) => Task.Delay(delay); - protected Task StringParameterTask(string text) => Task.Delay(Delay); + protected Task StringParameterTask(string? text) => Task.Delay(Delay); protected Task NoParameterImmediateNullReferenceExceptionTask() => throw new NullReferenceException(); @@ -53,17 +53,17 @@ protected async Task IntParameterDelayedNullReferenceExceptionTask(int delay) protected bool CanExecuteTrue(bool parameter) => true; - protected bool CanExecuteTrue(string parameter) => true; + protected bool CanExecuteTrue(string? parameter) => true; - protected bool CanExecuteTrue(object parameter) => true; + protected bool CanExecuteTrue(object? parameter) => true; protected bool CanExecuteFalse(bool parameter) => false; - protected bool CanExecuteFalse(string parameter) => false; + protected bool CanExecuteFalse(string? parameter) => false; - protected bool CanExecuteFalse(object parameter) => false; + protected bool CanExecuteFalse(object? parameter) => false; - protected bool CanExecuteDynamic(object booleanParameter) + protected bool CanExecuteDynamic(object? booleanParameter) { if (booleanParameter is bool parameter) return parameter; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_AsyncCommand_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_AsyncCommand_Tests.cs index 2f4f65408..690f4ef99 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_AsyncCommand_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_AsyncCommand_Tests.cs @@ -18,7 +18,9 @@ public void AsyncCommand_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -66,7 +68,9 @@ public void AsyncCommand_FuncBool_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute, () => true)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -74,7 +78,9 @@ public async Task AsyncCommand_FuncBool_NullCanExecuteParameter() { // Arrange Func? canExecute = null; +#pragma warning disable CS8604 // Possible null reference argument. var command = CommandFactory.Create(NoParameterTask, canExecute); +#pragma warning restore CS8604 // Possible null reference argument. // Act await command.ExecuteAsync(); @@ -117,7 +123,9 @@ public void AsyncCommandT_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -167,7 +175,9 @@ public void AsyncCommandT_FuncBool_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute, () => true)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -175,7 +185,9 @@ public async Task AsyncCommandT_FuncBool_NullCanExecuteParameter() { // Arrange Func? canExecute = null; +#pragma warning disable CS8604 // Possible null reference argument. var command = CommandFactory.Create(IntParameterTask, canExecute); +#pragma warning restore CS8604 // Possible null reference argument. // Act await command.ExecuteAsync(0); @@ -218,14 +230,18 @@ public void AsyncCommandTExecuteTCanExecute_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] public async Task AsyncCommandTExecuteTCanExecute_NullCanExecuteParameter() { // Arrange +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. var command = CommandFactory.Create(IntParameterTask, null); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. // Act await command.ExecuteAsync(0); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_AsyncValueCommand_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_AsyncValueCommand_Tests.cs index 387663ec4..90879ce59 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_AsyncValueCommand_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_AsyncValueCommand_Tests.cs @@ -19,7 +19,9 @@ public void AsyncValueCommand_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -67,7 +69,9 @@ public void AsyncValueCommand_FuncBool_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute, () => true)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -75,7 +79,9 @@ public async Task AsyncValueCommand_FuncBool_NullCanExecuteParameter() { // Arrange Func? canExecute = null; +#pragma warning disable CS8604 // Possible null reference argument. var command = CommandFactory.Create(NoParameterTask, canExecute); +#pragma warning restore CS8604 // Possible null reference argument. // Act await command.ExecuteAsync(); @@ -118,7 +124,9 @@ public void AsyncValueCommandT_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -168,7 +176,9 @@ public void AsyncValueCommandT_FuncBool_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute, () => true)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -176,7 +186,9 @@ public async Task AsyncValueCommandT_FuncBool_NullCanExecuteParameter() { // Arrange Func? canExecute = null; +#pragma warning disable CS8604 // Possible null reference argument. var command = CommandFactory.Create(IntParameterTask, canExecute); +#pragma warning restore CS8604 // Possible null reference argument. // Act await command.ExecuteAsync(0); @@ -219,7 +231,9 @@ public void AsyncValueCommandTExecuteTCanExecute_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_Command_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_Command_Tests.cs index 635b6fada..884935a3b 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_Command_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/ObjectModel/ICommandTests/CommandFactoryTests/CommandFactory_Command_Tests.cs @@ -16,7 +16,9 @@ public void Action_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -45,7 +47,9 @@ public void Action_NullCanExecuteParameter() // Act // Assert +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => CommandFactory.Create(NoParameterAction, null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] @@ -75,7 +79,9 @@ public void ActionObject_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -104,7 +110,9 @@ public void ActionObject_NullCanExecuteParameter() // Act // Assert +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => CommandFactory.Create(ObjectParameterAction, null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] @@ -136,7 +144,9 @@ public void ActionInt_NullExecuteParameter() // Act // Assert +#pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => CommandFactory.Create(execute, CanExecuteTrue)); +#pragma warning restore CS8604 // Possible null reference argument. } [Fact] @@ -147,7 +157,9 @@ public void ActionInt_NullCanExecuteParameter() // Act // Assert +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Throws(() => CommandFactory.Create(IntParameterAction, null)); +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Views/MediaElement_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Views/MediaElement_Tests.cs index 6b94c4e45..186e8ceeb 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Views/MediaElement_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Views/MediaElement_Tests.cs @@ -71,7 +71,7 @@ public void TestSourceRoundTrip() media.Source = uri; Assert.NotNull(media.Source); Assert.IsType(media.Source); - Assert.Equal(uri, ((UriMediaSource)media.Source).Uri); + Assert.Equal(uri, ((UriMediaSource?)media.Source)?.Uri); } [Fact] diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Views/MediaSource_Tests.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Views/MediaSource_Tests.cs index 1fc571a25..500436d5b 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Views/MediaSource_Tests.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Views/MediaSource_Tests.cs @@ -25,7 +25,7 @@ public void TestHelpers() var urisource = Core.MediaSource.FromUri(new Uri("http://xamarin.com/media.mp4")); Assert.IsType(urisource); - Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource)urisource).Uri.AbsoluteUri); + Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource?)urisource)?.Uri.AbsoluteUri); } [Fact] @@ -34,16 +34,16 @@ public void TestImplicitFileConversion() var mediaElement = new UI.Views.MediaElement { Source = "File.mp4" }; Assert.NotNull(mediaElement.Source); Assert.IsType(mediaElement.Source); - Assert.Equal("File.mp4", ((Core.FileMediaSource)mediaElement.Source).File); + Assert.Equal("File.mp4", ((Core.FileMediaSource?)mediaElement.Source)?.File); } [Fact] public void TestImplicitStringConversionWhenNull() { string? s = null; - var sut = (Core.MediaSource)s; - Assert.IsType(sut); - Assert.Null(((Core.FileMediaSource)sut).File); + var sut = (Core.MediaSource?)s; + Assert.IsType(sut); + Assert.Null(((Core.FileMediaSource?)sut)?.File); } [Fact] @@ -52,7 +52,7 @@ public void TestImplicitUriConversion() var mediaElement = new UI.Views.MediaElement { Source = new Uri("http://xamarin.com/media.mp4") }; Assert.NotNull(mediaElement.Source); Assert.IsType(mediaElement.Source); - Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource)mediaElement.Source).Uri.AbsoluteUri); + Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource?)mediaElement.Source)?.Uri.AbsoluteUri); } [Fact] @@ -61,14 +61,14 @@ public void TestImplicitStringUriConversion() var mediaElement = new UI.Views.MediaElement { Source = "http://xamarin.com/media.mp4" }; Assert.NotNull(mediaElement.Source); Assert.IsType(mediaElement.Source); - Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource)mediaElement.Source).Uri.AbsoluteUri); + Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource?)mediaElement.Source)?.Uri.AbsoluteUri); } [Fact] public void TestImplicitUriConversionWhenNull() { Uri? u = null; - var sut = (Core.MediaSource)u; + var sut = (Core.MediaSource?)u; Assert.Null(sut); } @@ -79,7 +79,7 @@ public void TestSetStringValue() mediaElement.SetValue(UI.Views.MediaElement.SourceProperty, "media.mp4"); Assert.NotNull(mediaElement.Source); Assert.IsType(mediaElement.Source); - Assert.Equal("media.mp4", ((Core.FileMediaSource)mediaElement.Source).File); + Assert.Equal("media.mp4", ((Core.FileMediaSource?)mediaElement.Source)?.File); } [Fact] @@ -91,7 +91,7 @@ public void TextBindToStringValue() mediaElement.BindingContext = "media.mp4"; Assert.NotNull(mediaElement.Source); Assert.IsType(mediaElement.Source); - Assert.Equal("media.mp4", ((Core.FileMediaSource)mediaElement.Source).File); + Assert.Equal("media.mp4", ((Core.FileMediaSource?)mediaElement.Source)?.File); } [Fact] @@ -103,7 +103,7 @@ public void TextBindToStringUriValue() mediaElement.BindingContext = "http://xamarin.com/media.mp4"; Assert.NotNull(mediaElement.Source); Assert.IsType(mediaElement.Source); - Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource)mediaElement.Source).Uri.AbsoluteUri); + Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource?)mediaElement.Source)?.Uri.AbsoluteUri); } [Fact] @@ -115,7 +115,7 @@ public void TextBindToUriValue() mediaElement.BindingContext = new Uri("http://xamarin.com/media.mp4"); Assert.NotNull(mediaElement.Source); Assert.IsType(mediaElement.Source); - Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource)mediaElement.Source).Uri.AbsoluteUri); + Assert.Equal("http://xamarin.com/media.mp4", ((Core.UriMediaSource?)mediaElement.Source)?.Uri.AbsoluteUri); } [Fact] diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/MaxLengthReachedBehavior.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/MaxLengthReachedBehavior.shared.cs index 8dc352dd2..47ef5c83a 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/MaxLengthReachedBehavior.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/MaxLengthReachedBehavior.shared.cs @@ -21,9 +21,9 @@ public class MaxLengthReachedBehavior : BaseBehavior /// /// Command that is triggered when the value configured in is reached. Both the event and this command are triggered. This is a bindable property. /// - public ICommand Command + public ICommand? Command { - get => (ICommand)GetValue(CommandProperty); + get => (ICommand?)GetValue(CommandProperty); set => SetValue(CommandProperty, value); } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/UserStoppedTypingBehavior.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/UserStoppedTypingBehavior.shared.cs index 6a82b6f77..2062125ce 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/UserStoppedTypingBehavior.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/UserStoppedTypingBehavior.shared.cs @@ -47,16 +47,16 @@ public class UserStoppedTypingBehavior : BaseBehavior /// /// Command that is triggered when the is reached. When is set, it's only triggered when both conditions are met. This is a bindable property. /// - public ICommand Command + public ICommand? Command { - get => (ICommand)GetValue(CommandProperty); + get => (ICommand?)GetValue(CommandProperty); set => SetValue(CommandProperty, value); } /// /// An optional parameter to forward to the . This is a bindable property. /// - public object CommandParameter + public object? CommandParameter { get => GetValue(CommandParameterProperty); set => SetValue(CommandParameterProperty, value); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/BoolToObjectConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/BoolToObjectConverter.shared.cs index 108b55739..4ce274c39 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/BoolToObjectConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/BoolToObjectConverter.shared.cs @@ -35,7 +35,7 @@ public class BoolToObjectConverter : ValueConverterExtension, IValueCon /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// The object assigned to if value equals True, otherwise the value assigned to . - public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value is bool result) return result ? TrueObject : FalseObject; @@ -51,7 +51,7 @@ public class BoolToObjectConverter : ValueConverterExtension, IValueCon /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// True if value equals , otherwise False. - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value is TObject result) return result.Equals(TrueObject); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ByteArrayToImageSourceConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ByteArrayToImageSourceConverter.shared.cs index 74dbd2898..2df999c12 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ByteArrayToImageSourceConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ByteArrayToImageSourceConverter.shared.cs @@ -20,7 +20,7 @@ public class ByteArrayToImageSourceConverter : ValueConverterExtension, IValueCo /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// An object of type . - public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value == null) return null; @@ -39,7 +39,7 @@ public class ByteArrayToImageSourceConverter : ValueConverterExtension, IValueCo /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// An object of type . - public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value == null) return null; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/DateTimeOffsetConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/DateTimeOffsetConverter.shared.cs index c16ec6331..261be88fc 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/DateTimeOffsetConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/DateTimeOffsetConverter.shared.cs @@ -17,7 +17,7 @@ public class DateTimeOffsetConverter : ValueConverterExtension, IValueConverter /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// The value. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + public object Convert(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture) => value is DateTimeOffset dateTimeOffset ? dateTimeOffset.DateTime : throw new ArgumentException("Value is not a valid DateTimeOffset", nameof(value)); @@ -30,7 +30,7 @@ public object Convert(object value, Type targetType, object parameter, System.Gl /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented.. /// The value. - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + public object ConvertBack(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture) => value is DateTime dateTime ? dateTime.Kind switch { diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/DoubleToIntConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/DoubleToIntConverter.shared.cs index 9697ddea0..ce189f125 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/DoubleToIntConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/DoubleToIntConverter.shared.cs @@ -24,7 +24,7 @@ public class DoubleToIntConverter : ValueConverterExtension, IValueConverter /// Multiplier (Equals 1 by default). /// The culture to use in the converter. This is not implemented. /// value. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) => value is double result ? (int)Math.Round(result * GetParameter(parameter)) : throw new ArgumentException("Value is not a valid double", nameof(value)); @@ -37,12 +37,12 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// Denominator (Equals 1 by default). /// The culture to use in the converter. This is not implemented. /// value. - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => value is int result ? result / GetParameter(parameter) : throw new ArgumentException("Value is not a valid integer", nameof(value)); - double GetParameter(object parameter) + double GetParameter(object? parameter) => parameter == null ? Ratio : parameter switch diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/EnumToBoolConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/EnumToBoolConverter.shared.cs index ac7b8c28b..e9cc10989 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/EnumToBoolConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/EnumToBoolConverter.shared.cs @@ -33,9 +33,9 @@ public class EnumToBoolConverter : ValueConverterExtension, IValueConverter /// value not equal to parameter. /// /// If value is not an - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object ?value, Type targetType, object? parameter, CultureInfo culture) { - if (!(value is Enum enumValue)) + if (value is not Enum enumValue) throw new ArgumentException("The value should be of type Enum", nameof(value)); return TrueValues.Count == 0 @@ -59,7 +59,7 @@ static bool CompareTwoEnums(Enum valueToCheck, object? referenceValue) } /// - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/EqualConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/EqualConverter.shared.cs index e8af98d33..4705eab46 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/EqualConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/EqualConverter.shared.cs @@ -18,7 +18,7 @@ public class EqualConverter : ValueConverterExtension, IValueConverter /// The second object to compare. /// The culture to use in the converter. This is not implemented. /// True if and are equal, False if they are not equal. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) => (value != null && value.Equals(parameter)) || (value == null && parameter == null); /// @@ -29,7 +29,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IndexToArrayItemConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IndexToArrayItemConverter.shared.cs index 3fd9a0e24..958f1dc9a 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IndexToArrayItemConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IndexToArrayItemConverter.shared.cs @@ -18,12 +18,12 @@ public class IndexToArrayItemConverter : ValueConverterExtension, IValueConverte /// The items array. /// The culture to use in the converter. This is not implemented. /// The item from the array that corresponds to passed index. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { - if (!(value is int index)) + if (value is not int index) throw new ArgumentException("Value is not a valid integer", nameof(value)); - if (!(parameter is Array array)) + if (parameter is not Array array) throw new ArgumentException("Parameter is not a valid array", nameof(parameter)); if (index < 0 || index >= array.Length) @@ -40,9 +40,9 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// The items array. /// The culture to use in the converter. This is not implemented. /// The index of the item from the array. - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) { - if (!(parameter is Array array)) + if (parameter is not Array array) throw new ArgumentException("Parameter is not a valid array", nameof(parameter)); for (var i = 0; i < array.Length; i++) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IntToBoolConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IntToBoolConverter.shared.cs index 453df7906..58de3abde 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IntToBoolConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IntToBoolConverter.shared.cs @@ -18,7 +18,7 @@ public class IntToBoolConverter : ValueConverterExtension, IValueConverter /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// False if the value is 0, otherwise if the value is anything but 0 it returns True. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) => value is int result ? result != 0 : throw new ArgumentException("Value is not a valid integer", nameof(value)); @@ -31,7 +31,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// 0 if the value is False, otherwise 1 if the value is True. - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value is bool result) return result ? 1 : 0; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/InvertedBoolConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/InvertedBoolConverter.shared.cs index 66ff4e97e..7991605ef 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/InvertedBoolConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/InvertedBoolConverter.shared.cs @@ -18,7 +18,7 @@ public class InvertedBoolConverter : ValueConverterExtension, IValueConverter /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// An inverted from the one coming in. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) => InverseBool(value); /// @@ -29,7 +29,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// An inverted from the one coming in. - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => InverseBool(value); /// @@ -37,7 +37,7 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu /// /// The value to inverse. /// The inverted value of the incoming . - bool InverseBool(object value) + bool InverseBool(object? value) { if (value is bool result) return !result; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IsNotNullOrEmptyConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IsNotNullOrEmptyConverter.shared.cs index 42634a917..7b370d287 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IsNotNullOrEmptyConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IsNotNullOrEmptyConverter.shared.cs @@ -18,7 +18,7 @@ public class IsNotNullOrEmptyConverter : ValueConverterExtension, IValueConverte /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// A indicating if the incoming value is not null and not empty. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) => value is string str ? !string.IsNullOrWhiteSpace(str) : value != null; /// @@ -29,7 +29,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IsNullOrEmptyConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IsNullOrEmptyConverter.shared.cs index a4fed1064..05aa4f926 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IsNullOrEmptyConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/IsNullOrEmptyConverter.shared.cs @@ -18,7 +18,7 @@ public class IsNullOrEmptyConverter : ValueConverterExtension, IValueConverter /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// A indicating if the incoming value is null or empty. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) => value == null || (value is string str && string.IsNullOrWhiteSpace(str)); /// @@ -29,7 +29,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ItemSelectedEventArgsConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ItemSelectedEventArgsConverter.shared.cs index 7512d8566..7de63b824 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ItemSelectedEventArgsConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ItemSelectedEventArgsConverter.shared.cs @@ -18,7 +18,7 @@ public class ItemSelectedEventArgsConverter : ValueConverterExtension, IValueCon /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// A object from object of type . - public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value == null) return null; @@ -36,7 +36,7 @@ public class ItemSelectedEventArgsConverter : ValueConverterExtension, IValueCon /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ItemTappedEventArgsConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ItemTappedEventArgsConverter.shared.cs index 09dc63970..800a0c4d6 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ItemTappedEventArgsConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ItemTappedEventArgsConverter.shared.cs @@ -18,7 +18,7 @@ public class ItemTappedEventArgsConverter : ValueConverterExtension, IValueConve /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// A object from object of type . - public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value == null) return null; @@ -36,7 +36,7 @@ public class ItemTappedEventArgsConverter : ValueConverterExtension, IValueConve /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListIsNotNullOrEmptyConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListIsNotNullOrEmptyConverter.shared.cs index b3b28aa3f..9b5146f79 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListIsNotNullOrEmptyConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListIsNotNullOrEmptyConverter.shared.cs @@ -19,7 +19,7 @@ public class ListIsNotNullOrEmptyConverter : ValueConverterExtension, IValueConv /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// A indicating if the incoming value is not null and not empty. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value == null) return false; @@ -38,7 +38,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListIsNullOrEmptyConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListIsNullOrEmptyConverter.shared.cs index 27da69ad3..99d4adaee 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListIsNullOrEmptyConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListIsNullOrEmptyConverter.shared.cs @@ -19,7 +19,7 @@ public class ListIsNullOrEmptyConverter : ValueConverterExtension, IValueConvert /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// A indicating if the incoming value is null or empty. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value == null) return true; @@ -38,7 +38,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListToStringConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListToStringConverter.shared.cs index d83c02047..8144c5832 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListToStringConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/ListToStringConverter.shared.cs @@ -25,7 +25,7 @@ public class ListToStringConverter : ValueConverterExtension, IValueConverter /// The separator that should be between each collection item. This overrides the value in . /// The culture to use in the converter. This is not implemented. /// Concatenated members string separated by or, if set, . - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value == null) return string.Empty; @@ -52,7 +52,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/MultiConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/MultiConverter.shared.cs index f4d406ffe..c1d7c93fd 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/MultiConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/MultiConverter.shared.cs @@ -18,8 +18,8 @@ public class MultiConverter : List, IValueConverter /// Parameter to pass into subsequent converters. /// The culture to use in the converter. /// The converted value. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - => parameter is IList parameters + public object? Convert(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture) + => parameter is IList parameters ? this.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameters.FirstOrDefault(x => x.ConverterType == converter.GetType())?.Value, culture)) : this.Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture)); @@ -32,7 +32,7 @@ public object Convert(object value, Type targetType, object parameter, System.Gl /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + public object? ConvertBack(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/NotEqualConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/NotEqualConverter.shared.cs index c09446242..635756403 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/NotEqualConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/NotEqualConverter.shared.cs @@ -18,7 +18,7 @@ public class NotEqualConverter : ValueConverterExtension, IValueConverter /// The second object to compare. /// The culture to use in the converter. This is not implemented. /// True if and are not equal, False if they are equal. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) => !((value != null && value.Equals(parameter)) || (value == null && parameter == null)); /// @@ -29,7 +29,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/StateToBooleanConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/StateToBooleanConverter.shared.cs index 21fe1fea0..02beb5595 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/StateToBooleanConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/StateToBooleanConverter.shared.cs @@ -23,9 +23,9 @@ public class StateToBooleanConverter : IValueConverter /// Optionally, a can be supplied here to compare against. /// The culture to use in the converter. This is not implemented. /// True if the provided s match, otherwise False if they don't match. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { - if (!(value is LayoutState state)) + if (value is not LayoutState state) throw new ArgumentException("Value is not a valid State", nameof(value)); if (parameter is LayoutState stateToCompare) @@ -42,7 +42,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TextCaseConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TextCaseConverter.shared.cs index 36210689d..c42732ec4 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TextCaseConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TextCaseConverter.shared.cs @@ -24,7 +24,7 @@ public class TextCaseConverter : ValueConverterExtension, IValueConverter /// The desired text case that the text should be converted to. Must match enum value. /// The culture to use in the converter. This is not implemented. /// The converted text representation with the desired casing. - public object? Convert(object? value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) => value == null || value is string || value is char ? Convert(value?.ToString(), parameter) : throw new ArgumentException("Value is neither a string nor a char", nameof(value)); @@ -37,20 +37,18 @@ public class TextCaseConverter : ValueConverterExtension, IValueConverter /// N/A /// N/A /// N/A - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) => throw new NotImplementedException(); - object? Convert(string? value, object parameter) => GetParameter(parameter) switch + object? Convert(string? value, object? parameter) => GetParameter(parameter) switch { TextCaseType.Lower => value?.ToLowerInvariant(), TextCaseType.Upper => value?.ToUpperInvariant(), - TextCaseType.FirstUpperRestLower => value != null && !string.IsNullOrWhiteSpace(value) - ? value.Substring(0, 1).ToUpperInvariant() + value.Substring(1).ToLowerInvariant() - : value, + TextCaseType.FirstUpperRestLower when value != null && !string.IsNullOrWhiteSpace(value) => value.Substring(0, 1).ToUpperInvariant() + value.Substring(1).ToLowerInvariant(), _ => value }; - TextCaseType GetParameter(object parameter) => parameter == null ? Type : parameter switch + TextCaseType GetParameter(object? parameter) => parameter == null ? Type : parameter switch { TextCaseType type => type, string typeString => Enum.TryParse(typeString, out TextCaseType result) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TimeSpanToDoubleConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TimeSpanToDoubleConverter.shared.cs index 14d026cf9..fa1363495 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TimeSpanToDoubleConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TimeSpanToDoubleConverter.shared.cs @@ -17,7 +17,7 @@ public class TimeSpanToDoubleConverter : IValueConverter /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// A value expressed in seconds. - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value is TimeSpan timespan) { @@ -35,7 +35,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// The value representing the converted value. - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (value is double doubleValue) { diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/VariableMultiValueConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/VariableMultiValueConverter.shared.cs index 409290caa..5cf2641b0 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/VariableMultiValueConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/VariableMultiValueConverter.shared.cs @@ -31,7 +31,7 @@ public class VariableMultiValueConverter : MultiValueConverterExtension, IMultiV /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// A single value dependant on the configuration for this converter. - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + public object Convert(object[]? values, Type targetType, object? parameter, CultureInfo culture) { if (values == null || values.Length == 0) return false; @@ -41,7 +41,7 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur if (boolValues.Length != values.Length) return false; - var count = boolValues.Count(v => v); + var count = boolValues.Count(); return ConditionType switch { @@ -62,7 +62,7 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur /// Additional parameter for the converter to handle. This is not implemented. /// The culture to use in the converter. This is not implemented. /// All bindings that evaluate to true if is true. Or null if is not a value or is false. - public object[]? ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + public object[]? ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture) { if (value is not bool boolValue || targetTypes.Any(t => !t.IsAssignableFrom(typeof(bool)))) return null; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/FileMediaSource.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/FileMediaSource.shared.cs index f8aeb5edf..e875603c4 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/FileMediaSource.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/FileMediaSource.shared.cs @@ -9,9 +9,9 @@ public sealed class FileMediaSource : MediaSource public static readonly BindableProperty FileProperty = BindableProperty.Create(nameof(File), typeof(string), typeof(FileMediaSource), propertyChanged: OnFileMediaSourceChanged); - public string File + public string? File { - get => (string)GetValue(FileProperty); + get => (string?)GetValue(FileProperty); set => SetValue(FileProperty, value); } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/MediaSource.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/MediaSource.shared.cs index 53b693e02..adc286b8e 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/MediaSource.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/MediaSource.shared.cs @@ -10,22 +10,27 @@ public abstract class MediaSource : Element { readonly WeakEventManager weakEventManager = new WeakEventManager(); - public static MediaSource FromFile(string file) => + public static MediaSource FromFile(string? file) => new FileMediaSource { File = file }; - public static MediaSource FromUri(Uri uri) => - !uri.IsAbsoluteUri ? throw new ArgumentException("Uri must be be absolute", nameof(uri)) : new UriMediaSource { Uri = uri }; + public static MediaSource? FromUri(Uri? uri) + { + if (uri == null) + return null; + + return !uri.IsAbsoluteUri ? throw new ArgumentException("Uri must be be absolute", nameof(uri)) : new UriMediaSource { Uri = uri }; + } - public static MediaSource FromUri(string uri) => FromUri(new Uri(uri)); + public static MediaSource? FromUri(string uri) => FromUri(new Uri(uri)); [Preserve(Conditional = true)] - public static implicit operator MediaSource(string source) => + public static implicit operator MediaSource?(string? source) => Uri.TryCreate(source, UriKind.Absolute, out var uri) && uri.Scheme != "file" ? FromUri(uri) : FromFile(source); [Preserve(Conditional = true)] - public static implicit operator MediaSource?(Uri uri) => uri == null ? null : FromUri(uri); + public static implicit operator MediaSource?(Uri? uri) => FromUri(uri); protected void OnSourceChanged() => weakEventManager.RaiseEvent(this, EventArgs.Empty, nameof(SourceChanged)); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/MediaSourceConverter.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/MediaSourceConverter.shared.cs index bf26d70e4..4881b7ae0 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/MediaSourceConverter.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Core/MediaSourceConverter.shared.cs @@ -1,12 +1,11 @@ using System; using Xamarin.Forms; -using Xamarin.Forms.Internals; namespace Xamarin.CommunityToolkit.Core { public sealed class MediaSourceConverter : TypeConverter { - public override object ConvertFromInvariantString(string value) + public override object? ConvertFromInvariantString(string value) { if (value == null) throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(MediaSource)}"); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/IconTintColor/IconTintColorEffectRouter.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/IconTintColor/IconTintColorEffectRouter.android.cs index 129ffd7f5..66bc5a251 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/IconTintColor/IconTintColorEffectRouter.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/IconTintColor/IconTintColorEffectRouter.android.cs @@ -68,7 +68,9 @@ void SetImageViewTintColor(ImageView image, Forms.Color color) if (color == Forms.Color.Default) image.ClearColorFilter(); +#pragma warning disable CS8604 // Possible null reference argument. image.SetColorFilter(new PorterDuffColorFilter(color.ToAndroid(), PorterDuff.Mode.SrcIn)); +#pragma warning restore CS8604 // Possible null reference argument. } void SetButtonTintColor(Button button, Forms.Color color) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/LifeCycle/LifeCycleEffectRouter.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/LifeCycle/LifeCycleEffectRouter.android.cs index 19b944552..a6466811e 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/LifeCycle/LifeCycleEffectRouter.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/LifeCycle/LifeCycleEffectRouter.android.cs @@ -15,8 +15,8 @@ namespace Xamarin.CommunityToolkit.Android.Effects /// public class LifeCycleEffectRouter : PlatformEffect { - View nativeView; - LifecycleEffect lifeCycleEffect; + View? nativeView; + LifecycleEffect? lifeCycleEffect; protected override void OnAttached() { @@ -29,13 +29,20 @@ protected override void OnAttached() nativeView.ViewDetachedFromWindow += OnNativeViewViewDetachedFromWindow; } - void OnNativeViewViewAttachedToWindow(object sender, View.ViewAttachedToWindowEventArgs e) => lifeCycleEffect.RaiseLoadedEvent(Element); + void OnNativeViewViewAttachedToWindow(object sender, View.ViewAttachedToWindowEventArgs e) => lifeCycleEffect?.RaiseLoadedEvent(Element); void OnNativeViewViewDetachedFromWindow(object sender, View.ViewDetachedFromWindowEventArgs e) { - lifeCycleEffect.RaiseUnloadedEvent(Element); - nativeView.ViewDetachedFromWindow -= OnNativeViewViewDetachedFromWindow; - nativeView.ViewAttachedToWindow -= OnNativeViewViewAttachedToWindow; + if (lifeCycleEffect != null) + lifeCycleEffect.RaiseUnloadedEvent(Element); + + if (nativeView != null) + { + nativeView.ViewDetachedFromWindow -= OnNativeViewViewDetachedFromWindow; + nativeView.ViewAttachedToWindow -= OnNativeViewViewAttachedToWindow; + nativeView.Dispose(); + } + nativeView = null; lifeCycleEffect = null; } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/LifeCycle/LifeCycleEffectRouter.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/LifeCycle/LifeCycleEffectRouter.uwp.cs index 6326189d8..77ecb7892 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/LifeCycle/LifeCycleEffectRouter.uwp.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/LifeCycle/LifeCycleEffectRouter.uwp.cs @@ -15,8 +15,8 @@ namespace Xamarin.CommunityToolkit.UWP.Effects /// public class LifeCycleEffectRouter : PlatformEffect { - FrameworkElement nativeView; - LifecycleEffect lifeCycleEffect; + FrameworkElement? nativeView; + LifecycleEffect? lifeCycleEffect; protected override void OnAttached() { @@ -29,13 +29,21 @@ protected override void OnAttached() nativeView.Unloaded += OnNativeViewUnloaded; } - void OnNativeViewLoaded(object sender, RoutedEventArgs e) => lifeCycleEffect.RaiseLoadedEvent(Element); + void OnNativeViewLoaded(object sender, RoutedEventArgs e) => lifeCycleEffect?.RaiseLoadedEvent(Element); void OnNativeViewUnloaded(object sender, RoutedEventArgs e) { - lifeCycleEffect.RaiseUnloadedEvent(Element); - nativeView.Unloaded -= OnNativeViewUnloaded; - nativeView.Loaded -= OnNativeViewLoaded; + if (lifeCycleEffect != null) + { + lifeCycleEffect.RaiseUnloadedEvent(Element); + } + + if (nativeView != null) + { + nativeView.Unloaded -= OnNativeViewUnloaded; + nativeView.Loaded -= OnNativeViewLoaded; + } + lifeCycleEffect = null; nativeView = null; } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/RemoveBorder/RemoveBorderEffect.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/RemoveBorder/RemoveBorderEffect.android.cs index af2759c2c..64174e120 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/RemoveBorder/RemoveBorderEffect.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/RemoveBorder/RemoveBorderEffect.android.cs @@ -1,7 +1,6 @@ using Android.Graphics; using Android.Graphics.Drawables; using Android.Graphics.Drawables.Shapes; -using Android.Runtime; using Xamarin.CommunityToolkit.Effects; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; @@ -13,16 +12,20 @@ namespace Xamarin.CommunityToolkit.Android.Effects { public class RemoveBorderEffect : PlatformEffect { - Drawable originalBackground; + Drawable? originalBackground; protected override void OnAttached() { originalBackground = Control.Background; var shape = new ShapeDrawable(new RectShape()); - shape.Paint.Color = global::Android.Graphics.Color.Transparent; - shape.Paint.StrokeWidth = 0; - shape.Paint.SetStyle(Paint.Style.Stroke); + if (shape.Paint != null) + { + shape.Paint.Color = global::Android.Graphics.Color.Transparent; + shape.Paint.StrokeWidth = 0; + shape.Paint.SetStyle(Paint.Style.Stroke); + } + Control.Background = shape; } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/SelectAllText/SelectAllTextEffect.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/SelectAllText/SelectAllTextEffect.android.cs index e23daa03a..a3daf0b0c 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/SelectAllText/SelectAllTextEffect.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/SelectAllText/SelectAllTextEffect.android.cs @@ -10,7 +10,7 @@ namespace Xamarin.CommunityToolkit.Android.Effects { public class SelectAllTextEffect : PlatformEffect { - EditText EditText => Control as EditText; + EditText? EditText => Control as EditText; protected override void OnAttached() => EditText?.SetSelectAllOnFocus(true); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Shadow/PlatformShadowEffect.ios.macos.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Shadow/PlatformShadowEffect.ios.macos.cs index 0f10cc7b1..bd639e4df 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Shadow/PlatformShadowEffect.ios.macos.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Shadow/PlatformShadowEffect.ios.macos.cs @@ -28,17 +28,17 @@ public class PlatformShadowEffect : PlatformEffect const float defaultOpacity = .5f; - NativeView View => Control ?? Container; + NativeView? View => Control ?? Container; protected override void OnAttached() { if (View == null) return; - UpdateColor(); - UpdateOpacity(); - UpdateRadius(); - UpdateOffset(); + UpdateColor(View); + UpdateOpacity(View); + UpdateRadius(View); + UpdateOffset(View); } protected override void OnDetached() @@ -59,41 +59,49 @@ protected override void OnElementPropertyChanged(PropertyChangedEventArgs args) switch (args.PropertyName) { case nameof(ShadowEffect.ColorPropertyName): - UpdateColor(); + UpdateColor(View); break; case nameof(ShadowEffect.OpacityPropertyName): - UpdateOpacity(); + UpdateOpacity(View); break; case nameof(ShadowEffect.RadiusPropertyName): - UpdateRadius(); + UpdateRadius(View); break; case nameof(ShadowEffect.OffsetXPropertyName): case nameof(ShadowEffect.OffsetYPropertyName): - UpdateOffset(); + UpdateOffset(View); break; } } - void UpdateColor() - => View.Layer.ShadowColor = ShadowEffect.GetColor(Element).ToCGColor(); + void UpdateColor(in NativeView view) + { + if (view.Layer != null) + view.Layer.ShadowColor = ShadowEffect.GetColor(Element).ToCGColor(); + } - void UpdateOpacity() + void UpdateOpacity(in NativeView view) { - var opacity = (float)ShadowEffect.GetOpacity(Element); - View.Layer.ShadowOpacity = opacity < 0 - ? defaultOpacity - : opacity; + if (view.Layer != null) + { + var opacity = (float)ShadowEffect.GetOpacity(Element); + view.Layer.ShadowOpacity = opacity < 0 ? defaultOpacity : opacity; + } } - void UpdateRadius() + void UpdateRadius(in NativeView view) { - var radius = (nfloat)ShadowEffect.GetRadius(Element); - View.Layer.ShadowRadius = radius < 0 - ? defaultRadius - : radius; + if (view.Layer != null) + { + var radius = (nfloat)ShadowEffect.GetRadius(Element); + view.Layer.ShadowRadius = radius < 0 ? defaultRadius : radius; + } } - void UpdateOffset() - => View.Layer.ShadowOffset = new CGSize((double)ShadowEffect.GetOffsetX(Element), (double)ShadowEffect.GetOffsetY(Element)); + void UpdateOffset(in NativeView view) + { + if (view.Layer != null) + view.Layer.ShadowOffset = new CGSize((double)ShadowEffect.GetOffsetX(Element), (double)ShadowEffect.GetOffsetY(Element)); + } } } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/GestureManager.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/GestureManager.shared.cs index 0eec16061..50c8f4818 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/GestureManager.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/GestureManager.shared.cs @@ -92,7 +92,7 @@ internal void HandleUserInteraction(TouchEffect sender, TouchInteractionStatus i internal void HandleHover(TouchEffect sender, HoverStatus status) { - if (!sender.Element.IsEnabled) + if (!sender.Element?.IsEnabled ?? true) return; var hoverState = status == HoverStatus.Entered @@ -123,7 +123,8 @@ internal async Task ChangeStateAsync(TouchEffect sender, bool animated) var isToggled = sender.IsToggled; - UpdateVisualState(sender.Element, state, hoverState); + if (sender.Element != null) + UpdateVisualState(sender.Element, state, hoverState); if (!animated) { @@ -225,7 +226,7 @@ internal void OnTapped(TouchEffect sender) void HandleCollectionViewSelection(TouchEffect sender) { - if (!sender.Element.TryFindParentElementWithParentOfType(out var result, out CollectionView? parent)) + if (sender.Element == null || !sender.Element.TryFindParentElementWithParentOfType(out var result, out CollectionView? parent)) return; var collectionView = parent ?? throw new NullReferenceException(); @@ -298,22 +299,22 @@ async Task SetBackgroundImageAsync(TouchEffect sender, TouchState touchState, Ho var source = normalBackgroundImageSource; if (touchState == TouchState.Pressed) { - if (sender.Element.IsSet(TouchEffect.PressedBackgroundImageAspectProperty)) + if (sender.Element?.IsSet(TouchEffect.PressedBackgroundImageAspectProperty) ?? false) aspect = sender.PressedBackgroundImageAspect; source = pressedBackgroundImageSource; } else if (hoverState == HoverState.Hovered) { - if (sender.Element.IsSet(TouchEffect.HoveredBackgroundImageAspectProperty)) + if (sender.Element?.IsSet(TouchEffect.HoveredBackgroundImageAspectProperty) ?? false) aspect = sender.HoveredBackgroundImageAspect; - if (sender.Element.IsSet(TouchEffect.HoveredBackgroundImageSourceProperty)) + if (sender.Element?.IsSet(TouchEffect.HoveredBackgroundImageSourceProperty) ?? false) source = hoveredBackgroundImageSource; } else { - if (sender.Element.IsSet(TouchEffect.NormalBackgroundImageAspectProperty)) + if (sender.Element?.IsSet(TouchEffect.NormalBackgroundImageAspectProperty) ?? false) aspect = sender.NormalBackgroundImageAspect; } @@ -343,10 +344,13 @@ Task SetBackgroundColor(TouchEffect sender, TouchState touchState, HoverState ho var pressedBackgroundColor = sender.PressedBackgroundColor; var hoveredBackgroundColor = sender.HoveredBackgroundColor; - if (normalBackgroundColor == Color.Default && - pressedBackgroundColor == Color.Default && - hoveredBackgroundColor == Color.Default) + if (sender.Element == null + || (normalBackgroundColor == Color.Default + && pressedBackgroundColor == Color.Default + && hoveredBackgroundColor == Color.Default)) + { return Task.FromResult(false); + } var element = sender.Element; if (defaultBackgroundColor == default) @@ -383,11 +387,11 @@ Task SetOpacity(TouchEffect sender, TouchState touchState, HoverState hoverState if (touchState == TouchState.Pressed) opacity = pressedOpacity; - else if (hoverState == HoverState.Hovered && sender.Element.IsSet(TouchEffect.HoveredOpacityProperty)) + else if (hoverState == HoverState.Hovered && (sender.Element?.IsSet(TouchEffect.HoveredOpacityProperty) ?? false)) opacity = hoveredOpacity; var element = sender.Element; - if (duration <= 0) + if (duration <= 0 && element != null) { element.Opacity = opacity; return Task.FromResult(true); @@ -411,10 +415,13 @@ Task SetScale(TouchEffect sender, TouchState touchState, HoverState hoverState, if (touchState == TouchState.Pressed) scale = pressedScale; - else if (hoverState == HoverState.Hovered && sender.Element.IsSet(TouchEffect.HoveredScaleProperty)) + else if (hoverState == HoverState.Hovered && (sender.Element?.IsSet(TouchEffect.HoveredScaleProperty) ?? false)) scale = hoveredScale; var element = sender.Element; + if (element == null) + return Task.FromResult(false); + if (duration <= 0) { element.Scale = scale; @@ -442,13 +449,15 @@ Task SetTranslation(TouchEffect sender, TouchState touchState, HoverState hoverS var pressedTranslationY = sender.PressedTranslationY; var hoveredTranslationY = sender.HoveredTranslationY; - if (Abs(normalTranslationX) <= double.Epsilon && - Abs(pressedTranslationX) <= double.Epsilon && - Abs(hoveredTranslationX) <= double.Epsilon && - Abs(normalTranslationY) <= double.Epsilon && - Abs(pressedTranslationY) <= double.Epsilon && - Abs(hoveredTranslationY) <= double.Epsilon) + if (Abs(normalTranslationX) <= double.Epsilon + && Abs(pressedTranslationX) <= double.Epsilon + && Abs(hoveredTranslationX) <= double.Epsilon + && Abs(normalTranslationY) <= double.Epsilon + && Abs(pressedTranslationY) <= double.Epsilon + && Abs(hoveredTranslationY) <= double.Epsilon) + { return Task.FromResult(false); + } var translationX = normalTranslationX; var translationY = normalTranslationY; @@ -460,22 +469,22 @@ Task SetTranslation(TouchEffect sender, TouchState touchState, HoverState hoverS } else if (hoverState == HoverState.Hovered) { - if (sender.Element.IsSet(TouchEffect.HoveredTranslationXProperty)) + if (sender.Element?.IsSet(TouchEffect.HoveredTranslationXProperty) ?? false) translationX = hoveredTranslationX; - if (sender.Element.IsSet(TouchEffect.HoveredTranslationYProperty)) + if (sender.Element?.IsSet(TouchEffect.HoveredTranslationYProperty) ?? false) translationY = hoveredTranslationY; } var element = sender.Element; - if (duration <= 0) + if (duration <= 0 && element != null) { element.TranslationX = translationX; element.TranslationY = translationY; return Task.FromResult(true); } - return element.TranslateTo(translationX, translationY, (uint)Abs(duration), easing); + return element?.TranslateTo(translationX, translationY, (uint)Abs(duration), easing) ?? Task.FromResult(false); } Task SetRotation(TouchEffect sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) @@ -484,26 +493,28 @@ Task SetRotation(TouchEffect sender, TouchState touchState, HoverState hoverStat var pressedRotation = sender.PressedRotation; var hoveredRotation = sender.HoveredRotation; - if (Abs(normalRotation) <= double.Epsilon && - Abs(pressedRotation) <= double.Epsilon && - Abs(hoveredRotation) <= double.Epsilon) + if (Abs(normalRotation) <= double.Epsilon + && Abs(pressedRotation) <= double.Epsilon + && Abs(hoveredRotation) <= double.Epsilon) + { return Task.FromResult(false); + } var rotation = normalRotation; if (touchState == TouchState.Pressed) rotation = pressedRotation; - else if (hoverState == HoverState.Hovered && sender.Element.IsSet(TouchEffect.HoveredRotationProperty)) + else if (hoverState == HoverState.Hovered && (sender.Element?.IsSet(TouchEffect.HoveredRotationProperty) ?? false)) rotation = hoveredRotation; var element = sender.Element; - if (duration <= 0) + if (duration <= 0 && element != null) { element.Rotation = rotation; return Task.FromResult(true); } - return element.RotateTo(rotation, (uint)Abs(duration), easing); + return element?.RotateTo(rotation, (uint)Abs(duration), easing) ?? Task.FromResult(false); } Task SetRotationX(TouchEffect sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) @@ -521,17 +532,17 @@ Task SetRotationX(TouchEffect sender, TouchState touchState, HoverState hoverSta if (touchState == TouchState.Pressed) rotationX = pressedRotationX; - else if (hoverState == HoverState.Hovered && sender.Element.IsSet(TouchEffect.HoveredRotationXProperty)) + else if (hoverState == HoverState.Hovered && (sender.Element?.IsSet(TouchEffect.HoveredRotationXProperty) ?? false)) rotationX = hoveredRotationX; var element = sender.Element; - if (duration <= 0) + if (duration <= 0 && element != null) { element.RotationX = rotationX; return Task.FromResult(true); } - return element.RotateXTo(rotationX, (uint)Abs(duration), easing); + return element?.RotateXTo(rotationX, (uint)Abs(duration), easing) ?? Task.FromResult(false); } Task SetRotationY(TouchEffect sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) @@ -549,17 +560,17 @@ Task SetRotationY(TouchEffect sender, TouchState touchState, HoverState hoverSta if (touchState == TouchState.Pressed) rotationY = pressedRotationY; - else if (hoverState == HoverState.Hovered && sender.Element.IsSet(TouchEffect.HoveredRotationYProperty)) + else if (hoverState == HoverState.Hovered && (sender.Element?.IsSet(TouchEffect.HoveredRotationYProperty) ?? false)) rotationY = hoveredRotationY; var element = sender.Element; - if (duration <= 0) + if (duration <= 0 && element != null) { element.RotationY = rotationY; return Task.FromResult(true); } - return element.RotateYTo(rotationY, (uint)Abs(duration), easing); + return element?.RotateYTo(rotationY, (uint)Abs(duration), easing) ?? Task.FromResult(false); } Color GetBackgroundColor(Color color) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.android.cs index 4df067254..f73f7d2e4 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.android.cs @@ -23,12 +23,12 @@ public class PlatformTouchEffect : PlatformEffect { static readonly Forms.Color defaultNativeAnimationColor = Forms.Color.FromRgba(128, 128, 128, 64); - AccessibilityManager accessibilityManager; - AccessibilityListener accessibilityListener; - TouchEffect effect; + AccessibilityManager? accessibilityManager; + AccessibilityListener? accessibilityListener; + TouchEffect? effect; bool isHoverSupported; - RippleDrawable ripple; - AView rippleView; + RippleDrawable? ripple; + AView? rippleView; float startX; float startY; Forms.Color rippleColor; @@ -36,7 +36,7 @@ public class PlatformTouchEffect : PlatformEffect AView View => Control ?? Container; - ViewGroup Group => Container ?? Control as ViewGroup; + ViewGroup Group => Container ?? (ViewGroup)Control; internal bool IsCanceled { get; set; } @@ -59,7 +59,7 @@ protected override void OnAttached() View.Touch += OnTouch; UpdateClickHandler(); - accessibilityManager = View.Context.GetSystemService(Context.AccessibilityService) as AccessibilityManager; + accessibilityManager = View.Context?.GetSystemService(Context.AccessibilityService) as AccessibilityManager; if (accessibilityManager != null) { accessibilityListener = new AccessibilityListener(this); @@ -80,7 +80,7 @@ protected override void OnAttached() return; } - rippleView = new FrameLayout(Group.Context) + rippleView = new FrameLayout(Group.Context ?? throw new NullReferenceException()) { LayoutParameters = new ViewGroup.LayoutParams(-1, -1), Clickable = false, @@ -100,7 +100,7 @@ protected override void OnDetached() try { - if (accessibilityManager != null) + if (accessibilityManager != null && accessibilityListener != null) { accessibilityManager.RemoveAccessibilityStateChangeListener(accessibilityListener); accessibilityManager.RemoveTouchExplorationStateChangeListener(accessibilityListener); @@ -154,7 +154,7 @@ protected override void OnElementPropertyChanged(PropertyChangedEventArgs args) void UpdateClickHandler() { View.Click -= OnClick; - if (IsAccessibilityMode || (effect.IsAvailable && effect.Element.IsEnabled)) + if (IsAccessibilityMode || ((effect?.IsAvailable ?? false) && (effect?.Element?.IsEnabled ?? false))) { View.Click += OnClick; return; @@ -171,7 +171,7 @@ void OnTouch(object sender, AView.TouchEventArgs e) if (IsAccessibilityMode) return; - switch (e.Event.ActionMasked) + switch (e.Event?.ActionMasked) { case MotionEventActions.Down: OnTouchDown(e); @@ -196,50 +196,52 @@ void OnTouch(object sender, AView.TouchEventArgs e) void OnTouchDown(AView.TouchEventArgs e) { + _ = e.Event ?? throw new NullReferenceException(); + IsCanceled = false; startX = e.Event.GetX(); startY = e.Event.GetY(); effect?.HandleUserInteraction(TouchInteractionStatus.Started); effect?.HandleTouch(TouchStatus.Started); StartRipple(e.Event.GetX(), e.Event.GetY()); - if (effect.DisallowTouchThreshold > 0) + if (effect?.DisallowTouchThreshold > 0) Group?.Parent?.RequestDisallowInterceptTouchEvent(true); } void OnTouchUp() - => HandleEnd(effect.Status == TouchStatus.Started ? TouchStatus.Completed : TouchStatus.Canceled); + => HandleEnd(effect?.Status == TouchStatus.Started ? TouchStatus.Completed : TouchStatus.Canceled); void OnTouchCancel() => HandleEnd(TouchStatus.Canceled); void OnTouchMove(object sender, AView.TouchEventArgs e) { - if (IsCanceled) + if (IsCanceled || e.Event == null) return; - var diffX = Math.Abs(e.Event.GetX() - startX) / View.Context.Resources.DisplayMetrics.Density; - var diffY = Math.Abs(e.Event.GetY() - startY) / View.Context.Resources.DisplayMetrics.Density; + var diffX = Math.Abs(e.Event.GetX() - startX) / View.Context?.Resources?.DisplayMetrics?.Density ?? throw new NullReferenceException(); + var diffY = Math.Abs(e.Event.GetY() - startY) / View.Context?.Resources?.DisplayMetrics?.Density ?? throw new NullReferenceException(); var maxDiff = Math.Max(diffX, diffY); - var disallowTouchThreshold = effect.DisallowTouchThreshold; + + var disallowTouchThreshold = effect?.DisallowTouchThreshold; if (disallowTouchThreshold > 0 && maxDiff > disallowTouchThreshold) { HandleEnd(TouchStatus.Canceled); return; } - var view = sender as AView; - if (view == null) + if (sender is not AView view) return; var screenPointerCoords = new Point(view.Left + e.Event.GetX(), view.Top + e.Event.GetY()); var viewRect = new Rectangle(view.Left, view.Top, view.Right - view.Left, view.Bottom - view.Top); var status = viewRect.Contains(screenPointerCoords) ? TouchStatus.Started : TouchStatus.Canceled; - if (isHoverSupported && ((status == TouchStatus.Canceled && effect.HoverStatus == HoverStatus.Entered) - || (status == TouchStatus.Started && effect.HoverStatus == HoverStatus.Exited))) + if (isHoverSupported && ((status == TouchStatus.Canceled && effect?.HoverStatus == HoverStatus.Entered) + || (status == TouchStatus.Started && effect?.HoverStatus == HoverStatus.Exited))) effect?.HandleHover(status == TouchStatus.Started ? HoverStatus.Entered : HoverStatus.Exited); - if (effect.Status != status) + if (effect?.Status != status) { effect?.HandleTouch(status); if (status == TouchStatus.Started) @@ -279,7 +281,7 @@ void HandleEnd(TouchStatus status) return; IsCanceled = true; - if (effect.DisallowTouchThreshold > 0) + if (effect?.DisallowTouchThreshold > 0) Group?.Parent?.RequestDisallowInterceptTouchEvent(false); effect?.HandleTouch(status); @@ -297,7 +299,7 @@ void StartRipple(float x, float y) UpdateRipple(); rippleView.Enabled = true; rippleView.BringToFront(); - ripple.SetHotspot(x, y); + ripple?.SetHotspot(x, y); rippleView.Pressed = true; } } @@ -319,8 +321,8 @@ void CreateRipple() var drawable = Group != null ? View?.Background : View?.Foreground; var isEmptyDrawable = Element is Layout || drawable == null; - if (drawable is RippleDrawable) - ripple = (RippleDrawable)drawable.GetConstantState().NewDrawable(); + if (drawable is RippleDrawable rippleDrawable && rippleDrawable.GetConstantState() is Drawable.ConstantState constantState) + ripple = (RippleDrawable)constantState.NewDrawable(); else ripple = new RippleDrawable(GetColorStateList(), isEmptyDrawable ? null : drawable, isEmptyDrawable ? new ColorDrawable(Color.White) : null); @@ -337,13 +339,15 @@ void UpdateRipple() rippleColor = effect.NativeAnimationColor; rippleRadius = effect.NativeAnimationRadius; - ripple.SetColor(GetColorStateList()); - if (Build.VERSION.SdkInt >= BuildVersionCodes.M) - ripple.Radius = (int)(View.Context.Resources.DisplayMetrics.Density * effect.NativeAnimationRadius); + ripple?.SetColor(GetColorStateList()); + if (Build.VERSION.SdkInt >= BuildVersionCodes.M && ripple != null) + ripple.Radius = (int)(View.Context?.Resources?.DisplayMetrics?.Density * effect?.NativeAnimationRadius ?? throw new NullReferenceException()); } ColorStateList GetColorStateList() { + _ = effect?.NativeAnimationColor ?? throw new NullReferenceException(); + var nativeAnimationColor = effect.NativeAnimationColor; if (nativeAnimationColor == Forms.Color.Default) nativeAnimationColor = defaultNativeAnimationColor; @@ -367,7 +371,7 @@ sealed class AccessibilityListener : Java.Lang.Object, AccessibilityManager.IAccessibilityStateChangeListener, AccessibilityManager.ITouchExplorationStateChangeListener { - PlatformTouchEffect platformTouchEffect; + PlatformTouchEffect? platformTouchEffect; internal AccessibilityListener(PlatformTouchEffect platformTouchEffect) => this.platformTouchEffect = platformTouchEffect; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.macos.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.macos.cs index 065abfb0f..25eae71d3 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.macos.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.macos.cs @@ -1,4 +1,5 @@ -using AppKit; +using System; +using AppKit; using Xamarin.CommunityToolkit.Effects; using Xamarin.CommunityToolkit.macOS.Effects; using Xamarin.Forms; @@ -10,11 +11,11 @@ namespace Xamarin.CommunityToolkit.macOS.Effects { public class PlatformTouchEffect : PlatformEffect { - NSGestureRecognizer gesture; + NSGestureRecognizer? gesture; - TouchEffect effect; + TouchEffect? effect; - MouseTrackingView mouseTrackingView; + MouseTrackingView? mouseTrackingView; protected override void OnAttached() { @@ -52,8 +53,8 @@ protected override void OnDetached() sealed class MouseTrackingView : NSView { - NSTrackingArea trackingArea; - TouchEffect effect; + NSTrackingArea? trackingArea; + TouchEffect? effect; public MouseTrackingView(TouchEffect effect) { @@ -105,8 +106,8 @@ protected override void Dispose(bool disposing) sealed class TouchNSClickGestureRecognizer : NSGestureRecognizer { - TouchEffect effect; - NSView container; + TouchEffect? effect; + NSView? container; public TouchNSClickGestureRecognizer(TouchEffect effect, NSView container) { @@ -118,8 +119,8 @@ Rectangle ViewRect { get { - var frame = container.Frame; - var parent = container.Superview; + var frame = container?.Frame ?? throw new NullReferenceException(); + var parent = container?.Superview; while (parent != null) { frame = new CoreGraphics.CGRect(frame.X + parent.Frame.X, frame.Y + parent.Frame.Y, frame.Width, frame.Height); @@ -169,7 +170,7 @@ public override void MouseDragged(NSEvent mouseEvent) (status == TouchStatus.Started && effect.HoverStatus == HoverStatus.Exited)) effect?.HandleHover(status == TouchStatus.Started ? HoverStatus.Entered : HoverStatus.Exited); - if (effect.Status != status) + if (effect?.Status != status) effect?.HandleTouch(status); base.MouseDragged(mouseEvent); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.tizen.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.tizen.cs index af6746e2d..eb5c81f12 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.tizen.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.tizen.cs @@ -11,9 +11,9 @@ namespace Xamarin.CommunityToolkit.Tizen.Effects { public class PlatformTouchEffect : PlatformEffect { - GestureLayer gestureLayer; + GestureLayer? gestureLayer; - TouchEffect effect; + TouchEffect? effect; protected override void OnAttached() { @@ -43,20 +43,20 @@ protected override void OnDetached() sealed class TouchTapGestureRecognizer : GestureLayer { - readonly TouchEffect effect; + readonly TouchEffect? effect; bool tapCompleted; bool longTapStarted; public TouchTapGestureRecognizer(EvasObject parent) : base(parent) { - SetTapCallback(GestureType.Tap, GestureLayer.GestureState.Start, OnTapStarted); - SetTapCallback(GestureType.Tap, GestureLayer.GestureState.End, OnGestureEnded); - SetTapCallback(GestureType.Tap, GestureLayer.GestureState.Abort, OnGestureAborted); + SetTapCallback(GestureType.Tap, GestureState.Start, OnTapStarted); + SetTapCallback(GestureType.Tap, GestureState.End, OnGestureEnded); + SetTapCallback(GestureType.Tap, GestureState.Abort, OnGestureAborted); - SetTapCallback(GestureType.LongTap, GestureLayer.GestureState.Start, OnLongTapStarted); - SetTapCallback(GestureType.LongTap, GestureLayer.GestureState.End, OnGestureEnded); - SetTapCallback(GestureType.LongTap, GestureLayer.GestureState.Abort, OnGestureAborted); + SetTapCallback(GestureType.LongTap, GestureState.Start, OnLongTapStarted); + SetTapCallback(GestureType.LongTap, GestureState.End, OnGestureEnded); + SetTapCallback(GestureType.LongTap, GestureState.Abort, OnGestureAborted); } public TouchTapGestureRecognizer(EvasObject parent, TouchEffect effect) @@ -90,10 +90,10 @@ void OnLongTapStarted(TapData data) void OnGestureEnded(TapData data) { - if (effect?.IsDisabled ?? true) + if (effect == null || effect.IsDisabled) return; - HandleTouch(effect?.Status == TouchStatus.Started ? TouchStatus.Completed : TouchStatus.Canceled, TouchInteractionStatus.Completed); + HandleTouch(effect.Status == TouchStatus.Started ? TouchStatus.Completed : TouchStatus.Canceled, TouchInteractionStatus.Completed); IsCanceled = true; tapCompleted = true; } @@ -119,12 +119,12 @@ public void HandleTouch(TouchStatus status, TouchInteractionStatus? touchInterac if (IsCanceled || effect == null) return; - if (effect?.IsDisabled ?? true) + if (effect.IsDisabled) return; if (touchInteractionStatus == TouchInteractionStatus.Started) { - effect?.HandleUserInteraction(TouchInteractionStatus.Started); + effect.HandleUserInteraction(TouchInteractionStatus.Started); touchInteractionStatus = null; } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.uwp.cs index 795c7310b..f72cc8c9a 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.uwp.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/PlatformTouchEffect.uwp.cs @@ -14,19 +14,19 @@ namespace Xamarin.CommunityToolkit.UWP.Effects { public class PlatformTouchEffect : PlatformEffect { - const string PointerDownAnimationKey = "PointerDownAnimation"; + const string pointerDownAnimationKey = "PointerDownAnimation"; - const string PointerUpAnimationKey = "PointerUpAnimation"; + const string pointerUpAnimationKey = "PointerUpAnimation"; - TouchEffect effect; + TouchEffect? effect; bool isPressed; bool isIntentionalCaptureLoss; - Storyboard pointerDownStoryboard; + Storyboard? pointerDownStoryboard; - Storyboard pointerUpStoryboard; + Storyboard? pointerUpStoryboard; protected override void OnAttached() { @@ -41,26 +41,26 @@ protected override void OnAttached() if (string.IsNullOrEmpty(nativeControl.Name)) nativeControl.Name = Guid.NewGuid().ToString(); - if (nativeControl.Resources.ContainsKey(PointerDownAnimationKey)) - pointerDownStoryboard = (Storyboard)nativeControl.Resources[PointerDownAnimationKey]; + if (nativeControl.Resources.ContainsKey(pointerDownAnimationKey)) + pointerDownStoryboard = (Storyboard)nativeControl.Resources[pointerDownAnimationKey]; else { pointerDownStoryboard = new Storyboard(); var downThemeAnimation = new PointerDownThemeAnimation(); Storyboard.SetTargetName(downThemeAnimation, nativeControl.Name); pointerDownStoryboard.Children.Add(downThemeAnimation); - nativeControl.Resources.Add(new KeyValuePair(PointerDownAnimationKey, pointerDownStoryboard)); + nativeControl.Resources.Add(new KeyValuePair(pointerDownAnimationKey, pointerDownStoryboard)); } - if (nativeControl.Resources.ContainsKey(PointerUpAnimationKey)) - pointerUpStoryboard = (Storyboard)nativeControl.Resources[PointerUpAnimationKey]; + if (nativeControl.Resources.ContainsKey(pointerUpAnimationKey)) + pointerUpStoryboard = (Storyboard)nativeControl.Resources[pointerUpAnimationKey]; else { pointerUpStoryboard = new Storyboard(); var upThemeAnimation = new PointerUpThemeAnimation(); Storyboard.SetTargetName(upThemeAnimation, nativeControl.Name); pointerUpStoryboard.Children.Add(upThemeAnimation); - nativeControl.Resources.Add(new KeyValuePair(PointerUpAnimationKey, pointerUpStoryboard)); + nativeControl.Resources.Add(new KeyValuePair(pointerUpAnimationKey, pointerUpStoryboard)); } } @@ -150,7 +150,7 @@ void OnPointerCaptureLost(object sender, PointerRoutedEventArgs e) effect?.HandleUserInteraction(TouchInteractionStatus.Completed); - if (effect.HoverStatus != HoverStatus.Exited) + if (effect?.HoverStatus != HoverStatus.Exited) effect?.HandleHover(HoverStatus.Exited); AnimateTilt(pointerUpStoryboard); @@ -190,7 +190,7 @@ void OnPointerPressed(object sender, PointerRoutedEventArgs e) isIntentionalCaptureLoss = false; } - void AnimateTilt(Storyboard storyboard) + void AnimateTilt(Storyboard? storyboard) { if ((effect?.NativeAnimation ?? false) && storyboard != null) { diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/TouchEffect.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/TouchEffect.shared.cs index 50e58d1ab..7c8b6e7c8 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/TouchEffect.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/Touch/TouchEffect.shared.cs @@ -465,7 +465,7 @@ public class TouchEffect : RoutingEffect VisualElement? element; public TouchEffect() - : base(EffectIds.TouchEffect) + : base(EffectIds.TouchEffect) { #region Required work-around to prevent linker from removing the platform-specific implementation #if __ANDROID__ @@ -487,361 +487,361 @@ public TouchEffect() #endregion } - public static bool GetIsAvailable(BindableObject bindable) - => (bool)bindable.GetValue(IsAvailableProperty); + public static bool GetIsAvailable(BindableObject? bindable) + => (bool)(bindable?.GetValue(IsAvailableProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetIsAvailable(BindableObject bindable, bool value) - => bindable.SetValue(IsAvailableProperty, value); + public static void SetIsAvailable(BindableObject? bindable, bool value) + => bindable?.SetValue(IsAvailableProperty, value); - public static bool GetShouldMakeChildrenInputTransparent(BindableObject bindable) - => (bool)bindable.GetValue(ShouldMakeChildrenInputTransparentProperty); + public static bool GetShouldMakeChildrenInputTransparent(BindableObject? bindable) + => (bool)(bindable?.GetValue(ShouldMakeChildrenInputTransparentProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetShouldMakeChildrenInputTransparent(BindableObject bindable, bool value) - => bindable.SetValue(ShouldMakeChildrenInputTransparentProperty, value); + public static void SetShouldMakeChildrenInputTransparent(BindableObject? bindable, bool value) + => bindable?.SetValue(ShouldMakeChildrenInputTransparentProperty, value); - public static ICommand GetCommand(BindableObject bindable) - => (ICommand)bindable.GetValue(CommandProperty); + public static ICommand GetCommand(BindableObject? bindable) + => (ICommand)(bindable?.GetValue(CommandProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetCommand(BindableObject bindable, ICommand value) - => bindable.SetValue(CommandProperty, value); + public static void SetCommand(BindableObject? bindable, ICommand value) + => bindable?.SetValue(CommandProperty, value); - public static ICommand GetLongPressCommand(BindableObject bindable) - => (ICommand)bindable.GetValue(LongPressCommandProperty); + public static ICommand GetLongPressCommand(BindableObject? bindable) + => (ICommand)(bindable?.GetValue(LongPressCommandProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetLongPressCommand(BindableObject bindable, ICommand value) - => bindable.SetValue(LongPressCommandProperty, value); + public static void SetLongPressCommand(BindableObject? bindable, ICommand value) + => bindable?.SetValue(LongPressCommandProperty, value); - public static object GetCommandParameter(BindableObject bindable) - => bindable.GetValue(CommandParameterProperty); + public static object GetCommandParameter(BindableObject? bindable) + => bindable?.GetValue(CommandParameterProperty) ?? throw new ArgumentNullException(nameof(bindable)); - public static void SetCommandParameter(BindableObject bindable, object value) - => bindable.SetValue(CommandParameterProperty, value); + public static void SetCommandParameter(BindableObject? bindable, object value) + => bindable?.SetValue(CommandParameterProperty, value); - public static object GetLongPressCommandParameter(BindableObject bindable) - => bindable.GetValue(LongPressCommandParameterProperty); + public static object GetLongPressCommandParameter(BindableObject? bindable) + => bindable?.GetValue(LongPressCommandParameterProperty) ?? throw new ArgumentNullException(nameof(bindable)); - public static void SetLongPressCommandParameter(BindableObject bindable, object value) - => bindable.SetValue(LongPressCommandParameterProperty, value); + public static void SetLongPressCommandParameter(BindableObject? bindable, object value) + => bindable?.SetValue(LongPressCommandParameterProperty, value); - public static int GetLongPressDuration(BindableObject bindable) - => (int)bindable.GetValue(LongPressDurationProperty); + public static int GetLongPressDuration(BindableObject? bindable) + => (int)(bindable?.GetValue(LongPressDurationProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetLongPressDuration(BindableObject bindable, int value) - => bindable.SetValue(LongPressDurationProperty, value); + public static void SetLongPressDuration(BindableObject? bindable, int value) + => bindable?.SetValue(LongPressDurationProperty, value); - public static TouchStatus GetStatus(BindableObject bindable) - => (TouchStatus)bindable.GetValue(StatusProperty); + public static TouchStatus GetStatus(BindableObject? bindable) + => (TouchStatus)(bindable?.GetValue(StatusProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetStatus(BindableObject bindable, TouchStatus value) - => bindable.SetValue(StatusProperty, value); + public static void SetStatus(BindableObject? bindable, TouchStatus value) + => bindable?.SetValue(StatusProperty, value); - public static TouchState GetState(BindableObject bindable) - => (TouchState)bindable.GetValue(StateProperty); + public static TouchState GetState(BindableObject? bindable) + => (TouchState)(bindable?.GetValue(StateProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetState(BindableObject bindable, TouchState value) - => bindable.SetValue(StateProperty, value); + public static void SetState(BindableObject? bindable, TouchState value) + => bindable?.SetValue(StateProperty, value); - public static TouchInteractionStatus GetInteractionStatus(BindableObject bindable) - => (TouchInteractionStatus)bindable.GetValue(InteractionStatusProperty); + public static TouchInteractionStatus GetInteractionStatus(BindableObject? bindable) + => (TouchInteractionStatus)(bindable?.GetValue(InteractionStatusProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetInteractionStatus(BindableObject bindable, TouchInteractionStatus value) - => bindable.SetValue(InteractionStatusProperty, value); + public static void SetInteractionStatus(BindableObject? bindable, TouchInteractionStatus value) + => bindable?.SetValue(InteractionStatusProperty, value); - public static HoverStatus GetHoverStatus(BindableObject bindable) - => (HoverStatus)bindable.GetValue(HoverStatusProperty); + public static HoverStatus GetHoverStatus(BindableObject? bindable) + => (HoverStatus)(bindable?.GetValue(HoverStatusProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoverStatus(BindableObject bindable, HoverStatus value) - => bindable.SetValue(HoverStatusProperty, value); + public static void SetHoverStatus(BindableObject? bindable, HoverStatus value) + => bindable?.SetValue(HoverStatusProperty, value); - public static HoverState GetHoverState(BindableObject bindable) - => (HoverState)bindable.GetValue(HoverStateProperty); + public static HoverState GetHoverState(BindableObject? bindable) + => (HoverState)(bindable?.GetValue(HoverStateProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoverState(BindableObject bindable, HoverState value) - => bindable.SetValue(HoverStateProperty, value); + public static void SetHoverState(BindableObject? bindable, HoverState value) + => bindable?.SetValue(HoverStateProperty, value); - public static Color GetNormalBackgroundColor(BindableObject bindable) - => (Color)bindable.GetValue(NormalBackgroundColorProperty); + public static Color GetNormalBackgroundColor(BindableObject? bindable) + => (Color)(bindable?.GetValue(NormalBackgroundColorProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalBackgroundColor(BindableObject bindable, Color value) - => bindable.SetValue(NormalBackgroundColorProperty, value); + public static void SetNormalBackgroundColor(BindableObject? bindable, Color value) + => bindable?.SetValue(NormalBackgroundColorProperty, value); - public static Color GetHoveredBackgroundColor(BindableObject bindable) - => (Color)bindable.GetValue(HoveredBackgroundColorProperty); + public static Color GetHoveredBackgroundColor(BindableObject? bindable) + => (Color)(bindable?.GetValue(HoveredBackgroundColorProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredBackgroundColor(BindableObject bindable, Color value) - => bindable.SetValue(HoveredBackgroundColorProperty, value); + public static void SetHoveredBackgroundColor(BindableObject? bindable, Color value) + => bindable?.SetValue(HoveredBackgroundColorProperty, value); - public static Color GetPressedBackgroundColor(BindableObject bindable) - => (Color)bindable.GetValue(PressedBackgroundColorProperty); + public static Color GetPressedBackgroundColor(BindableObject? bindable) + => (Color)(bindable?.GetValue(PressedBackgroundColorProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedBackgroundColor(BindableObject bindable, Color value) - => bindable.SetValue(PressedBackgroundColorProperty, value); + public static void SetPressedBackgroundColor(BindableObject? bindable, Color value) + => bindable?.SetValue(PressedBackgroundColorProperty, value); - public static double GetNormalOpacity(BindableObject bindable) - => (double)bindable.GetValue(NormalOpacityProperty); + public static double GetNormalOpacity(BindableObject? bindable) + => (double)(bindable?.GetValue(NormalOpacityProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalOpacity(BindableObject bindable, double value) - => bindable.SetValue(NormalOpacityProperty, value); + public static void SetNormalOpacity(BindableObject? bindable, double value) + => bindable?.SetValue(NormalOpacityProperty, value); - public static double GetHoveredOpacity(BindableObject bindable) - => (double)bindable.GetValue(HoveredOpacityProperty); + public static double GetHoveredOpacity(BindableObject? bindable) + => (double)(bindable?.GetValue(HoveredOpacityProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredOpacity(BindableObject bindable, double value) - => bindable.SetValue(HoveredOpacityProperty, value); + public static void SetHoveredOpacity(BindableObject? bindable, double value) + => bindable?.SetValue(HoveredOpacityProperty, value); - public static double GetPressedOpacity(BindableObject bindable) - => (double)bindable.GetValue(PressedOpacityProperty); + public static double GetPressedOpacity(BindableObject? bindable) + => (double)(bindable?.GetValue(PressedOpacityProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedOpacity(BindableObject bindable, double value) - => bindable.SetValue(PressedOpacityProperty, value); + public static void SetPressedOpacity(BindableObject? bindable, double value) + => bindable?.SetValue(PressedOpacityProperty, value); - public static double GetNormalScale(BindableObject bindable) - => (double)bindable.GetValue(NormalScaleProperty); + public static double GetNormalScale(BindableObject? bindable) + => (double)(bindable?.GetValue(NormalScaleProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalScale(BindableObject bindable, double value) - => bindable.SetValue(NormalScaleProperty, value); + public static void SetNormalScale(BindableObject? bindable, double value) + => bindable?.SetValue(NormalScaleProperty, value); - public static double GetHoveredScale(BindableObject bindable) - => (double)bindable.GetValue(HoveredScaleProperty); + public static double GetHoveredScale(BindableObject? bindable) + => (double)(bindable?.GetValue(HoveredScaleProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredScale(BindableObject bindable, double value) - => bindable.SetValue(HoveredScaleProperty, value); + public static void SetHoveredScale(BindableObject? bindable, double value) + => bindable?.SetValue(HoveredScaleProperty, value); - public static double GetPressedScale(BindableObject bindable) - => (double)bindable.GetValue(PressedScaleProperty); + public static double GetPressedScale(BindableObject? bindable) + => (double)(bindable?.GetValue(PressedScaleProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedScale(BindableObject bindable, double value) - => bindable.SetValue(PressedScaleProperty, value); + public static void SetPressedScale(BindableObject? bindable, double value) + => bindable?.SetValue(PressedScaleProperty, value); - public static double GetNormalTranslationX(BindableObject bindable) - => (double)bindable.GetValue(NormalTranslationXProperty); + public static double GetNormalTranslationX(BindableObject? bindable) + => (double)(bindable?.GetValue(NormalTranslationXProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalTranslationX(BindableObject bindable, double value) - => bindable.SetValue(NormalTranslationXProperty, value); + public static void SetNormalTranslationX(BindableObject? bindable, double value) + => bindable?.SetValue(NormalTranslationXProperty, value); - public static double GetHoveredTranslationX(BindableObject bindable) - => (double)bindable.GetValue(HoveredTranslationXProperty); + public static double GetHoveredTranslationX(BindableObject? bindable) + => (double)(bindable?.GetValue(HoveredTranslationXProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredTranslationX(BindableObject bindable, double value) - => bindable.SetValue(HoveredTranslationXProperty, value); + public static void SetHoveredTranslationX(BindableObject? bindable, double value) + => bindable?.SetValue(HoveredTranslationXProperty, value); - public static double GetPressedTranslationX(BindableObject bindable) - => (double)bindable.GetValue(PressedTranslationXProperty); + public static double GetPressedTranslationX(BindableObject? bindable) + => (double)(bindable?.GetValue(PressedTranslationXProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedTranslationX(BindableObject bindable, double value) - => bindable.SetValue(PressedTranslationXProperty, value); + public static void SetPressedTranslationX(BindableObject? bindable, double value) + => bindable?.SetValue(PressedTranslationXProperty, value); - public static double GetNormalTranslationY(BindableObject bindable) - => (double)bindable.GetValue(NormalTranslationYProperty); + public static double GetNormalTranslationY(BindableObject? bindable) + => (double)(bindable?.GetValue(NormalTranslationYProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalTranslationY(BindableObject bindable, double value) - => bindable.SetValue(NormalTranslationYProperty, value); + public static void SetNormalTranslationY(BindableObject? bindable, double value) + => bindable?.SetValue(NormalTranslationYProperty, value); - public static double GetHoveredTranslationY(BindableObject bindable) - => (double)bindable.GetValue(HoveredTranslationYProperty); + public static double GetHoveredTranslationY(BindableObject? bindable) + => (double)(bindable?.GetValue(HoveredTranslationYProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredTranslationY(BindableObject bindable, double value) - => bindable.SetValue(HoveredTranslationYProperty, value); + public static void SetHoveredTranslationY(BindableObject? bindable, double value) + => bindable?.SetValue(HoveredTranslationYProperty, value); - public static double GetPressedTranslationY(BindableObject bindable) - => (double)bindable.GetValue(PressedTranslationYProperty); + public static double GetPressedTranslationY(BindableObject? bindable) + => (double)(bindable?.GetValue(PressedTranslationYProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedTranslationY(BindableObject bindable, double value) - => bindable.SetValue(PressedTranslationYProperty, value); + public static void SetPressedTranslationY(BindableObject? bindable, double value) + => bindable?.SetValue(PressedTranslationYProperty, value); - public static double GetNormalRotation(BindableObject bindable) - => (double)bindable.GetValue(NormalRotationProperty); + public static double GetNormalRotation(BindableObject? bindable) + => (double)(bindable?.GetValue(NormalRotationProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalRotation(BindableObject bindable, double value) - => bindable.SetValue(NormalRotationProperty, value); + public static void SetNormalRotation(BindableObject? bindable, double value) + => bindable?.SetValue(NormalRotationProperty, value); - public static double GetHoveredRotation(BindableObject bindable) - => (double)bindable.GetValue(HoveredRotationProperty); + public static double GetHoveredRotation(BindableObject? bindable) + => (double)(bindable?.GetValue(HoveredRotationProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredRotation(BindableObject bindable, double value) - => bindable.SetValue(HoveredRotationProperty, value); + public static void SetHoveredRotation(BindableObject? bindable, double value) + => bindable?.SetValue(HoveredRotationProperty, value); - public static double GetPressedRotation(BindableObject bindable) - => (double)bindable.GetValue(PressedRotationProperty); + public static double GetPressedRotation(BindableObject? bindable) + => (double)(bindable?.GetValue(PressedRotationProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedRotation(BindableObject bindable, double value) - => bindable.SetValue(PressedRotationProperty, value); + public static void SetPressedRotation(BindableObject? bindable, double value) + => bindable?.SetValue(PressedRotationProperty, value); - public static double GetNormalRotationX(BindableObject bindable) - => (double)bindable.GetValue(NormalRotationXProperty); + public static double GetNormalRotationX(BindableObject? bindable) + => (double)(bindable?.GetValue(NormalRotationXProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalRotationX(BindableObject bindable, double value) - => bindable.SetValue(NormalRotationXProperty, value); + public static void SetNormalRotationX(BindableObject? bindable, double value) + => bindable?.SetValue(NormalRotationXProperty, value); - public static double GetHoveredRotationX(BindableObject bindable) - => (double)bindable.GetValue(HoveredRotationXProperty); + public static double GetHoveredRotationX(BindableObject? bindable) + => (double)(bindable?.GetValue(HoveredRotationXProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredRotationX(BindableObject bindable, double value) - => bindable.SetValue(HoveredRotationXProperty, value); + public static void SetHoveredRotationX(BindableObject? bindable, double value) + => bindable?.SetValue(HoveredRotationXProperty, value); - public static double GetPressedRotationX(BindableObject bindable) - => (double)bindable.GetValue(PressedRotationXProperty); + public static double GetPressedRotationX(BindableObject? bindable) + => (double)(bindable?.GetValue(PressedRotationXProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedRotationX(BindableObject bindable, double value) - => bindable.SetValue(PressedRotationXProperty, value); + public static void SetPressedRotationX(BindableObject? bindable, double value) + => bindable?.SetValue(PressedRotationXProperty, value); - public static double GetNormalRotationY(BindableObject bindable) - => (double)bindable.GetValue(NormalRotationYProperty); + public static double GetNormalRotationY(BindableObject? bindable) + => (double)(bindable?.GetValue(NormalRotationYProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalRotationY(BindableObject bindable, double value) - => bindable.SetValue(NormalRotationYProperty, value); + public static void SetNormalRotationY(BindableObject? bindable, double value) + => bindable?.SetValue(NormalRotationYProperty, value); - public static double GetHoveredRotationY(BindableObject bindable) - => (double)bindable.GetValue(HoveredRotationYProperty); + public static double GetHoveredRotationY(BindableObject? bindable) + => (double)(bindable?.GetValue(HoveredRotationYProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredRotationY(BindableObject bindable, double value) - => bindable.SetValue(HoveredRotationYProperty, value); + public static void SetHoveredRotationY(BindableObject? bindable, double value) + => bindable?.SetValue(HoveredRotationYProperty, value); - public static double GetPressedRotationY(BindableObject bindable) - => (double)bindable.GetValue(PressedRotationYProperty); + public static double GetPressedRotationY(BindableObject? bindable) + => (double)(bindable?.GetValue(PressedRotationYProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedRotationY(BindableObject bindable, double value) - => bindable.SetValue(PressedRotationYProperty, value); + public static void SetPressedRotationY(BindableObject? bindable, double value) + => bindable?.SetValue(PressedRotationYProperty, value); - public static int GetAnimationDuration(BindableObject bindable) - => (int)bindable.GetValue(AnimationDurationProperty); + public static int GetAnimationDuration(BindableObject? bindable) + => (int)(bindable?.GetValue(AnimationDurationProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetAnimationDuration(BindableObject bindable, int value) - => bindable.SetValue(AnimationDurationProperty, value); + public static void SetAnimationDuration(BindableObject? bindable, int value) + => bindable?.SetValue(AnimationDurationProperty, value); - public static Easing GetAnimationEasing(BindableObject bindable) - => (Easing)bindable.GetValue(AnimationEasingProperty); + public static Easing GetAnimationEasing(BindableObject? bindable) + => (Easing)(bindable?.GetValue(AnimationEasingProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetAnimationEasing(BindableObject bindable, Easing value) - => bindable.SetValue(AnimationEasingProperty, value); + public static void SetAnimationEasing(BindableObject? bindable, Easing value) + => bindable?.SetValue(AnimationEasingProperty, value); - public static int GetPressedAnimationDuration(BindableObject bindable) - => (int)bindable.GetValue(PressedAnimationDurationProperty); + public static int GetPressedAnimationDuration(BindableObject? bindable) + => (int)(bindable?.GetValue(PressedAnimationDurationProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedAnimationDuration(BindableObject bindable, int value) - => bindable.SetValue(PressedAnimationDurationProperty, value); + public static void SetPressedAnimationDuration(BindableObject? bindable, int value) + => bindable?.SetValue(PressedAnimationDurationProperty, value); - public static Easing GetPressedAnimationEasing(BindableObject bindable) - => (Easing)bindable.GetValue(PressedAnimationEasingProperty); + public static Easing GetPressedAnimationEasing(BindableObject? bindable) + => (Easing)(bindable?.GetValue(PressedAnimationEasingProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedAnimationEasing(BindableObject bindable, Easing value) - => bindable.SetValue(PressedAnimationEasingProperty, value); + public static void SetPressedAnimationEasing(BindableObject? bindable, Easing value) + => bindable?.SetValue(PressedAnimationEasingProperty, value); - public static int GetNormalAnimationDuration(BindableObject bindable) - => (int)bindable.GetValue(NormalAnimationDurationProperty); + public static int GetNormalAnimationDuration(BindableObject? bindable) + => (int)(bindable?.GetValue(NormalAnimationDurationProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalAnimationDuration(BindableObject bindable, int value) - => bindable.SetValue(NormalAnimationDurationProperty, value); + public static void SetNormalAnimationDuration(BindableObject? bindable, int value) + => bindable?.SetValue(NormalAnimationDurationProperty, value); - public static Easing GetNormalAnimationEasing(BindableObject bindable) - => (Easing)bindable.GetValue(NormalAnimationEasingProperty); + public static Easing GetNormalAnimationEasing(BindableObject? bindable) + => (Easing)(bindable?.GetValue(NormalAnimationEasingProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalAnimationEasing(BindableObject bindable, Easing value) - => bindable.SetValue(NormalAnimationEasingProperty, value); + public static void SetNormalAnimationEasing(BindableObject? bindable, Easing value) + => bindable?.SetValue(NormalAnimationEasingProperty, value); - public static int GetHoveredAnimationDuration(BindableObject bindable) - => (int)bindable.GetValue(HoveredAnimationDurationProperty); + public static int GetHoveredAnimationDuration(BindableObject? bindable) + => (int)(bindable?.GetValue(HoveredAnimationDurationProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredAnimationDuration(BindableObject bindable, int value) - => bindable.SetValue(HoveredAnimationDurationProperty, value); + public static void SetHoveredAnimationDuration(BindableObject? bindable, int value) + => bindable?.SetValue(HoveredAnimationDurationProperty, value); - public static Easing GetHoveredAnimationEasing(BindableObject bindable) - => (Easing)bindable.GetValue(HoveredAnimationEasingProperty); + public static Easing GetHoveredAnimationEasing(BindableObject? bindable) + => (Easing)(bindable?.GetValue(HoveredAnimationEasingProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredAnimationEasing(BindableObject bindable, Easing value) - => bindable.SetValue(HoveredAnimationEasingProperty, value); + public static void SetHoveredAnimationEasing(BindableObject? bindable, Easing value) + => bindable?.SetValue(HoveredAnimationEasingProperty, value); - public static int GetPulseCount(BindableObject bindable) - => (int)bindable.GetValue(PulseCountProperty); + public static int GetPulseCount(BindableObject? bindable) + => (int)(bindable?.GetValue(PulseCountProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPulseCount(BindableObject bindable, int value) - => bindable.SetValue(PulseCountProperty, value); + public static void SetPulseCount(BindableObject? bindable, int value) + => bindable?.SetValue(PulseCountProperty, value); - public static bool? GetIsToggled(BindableObject bindable) - => (bool?)bindable.GetValue(IsToggledProperty); + public static bool? GetIsToggled(BindableObject? bindable) + => (bool?)(bindable?.GetValue(IsToggledProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetIsToggled(BindableObject bindable, bool? value) - => bindable.SetValue(IsToggledProperty, value); + public static void SetIsToggled(BindableObject? bindable, bool? value) + => bindable?.SetValue(IsToggledProperty, value); - public static int GetDisallowTouchThreshold(BindableObject bindable) - => (int)bindable.GetValue(DisallowTouchThresholdProperty); + public static int GetDisallowTouchThreshold(BindableObject? bindable) + => (int)(bindable?.GetValue(DisallowTouchThresholdProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetDisallowTouchThreshold(BindableObject bindable, int value) - => bindable.SetValue(DisallowTouchThresholdProperty, value); + public static void SetDisallowTouchThreshold(BindableObject? bindable, int value) + => bindable?.SetValue(DisallowTouchThresholdProperty, value); - public static bool GetNativeAnimation(BindableObject bindable) - => (bool)bindable.GetValue(NativeAnimationProperty); + public static bool GetNativeAnimation(BindableObject? bindable) + => (bool)(bindable?.GetValue(NativeAnimationProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNativeAnimation(BindableObject bindable, bool value) - => bindable.SetValue(NativeAnimationProperty, value); + public static void SetNativeAnimation(BindableObject? bindable, bool value) + => bindable?.SetValue(NativeAnimationProperty, value); - public static Color GetNativeAnimationColor(BindableObject bindable) - => (Color)bindable.GetValue(NativeAnimationColorProperty); + public static Color GetNativeAnimationColor(BindableObject? bindable) + => (Color)(bindable?.GetValue(NativeAnimationColorProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNativeAnimationColor(BindableObject bindable, Color value) - => bindable.SetValue(NativeAnimationColorProperty, value); + public static void SetNativeAnimationColor(BindableObject? bindable, Color value) + => bindable?.SetValue(NativeAnimationColorProperty, value); - public static int GetNativeAnimationRadius(BindableObject bindable) - => (int)bindable.GetValue(NativeAnimationRadiusProperty); + public static int GetNativeAnimationRadius(BindableObject? bindable) + => (int)(bindable?.GetValue(NativeAnimationRadiusProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNativeAnimationRadius(BindableObject bindable, int value) - => bindable.SetValue(NativeAnimationRadiusProperty, value); + public static void SetNativeAnimationRadius(BindableObject? bindable, int value) + => bindable?.SetValue(NativeAnimationRadiusProperty, value); - public static int GetNativeAnimationShadowRadius(BindableObject bindable) - => (int)bindable.GetValue(NativeAnimationShadowRadiusProperty); + public static int GetNativeAnimationShadowRadius(BindableObject? bindable) + => (int)(bindable?.GetValue(NativeAnimationShadowRadiusProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNativeAnimationShadowRadius(BindableObject bindable, int value) - => bindable.SetValue(NativeAnimationShadowRadiusProperty, value); + public static void SetNativeAnimationShadowRadius(BindableObject? bindable, int value) + => bindable?.SetValue(NativeAnimationShadowRadiusProperty, value); - public static ImageSource GetNormalBackgroundImageSource(BindableObject bindable) - => (ImageSource)bindable.GetValue(NormalBackgroundImageSourceProperty); + public static ImageSource GetNormalBackgroundImageSource(BindableObject? bindable) + => (ImageSource)(bindable?.GetValue(NormalBackgroundImageSourceProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalBackgroundImageSource(BindableObject bindable, ImageSource value) - => bindable.SetValue(NormalBackgroundImageSourceProperty, value); + public static void SetNormalBackgroundImageSource(BindableObject? bindable, ImageSource value) + => bindable?.SetValue(NormalBackgroundImageSourceProperty, value); - public static ImageSource GetHoveredBackgroundImageSource(BindableObject bindable) - => (ImageSource)bindable.GetValue(HoveredBackgroundImageSourceProperty); + public static ImageSource GetHoveredBackgroundImageSource(BindableObject? bindable) + => (ImageSource)(bindable?.GetValue(HoveredBackgroundImageSourceProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredBackgroundImageSource(BindableObject bindable, ImageSource value) - => bindable.SetValue(HoveredBackgroundImageSourceProperty, value); + public static void SetHoveredBackgroundImageSource(BindableObject? bindable, ImageSource value) + => bindable?.SetValue(HoveredBackgroundImageSourceProperty, value); - public static ImageSource GetPressedBackgroundImageSource(BindableObject bindable) - => (ImageSource)bindable.GetValue(PressedBackgroundImageSourceProperty); + public static ImageSource GetPressedBackgroundImageSource(BindableObject? bindable) + => (ImageSource)(bindable?.GetValue(PressedBackgroundImageSourceProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedBackgroundImageSource(BindableObject bindable, ImageSource value) - => bindable.SetValue(PressedBackgroundImageSourceProperty, value); + public static void SetPressedBackgroundImageSource(BindableObject? bindable, ImageSource value) + => bindable?.SetValue(PressedBackgroundImageSourceProperty, value); - public static Aspect GetBackgroundImageAspect(BindableObject bindable) - => (Aspect)bindable.GetValue(BackgroundImageAspectProperty); + public static Aspect GetBackgroundImageAspect(BindableObject? bindable) + => (Aspect)(bindable?.GetValue(BackgroundImageAspectProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetBackgroundImageAspect(BindableObject bindable, Aspect value) - => bindable.SetValue(BackgroundImageAspectProperty, value); + public static void SetBackgroundImageAspect(BindableObject? bindable, Aspect value) + => bindable?.SetValue(BackgroundImageAspectProperty, value); - public static Aspect GetNormalBackgroundImageAspect(BindableObject bindable) - => (Aspect)bindable.GetValue(NormalBackgroundImageAspectProperty); + public static Aspect GetNormalBackgroundImageAspect(BindableObject? bindable) + => (Aspect)(bindable?.GetValue(NormalBackgroundImageAspectProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetNormalBackgroundImageAspect(BindableObject bindable, Aspect value) - => bindable.SetValue(NormalBackgroundImageAspectProperty, value); + public static void SetNormalBackgroundImageAspect(BindableObject? bindable, Aspect value) + => bindable?.SetValue(NormalBackgroundImageAspectProperty, value); - public static Aspect GetHoveredBackgroundImageAspect(BindableObject bindable) - => (Aspect)bindable.GetValue(HoveredBackgroundImageAspectProperty); + public static Aspect GetHoveredBackgroundImageAspect(BindableObject? bindable) + => (Aspect)(bindable?.GetValue(HoveredBackgroundImageAspectProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetHoveredBackgroundImageAspect(BindableObject bindable, Aspect value) - => bindable.SetValue(HoveredBackgroundImageAspectProperty, value); + public static void SetHoveredBackgroundImageAspect(BindableObject? bindable, Aspect value) + => bindable?.SetValue(HoveredBackgroundImageAspectProperty, value); - public static Aspect GetPressedBackgroundImageAspect(BindableObject bindable) - => (Aspect)bindable.GetValue(PressedBackgroundImageAspectProperty); + public static Aspect GetPressedBackgroundImageAspect(BindableObject? bindable) + => (Aspect)(bindable?.GetValue(PressedBackgroundImageAspectProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetPressedBackgroundImageAspect(BindableObject bindable, Aspect value) - => bindable.SetValue(PressedBackgroundImageAspectProperty, value); + public static void SetPressedBackgroundImageAspect(BindableObject? bindable, Aspect value) + => bindable?.SetValue(PressedBackgroundImageAspectProperty, value); - public static bool GetShouldSetImageOnAnimationEnd(BindableObject bindable) - => (bool)bindable.GetValue(ShouldSetImageOnAnimationEndProperty); + public static bool GetShouldSetImageOnAnimationEnd(BindableObject? bindable) + => (bool)(bindable?.GetValue(ShouldSetImageOnAnimationEndProperty) ?? throw new ArgumentNullException(nameof(bindable))); - public static void SetShouldSetImageOnAnimationEnd(BindableObject bindable, bool value) - => bindable.SetValue(ShouldSetImageOnAnimationEndProperty, value); + public static void SetShouldSetImageOnAnimationEnd(BindableObject? bindable, bool value) + => bindable?.SetValue(ShouldSetImageOnAnimationEndProperty, value); - static void TryGenerateEffect(BindableObject bindable, object oldValue, object newValue) + static void TryGenerateEffect(BindableObject? bindable, object oldValue, object newValue) { if (bindable is not VisualElement view || view.Effects.OfType().Any()) return; @@ -1015,12 +1015,11 @@ public HoverState HoverState public bool ShouldSetImageOnAnimationEnd => GetShouldSetImageOnAnimationEnd(Element); - internal bool CanExecute - => IsAvailable && - Element.IsEnabled && - (Command?.CanExecute(CommandParameter) ?? true); + internal bool CanExecute => IsAvailable + && (Element?.IsEnabled ?? false) + && (Command?.CanExecute(CommandParameter) ?? true); - internal new VisualElement Element + internal new VisualElement? Element { get => element; set @@ -1047,13 +1046,13 @@ internal new VisualElement Element } } - internal static TouchEffect? GetFrom(BindableObject bindable) + internal static TouchEffect? GetFrom(BindableObject? bindable) { var effects = (bindable as VisualElement)?.Effects?.OfType(); return effects?.FirstOrDefault(x => !x.IsAutoGenerated) ?? effects?.FirstOrDefault(); } - internal static TouchEffect? PickFrom(BindableObject bindable) + internal static TouchEffect? PickFrom(BindableObject? bindable) { var effects = (bindable as VisualElement)?.Effects?.OfType(); return effects?.FirstOrDefault(x => !x.IsAutoGenerated && !x.IsUsed) diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.uwp.cs index fb6c4decf..642b10350 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.uwp.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.uwp.cs @@ -18,7 +18,9 @@ Page GetCurrentPage(Page currentPage) { if (currentPage.NavigationProxy.ModalStack.LastOrDefault() is Page modal) return modal; +#pragma warning disable CS0618 // Type or member is obsolete else if (currentPage is MasterDetailPage mdp) +#pragma warning restore CS0618 // Type or member is obsolete return GetCurrentPage(mdp.Detail); else if (currentPage is FlyoutPage fp) return GetCurrentPage(fp.Detail); @@ -31,7 +33,7 @@ Page GetCurrentPage(Page currentPage) } } - static Task PlatformShowPopupAsync(Popup popup) + static Task PlatformShowPopupAsync(Popup popup) { PlatformShowPopup(popup); return popup.Result; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/LocalizedString.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/LocalizedString.shared.cs index 0fcfa473c..563cc8774 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/LocalizedString.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/LocalizedString.shared.cs @@ -7,14 +7,14 @@ namespace Xamarin.CommunityToolkit.Helpers #if !NETSTANDARD1_0 public class LocalizedString : ObservableObject { - readonly Func? generator; + readonly Func? generator; - public LocalizedString(Func? generator = null) + public LocalizedString(Func? generator = null) : this(LocalizationResourceManager.Current, generator) { } - public LocalizedString(LocalizationResourceManager localizationManager, Func? generator = null) + public LocalizedString(LocalizationResourceManager localizationManager, Func? generator = null) { this.generator = generator; @@ -26,7 +26,7 @@ public LocalizedString(LocalizationResourceManager localizationManager, Func generator?.Invoke(); [Preserve(Conditional = true)] - public static implicit operator LocalizedString(Func func) => new LocalizedString(func); + public static implicit operator LocalizedString(Func? func) => new LocalizedString(func); } #endif } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/SafeArea.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/SafeArea.shared.cs index 71b1d0742..c0d9f33e3 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/SafeArea.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/SafeArea.shared.cs @@ -51,9 +51,9 @@ bool Equals(SafeArea other) Bottom == other.Bottom); public override bool Equals(object obj) - => !ReferenceEquals(null, obj) && - obj is SafeArea safeArea && - Equals(safeArea); + => obj is not null + && obj is SafeArea safeArea + && Equals(safeArea); public override int GetHashCode() { diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/WeakEventManagerService.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/WeakEventManagerService.shared.cs index 8f51b7b1b..47c252f9d 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/WeakEventManagerService.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/WeakEventManagerService.shared.cs @@ -164,15 +164,13 @@ static void AddRemoveEvents(in string eventName, in Dictionary f.Name is "m_owner").GetValue(rtDynamicMethod) - : null; + return (typeInfoRTDynamicMethod != null && typeInfoRTDynamicMethod.IsAssignableFrom(rtDynamicMethod.GetType().GetTypeInfo())) + ? (DynamicMethod)typeRTDynamicMethod.GetRuntimeFields().First(f => f.Name is "m_owner").GetValue(rtDynamicMethod) + : null; } static bool IsLightweightMethod(this MethodBase method) { - _ = method ?? throw new ArgumentNullException(nameof(method)); - var typeInfoRTDynamicMethod = typeof(DynamicMethod).GetTypeInfo().GetDeclaredNestedType("RTDynamicMethod"); return method is DynamicMethod || (typeInfoRTDynamicMethod?.IsAssignableFrom(method.GetType().GetTypeInfo()) ?? false); } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Startup/ToolkitPlatform.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Startup/ToolkitPlatform.android.cs index 60d866add..1a96aee86 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Startup/ToolkitPlatform.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Startup/ToolkitPlatform.android.cs @@ -6,12 +6,12 @@ namespace Xamarin.CommunityToolkit /// /// Platform extension methods. /// - internal static class ToolkitPlatform + static class ToolkitPlatform { /// /// Gets the . /// - internal static Context Context + internal static Context? Context { get { diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraFragment.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraFragment.android.cs index b748c50dd..e83bb3cc5 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraFragment.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraFragment.android.cs @@ -45,20 +45,24 @@ namespace Xamarin.CommunityToolkit.UI.Views class CameraFragment : Fragment, TextureView.ISurfaceTextureListener { // Max preview width that is guaranteed by Camera2 API - const int MAX_PREVIEW_HEIGHT = 1080; + const int maxPreviewHeight = 1080; + // Max preview height that is guaranteed by Camera2 API - const int MAX_PREVIEW_WIDTH = 1920; + const int maxPrevieWidth = 1920; + + readonly Java.Util.Concurrent.Semaphore captureSessionOpenCloseLock = new Java.Util.Concurrent.Semaphore(1); + readonly MediaActionSound mediaSound = new MediaActionSound(); - CameraDevice device; - CaptureRequest.Builder sessionBuilder; - CameraCaptureSession session; + CameraDevice? device; + CaptureRequest.Builder? sessionBuilder; + CameraCaptureSession? session; - AutoFitTextureView texture; - ImageReader photoReader; - MediaRecorder mediaRecorder; + AutoFitTextureView? texture; + ImageReader? photoReader; + MediaRecorder? mediaRecorder; bool audioPermissionsGranted; bool cameraPermissionsGranted; - ASize previewSize, videoSize, photoSize; + ASize? previewSize, videoSize, photoSize; int sensorOrientation; LensFacing cameraType; @@ -67,34 +71,21 @@ class CameraFragment : Fragment, TextureView.ISurfaceTextureListener bool stabilizationSupported; bool repeatingIsRunning; FlashMode flashMode; - string cameraId; - string videoFile; - Java.Util.Concurrent.Semaphore captureSessionOpenCloseLock = new Java.Util.Concurrent.Semaphore(1); - CameraTemplate cameraTemplate; - HandlerThread backgroundThread; - Handler backgroundHandler = null; + string? cameraId; + string videoFile = string.Empty; + CameraTemplate? cameraTemplate; + HandlerThread? backgroundThread; + Handler? backgroundHandler = null; float zoom = 1; - bool ZoomSupported => maxDigitalZoom != 0; - float maxDigitalZoom; - Rect activeRect; - - public bool IsRecordingVideo { get; set; } - - bool UseSystemSound { get; set; } + Rect? activeRect; - CameraManager manager; + CameraManager? manager; - CameraManager Manager => manager ??= (CameraManager)Context.GetSystemService(Context.CameraService); - - MediaActionSound mediaSound; - - MediaActionSound MediaSound => mediaSound ??= new MediaActionSound(); - - TaskCompletionSource initTaskSource; - TaskCompletionSource permissionsRequested; + TaskCompletionSource? initTaskSource; + TaskCompletionSource? permissionsRequested; public CameraFragment() { @@ -121,14 +112,22 @@ bool Available get => Element?.IsAvailable ?? false; set { - if (Element?.IsAvailable != value) + if (Element != null && Element.IsAvailable != value) Element.IsAvailable = value; } } - public CameraView Element { get; set; } + public bool IsRecordingVideo { get; set; } + + bool UseSystemSound { get; set; } + + public CameraView? Element { get; set; } - public override AView OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) => + CameraManager Manager => manager ??= (CameraManager)(Context.GetSystemService(Context.CameraService) ?? throw new NullReferenceException()); + + bool ZoomSupported => maxDigitalZoom != 0; + + public override AView? OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) => inflater.Inflate(Resource.Layout.CameraFragment, null); public override void OnViewCreated(AView view, Bundle savedInstanceState) => @@ -161,7 +160,9 @@ void StartBackgroundThread() { backgroundThread = new HandlerThread("CameraBackground"); backgroundThread.Start(); +#pragma warning disable CS8604 // Possible null reference argument. backgroundHandler = new Handler(backgroundThread.Looper); +#pragma warning restore CS8604 // Possible null reference argument. } void StopBackgroundThread() @@ -200,39 +201,44 @@ public async Task RetrieveCameraDevice(bool force = false) IsBusy = true; cameraId = GetCameraId(); - if (string.IsNullOrEmpty(cameraId)) + if (cameraId == null || string.IsNullOrEmpty(cameraId)) { IsBusy = false; captureSessionOpenCloseLock.Release(); // _texture.ClearCanvas(Element.BackgroundColor.ToAndroid()); // HANG after select valid camera... - Element.RaiseMediaCaptureFailed($"No {Element.CameraOptions} camera found"); + Element?.RaiseMediaCaptureFailed($"No {Element.CameraOptions} camera found"); } else { try { var characteristics = Manager.GetCameraCharacteristics(cameraId); - var map = (StreamConfigurationMap)characteristics.Get(CameraCharacteristics.ScalerStreamConfigurationMap); + var map = (StreamConfigurationMap)(characteristics?.Get(CameraCharacteristics.ScalerStreamConfigurationMap) ?? throw new NullReferenceException()); flashSupported = characteristics.Get(CameraCharacteristics.FlashInfoAvailable) == Java.Lang.Boolean.True; stabilizationSupported = false; var stabilizationModes = characteristics.Get(CameraCharacteristics.ControlAvailableVideoStabilizationModes); - if (stabilizationModes != null) + + if (stabilizationModes is IEnumerable modes) { - var modes = (int[])stabilizationModes; foreach (var mode in modes) { if (mode == (int)ControlVideoStabilizationMode.On) stabilizationSupported = true; } } - Element.MaxZoom = maxDigitalZoom = (float)characteristics.Get(CameraCharacteristics.ScalerAvailableMaxDigitalZoom); - activeRect = (Rect)characteristics.Get(CameraCharacteristics.SensorInfoActiveArraySize); - sensorOrientation = (int)characteristics.Get(CameraCharacteristics.SensorOrientation); + + if (Element != null) + Element.MaxZoom = maxDigitalZoom = (float)(characteristics.Get(CameraCharacteristics.ScalerAvailableMaxDigitalZoom) ?? throw new NullReferenceException()); + + activeRect = (Rect)(characteristics.Get(CameraCharacteristics.SensorInfoActiveArraySize) ?? throw new NullReferenceException()); + sensorOrientation = (int)(characteristics.Get(CameraCharacteristics.SensorOrientation) ?? throw new NullReferenceException()); var displaySize = new APoint(); - Activity.WindowManager.DefaultDisplay.GetSize(displaySize); + Activity.WindowManager?.DefaultDisplay?.GetSize(displaySize); + + _ = texture ?? throw new NullReferenceException(); var rotatedViewWidth = texture.Width; var rotatedViewHeight = texture.Height; var maxPreviewWidth = displaySize.X; @@ -246,33 +252,33 @@ public async Task RetrieveCameraDevice(bool force = false) maxPreviewHeight = displaySize.X; } - if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) + if (maxPreviewHeight > CameraFragment.maxPreviewHeight) { - maxPreviewHeight = MAX_PREVIEW_HEIGHT; + maxPreviewHeight = CameraFragment.maxPreviewHeight; } - if (maxPreviewWidth > MAX_PREVIEW_WIDTH) + if (maxPreviewWidth > maxPrevieWidth) { - maxPreviewWidth = MAX_PREVIEW_WIDTH; + maxPreviewWidth = maxPrevieWidth; } photoSize = GetMaxSize(map.GetOutputSizes((int)ImageFormatType.Jpeg)); videoSize = GetMaxSize(map.GetOutputSizes(Class.FromType(typeof(MediaRecorder)))); previewSize = ChooseOptimalSize( - map.GetOutputSizes(Class.FromType(typeof(SurfaceTexture))), + map.GetOutputSizes(Class.FromType(typeof(SurfaceTexture))) ?? throw new NullReferenceException(), rotatedViewWidth, rotatedViewHeight, maxPreviewWidth, maxPreviewHeight, cameraTemplate == CameraTemplate.Record ? videoSize : photoSize); - cameraType = (LensFacing)(int)characteristics.Get(CameraCharacteristics.LensFacing); + cameraType = (LensFacing)(int)(characteristics.Get(CameraCharacteristics.LensFacing) ?? throw new NullReferenceException()); - if (Resources.Configuration.Orientation == AOrientation.Landscape) + if (Resources.Configuration?.Orientation == AOrientation.Landscape) texture.SetAspectRatio(previewSize.Width, previewSize.Height); else texture.SetAspectRatio(previewSize.Height, previewSize.Width); - initTaskSource = new TaskCompletionSource(); + initTaskSource = new TaskCompletionSource(); Manager.OpenCamera( cameraId, @@ -318,16 +324,11 @@ public async Task RetrieveCameraDevice(bool force = false) public void UpdateCaptureOptions() { - switch (Element.CaptureMode) + cameraTemplate = Element?.CaptureMode switch { - default: - case CameraCaptureMode.Photo: - cameraTemplate = CameraTemplate.Preview; - break; - case CameraCaptureMode.Video: - cameraTemplate = CameraTemplate.Record; - break; - } + CameraCaptureMode.Video => CameraTemplate.Record, + _ => CameraTemplate.Preview, + }; } public void TakePhoto() @@ -337,12 +338,12 @@ public void TakePhoto() try { - if (device != null) + if (device != null && session != null && sessionBuilder != null && photoReader?.Surface != null) { session.StopRepeating(); repeatingIsRunning = false; sessionBuilder.AddTarget(photoReader.Surface); - sessionBuilder.Set(CaptureRequest.FlashMode, (int)flashMode); + sessionBuilder.Set(CaptureRequest.FlashMode ?? throw new NullReferenceException(), (int)flashMode); /*sessionBuilder.Set(CaptureRequest.JpegOrientation, GetJpegOrientation());*/ session.Capture(sessionBuilder.Build(), null, null); sessionBuilder.RemoveTarget(photoReader.Surface); @@ -355,7 +356,7 @@ public void TakePhoto() } } - void OnPhoto(object sender, Tuple tuple) => + void OnPhoto(object sender, Tuple tuple) => Device.BeginInvokeOnMainThread(() => Element?.RaiseMediaCaptured(new MediaCapturedEventArgs(tuple.Item1, tuple.Item2, tuple.Item3))); @@ -367,12 +368,13 @@ void SetupImageReader() { DisposeImageReader(); + _ = photoSize ?? throw new NullReferenceException(); photoReader = ImageReader.NewInstance(photoSize.Width, photoSize.Height, ImageFormatType.Jpeg, maxImages: 1); var readerListener = new ImageAvailableListener(); readerListener.Photo += (_, bytes) => { - string filePath = null; + string? filePath = null; // Calculate image rotation based on sensor and device orientation var rotation = GetRotationCompensation(); @@ -388,21 +390,25 @@ void SetupImageReader() OnPhoto(this, new Tuple(filePath, Element.SavePhotoToFile ? null : bytes));*/ Sound(MediaActionSoundType.ShutterClick); - OnPhoto(this, new Tuple(filePath, bytes, rotation)); + OnPhoto(this, new Tuple(filePath, bytes, rotation)); }; photoReader.SetOnImageAvailableListener(readerListener, backgroundHandler); } - private int GetRotationCompensation() + int GetRotationCompensation() { + _ = cameraId ?? throw new NullReferenceException(); + var rotationCompensation = GetDisplayRotationDegrees(); - var c = Manager.GetCameraCharacteristics(cameraId); + var cameraCharacteristics = Manager.GetCameraCharacteristics(cameraId); + // Get the device's sensor orientation. - var sensorOrientation = (int)c.Get(CameraCharacteristics.SensorOrientation); + var sensorOrientation = (int)(cameraCharacteristics.Get(CameraCharacteristics.SensorOrientation) ?? throw new NullReferenceException()); + var lensFacing = (Integer)(cameraCharacteristics.Get(CameraCharacteristics.LensFacing) ?? throw new NullReferenceException()); - var facingFront = ((Integer)c.Get(CameraCharacteristics.LensFacing)).IntValue() == (int)LensFacing.Front; - if (facingFront) + var isfacingFront = lensFacing.IntValue() == (int)LensFacing.Front; + if (isfacingFront) { rotationCompensation = (sensorOrientation + rotationCompensation) % 360; } @@ -430,6 +436,8 @@ void SetupMediaRecorder(Surface previewSurface) mediaRecorder.SetProfile(profile); else { + _ = videoSize ?? throw new NullReferenceException(); + mediaRecorder.SetOutputFormat(OutputFormat.Mpeg4); mediaRecorder.SetVideoEncodingBitRate(10000000); mediaRecorder.SetVideoFrameRate(30); @@ -447,7 +455,7 @@ void SetupMediaRecorder(Surface previewSurface) mediaRecorder.Prepare(); } - CamcorderProfile GetCamcoderProfile() + CamcorderProfile? GetCamcoderProfile() { var cameraId = Convert.ToInt32(this.cameraId); if (CamcorderProfile.HasProfile(cameraId, CamcorderQuality.HighSpeed1080p)) @@ -529,7 +537,10 @@ async Task PrepareSession() { CloseSession(); - sessionBuilder = device.CreateCaptureRequest(cameraTemplate); + if (mediaRecorder == null || device == null || cameraTemplate is not CameraTemplate cameraTemplate_nonNull) + throw new NullReferenceException(); + + sessionBuilder = device.CreateCaptureRequest(cameraTemplate_nonNull); SetFlash(); SetVideoStabilization(); @@ -538,32 +549,38 @@ async Task PrepareSession() var surfaces = new List(); // preview texture - if (texture.IsAvailable && previewSize != null) + if (previewSize != null && texture?.IsAvailable is true) { - var texture = this.texture.SurfaceTexture; + var texture = this.texture.SurfaceTexture ?? throw new NullReferenceException(); texture.SetDefaultBufferSize(previewSize.Width, previewSize.Height); var previewSurface = new Surface(texture); surfaces.Add(previewSurface); sessionBuilder.AddTarget(previewSurface); // video mode - if (cameraTemplate == CameraTemplate.Record) + if (cameraTemplate is CameraTemplate.Record) { SetupMediaRecorder(previewSurface); var mediaSurface = mediaRecorder.Surface; - surfaces.Add(mediaSurface); - sessionBuilder.AddTarget(mediaSurface); + + if (mediaSurface != null) + { + surfaces.Add(mediaSurface); + sessionBuilder.AddTarget(mediaSurface); + } } // photo mode else { SetupImageReader(); - surfaces.Add(photoReader.Surface); + + if (photoReader?.Surface != null) + surfaces.Add(photoReader.Surface); } } - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(); device.CreateCaptureSession( surfaces, @@ -572,7 +589,7 @@ async Task PrepareSession() OnConfigureFailedAction = captureSession => { tcs.SetResult(null); - Element.RaiseMediaCaptureFailed("Failed to create captire sesstion"); + Element?.RaiseMediaCaptureFailed("Failed to create captire sesstion"); }, OnConfiguredAction = captureSession => tcs.SetResult(captureSession) }, @@ -630,10 +647,10 @@ public void UpdateRepeatingRequest() if (repeatingIsRunning) session.StopRepeating(); - sessionBuilder.Set(CaptureRequest.ControlMode, (int)ControlMode.Auto); - sessionBuilder.Set(CaptureRequest.ControlAeMode, (int)ControlAEMode.On); + sessionBuilder.Set(CaptureRequest.ControlMode ?? throw new NullReferenceException(), (int)ControlMode.Auto); + sessionBuilder.Set(CaptureRequest.ControlAeMode ?? throw new NullReferenceException(), (int)ControlAEMode.On); if (cameraTemplate == CameraTemplate.Record) - sessionBuilder.Set(CaptureRequest.FlashMode, (int)flashMode); + sessionBuilder.Set(CaptureRequest.FlashMode ?? throw new NullReferenceException(), (int)flashMode); session.SetRepeatingRequest(sessionBuilder.Build(), listener: null, backgroundHandler); repeatingIsRunning = true; @@ -687,17 +704,20 @@ public void CloseDevice() } } - void UpdateBackgroundColor() => - View?.SetBackgroundColor(Element.BackgroundColor.ToAndroid()); + void UpdateBackgroundColor() + { + if (Element != null) + View?.SetBackgroundColor(Element.BackgroundColor.ToAndroid()); + } public void SetFlash() { if (!flashSupported) return; - flashMode = Element.FlashMode switch + flashMode = Element?.FlashMode switch { - CameraFlashMode.Off => FlashMode.Off, + CameraFlashMode.Off or null => FlashMode.Off, CameraFlashMode.Torch => FlashMode.Torch, _ => FlashMode.Single, }; @@ -707,35 +727,37 @@ public void SetVideoStabilization() { if (sessionBuilder == null || !stabilizationSupported) return; - sessionBuilder.Set(CaptureRequest.ControlVideoStabilizationMode, - (int)(Element.VideoStabilization ? ControlVideoStabilizationMode.On : ControlVideoStabilizationMode.Off)); + sessionBuilder.Set(CaptureRequest.ControlVideoStabilizationMode ?? throw new NullReferenceException(), + (int)((Element?.VideoStabilization ?? false) ? ControlVideoStabilizationMode.On : ControlVideoStabilizationMode.Off)); } public void ApplyZoom() { + _ = Element ?? throw new NullReferenceException(); + zoom = (float)System.Math.Max(1f, System.Math.Min(Element.Zoom, maxDigitalZoom)); if (ZoomSupported) - sessionBuilder?.Set(CaptureRequest.ScalerCropRegion, GetZoomRect()); + sessionBuilder?.Set(CaptureRequest.ScalerCropRegion ?? throw new NullReferenceException(), GetZoomRect()); } - string GetCameraId() + string? GetCameraId() { var cameraIdList = Manager.GetCameraIdList(); if (cameraIdList.Length == 0) return null; - string FilterCameraByLens(LensFacing lensFacing) + string? FilterCameraByLens(LensFacing lensFacing) { foreach (var id in cameraIdList) { var characteristics = Manager.GetCameraCharacteristics(id); - if (lensFacing == (LensFacing)(int)characteristics.Get(CameraCharacteristics.LensFacing)) + if (lensFacing == (LensFacing)(int)(characteristics?.Get(CameraCharacteristics.LensFacing) ?? throw new NullReferenceException())) return id; } return null; } - return Element.CameraOptions switch + return Element?.CameraOptions switch { CameraOptions.Front => FilterCameraByLens(LensFacing.Front), CameraOptions.Back => FilterCameraByLens(LensFacing.Back), @@ -745,23 +767,23 @@ string FilterCameraByLens(LensFacing lensFacing) } #region TextureView.ISurfaceTextureListener - async void TextureView.ISurfaceTextureListener.OnSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) + async void TextureView.ISurfaceTextureListener.OnSurfaceTextureAvailable(SurfaceTexture? surface, int width, int height) { UpdateBackgroundColor(); UpdateCaptureOptions(); await RetrieveCameraDevice(); } - void TextureView.ISurfaceTextureListener.OnSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) => + void TextureView.ISurfaceTextureListener.OnSurfaceTextureSizeChanged(SurfaceTexture? surface, int width, int height) => ConfigureTransform(width, height); - bool TextureView.ISurfaceTextureListener.OnSurfaceTextureDestroyed(SurfaceTexture surface) + bool TextureView.ISurfaceTextureListener.OnSurfaceTextureDestroyed(SurfaceTexture? surface) { CloseDevice(); return true; } - void TextureView.ISurfaceTextureListener.OnSurfaceTextureUpdated(SurfaceTexture surface) + void TextureView.ISurfaceTextureListener.OnSurfaceTextureUpdated(SurfaceTexture? surface) { } #endregion @@ -776,7 +798,7 @@ async Task RequestCameraPermissions() cameraPermissionsGranted = ContextCompat.CheckSelfPermission(Context, Manifest.Permission.Camera) == Permission.Granted; if (!cameraPermissionsGranted) permissionsToRequest.Add(Manifest.Permission.Camera); - if (Element.CaptureMode == CameraCaptureMode.Video) + if (Element?.CaptureMode == CameraCaptureMode.Video) { audioPermissionsGranted = ContextCompat.CheckSelfPermission(Context, Manifest.Permission.RecordAudio) == Permission.Granted; if (!audioPermissionsGranted) @@ -804,14 +826,14 @@ public override void OnRequestPermissionsResult(int requestCode, string[] permis { cameraPermissionsGranted = grantResults[i] == Permission.Granted; if (!cameraPermissionsGranted) - Element.RaiseMediaCaptureFailed($"No permission to use the camera."); + Element?.RaiseMediaCaptureFailed($"No permission to use the camera."); } else if (permissions[i] == Manifest.Permission.RecordAudio) { audioPermissionsGranted = grantResults[i] == Permission.Granted; if (!audioPermissionsGranted) { - Element.RaiseMediaCaptureFailed($"No permission to record audio."); + Element?.RaiseMediaCaptureFailed($"No permission to record audio."); } } } @@ -820,7 +842,7 @@ public override void OnRequestPermissionsResult(int requestCode, string[] permis #endregion #region Helpers - void LogError(string desc, Java.Lang.Exception ex = null) + void LogError(string desc, Java.Lang.Exception? ex = null) { var newLine = System.Environment.NewLine; var sb = new StringBuilder(desc); @@ -868,60 +890,66 @@ string ConstructMediaFilename(string prefix, string extension) { // "To improve user privacy, direct access to shared/external storage devices is deprecated" // Env.GetExternalStoragePublicDirectory(Env.DirectoryDcim).AbsolutePath - var path = Context.GetExternalFilesDir(Env.DirectoryDcim).AbsolutePath; + var path = Context.GetExternalFilesDir(Env.DirectoryDcim)?.AbsolutePath ?? throw new NullReferenceException(); + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + var fileName = DateTime.Now.ToString("yyyyddMM_HHmmss"); + if (!string.IsNullOrEmpty(prefix)) fileName = $"{prefix}_{fileName}"; + return System.IO.Path.Combine(path, $"{fileName}.{extension}"); } - Rect GetZoomRect() + Rect? GetZoomRect() { if (activeRect == null) return null; + var width = activeRect.Width(); var heigth = activeRect.Height(); var newWidth = (int)(width / zoom); var newHeight = (int)(heigth / zoom); var x = (width - newWidth) / 2; var y = (heigth - newHeight) / 2; + return new Rect(x, y, x + newWidth, y + newHeight); } - SurfaceOrientation GetDisplayRotation() - => App.Context.GetSystemService(Context.WindowService).JavaCast().DefaultDisplay.Rotation; + SurfaceOrientation? GetDisplayRotation() + => App.Context.GetSystemService(Context.WindowService).JavaCast()?.DefaultDisplay?.Rotation; - int GetDisplayRotationDegrees() => - GetDisplayRotation() switch - { - SurfaceOrientation.Rotation90 => 90, - SurfaceOrientation.Rotation180 => 180, - SurfaceOrientation.Rotation270 => 270, - _ => 0, - }; + int GetDisplayRotationDegrees() => GetDisplayRotation() switch + { + SurfaceOrientation.Rotation90 => 90, + SurfaceOrientation.Rotation180 => 180, + SurfaceOrientation.Rotation270 => 270, + _ => 0, + }; - int GetJpegRotationDegrees() => - GetDisplayRotation() switch - { - SurfaceOrientation.Rotation90 => 0, - SurfaceOrientation.Rotation180 => 270, - SurfaceOrientation.Rotation270 => 180, - _ => 90, - }; + int GetJpegRotationDegrees() => GetDisplayRotation() switch + { + SurfaceOrientation.Rotation90 => 0, + SurfaceOrientation.Rotation180 => 270, + SurfaceOrientation.Rotation270 => 180, + _ => 90, + }; - int GetPreviewOrientation() => - GetDisplayRotation() switch - { - SurfaceOrientation.Rotation90 => 270, - SurfaceOrientation.Rotation180 => 180, - SurfaceOrientation.Rotation270 => 90, - _ => 0, - }; + int GetPreviewOrientation() => GetDisplayRotation() switch + { + SurfaceOrientation.Rotation90 => 270, + SurfaceOrientation.Rotation180 => 180, + SurfaceOrientation.Rotation270 => 90, + _ => 0, + }; - public void ConfigureTransform() => + public void ConfigureTransform() + { + _ = texture ?? throw new NullReferenceException(); ConfigureTransform(texture.Width, texture.Height); + } void ConfigureTransform(int viewWidth, int viewHeight) { @@ -930,7 +958,7 @@ void ConfigureTransform(int viewWidth, int viewHeight) if (texture == null || previewSize == null || activity == null) return; - var rotation = (int)activity.WindowManager.DefaultDisplay.Rotation; + var rotation = (int?)activity.WindowManager?.DefaultDisplay?.Rotation; var matrix = new Matrix(); var viewRect = new RectF(0, 0, viewWidth, viewHeight); var bufferRect = new RectF(0, 0, previewSize.Height, previewSize.Width); @@ -943,7 +971,7 @@ void ConfigureTransform(int viewWidth, int viewHeight) matrix.SetRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.Fill); var scale = System.Math.Max((float)viewHeight / previewSize.Height, (float)viewWidth / previewSize.Width); matrix.PostScale(scale, scale, centerX, centerY); - matrix.PostRotate(90 * (rotation - 2), centerX, centerY); + matrix.PostRotate(90 * (rotation.Value - 2), centerX, centerY); } else if (rotation == (int)SurfaceOrientation.Rotation180) matrix.PostRotate(180, centerX, centerY); @@ -965,11 +993,12 @@ void Sound(MediaActionSoundType soundType) mediaSound.Play(soundType); } - ASize GetMaxSize(ASize[] imageSizes) + ASize GetMaxSize(ASize[]? imageSizes) { - ASize maxSize = null; + ASize? maxSize = null; long maxPixels = 0; - for (var i = 0; i < imageSizes.Length; i++) + + for (var i = 0; i < imageSizes?.Length; i++) { long currentPixels = imageSizes[i].Width * imageSizes[i].Height; if (currentPixels > maxPixels) @@ -978,7 +1007,8 @@ ASize GetMaxSize(ASize[] imageSizes) maxPixels = currentPixels; } } - return maxSize; + + return maxSize ?? throw new NullReferenceException(); } // chooses the smallest one whose width and height are at least as large as the respective requested values @@ -986,8 +1016,10 @@ ASize ChooseOptimalSize(ASize[] choices, int width, int height, int maxWidth, in { var bigEnough = new List(); var notBigEnough = new List(); + var w = aspectRatio.Width; var h = aspectRatio.Height; + foreach (var option in choices) { if (option.Width <= maxWidth && option.Height <= maxHeight && diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraStateListener.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraStateListener.android.cs index d8c051be1..b5423fa06 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraStateListener.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraStateListener.android.cs @@ -1,22 +1,21 @@ using System; -using System.Collections.Generic; using Android.Hardware.Camera2; namespace Xamarin.CommunityToolkit.UI.Views { class CameraStateListener : CameraDevice.StateCallback { - public Action OnOpenedAction; - public Action OnDisconnectedAction; - public Action OnErrorAction; - public Action OnClosedAction; + public Action? OnOpenedAction; + public Action? OnDisconnectedAction; + public Action? OnErrorAction; + public Action? OnClosedAction; public override void OnOpened(CameraDevice camera) => OnOpenedAction?.Invoke(camera); public override void OnDisconnected(CameraDevice camera) => OnDisconnectedAction?.Invoke(camera); - public override void OnError(CameraDevice camera, CameraError error) => OnErrorAction(camera, error); + public override void OnError(CameraDevice camera, CameraError error) => OnErrorAction?.Invoke(camera, error); - public override void OnClosed(CameraDevice camera) => OnClosedAction(camera); + public override void OnClosed(CameraDevice camera) => OnClosedAction?.Invoke(camera); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraViewRenderer.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraViewRenderer.android.cs index e8fffa282..c5bdb8e8e 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraViewRenderer.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/CameraViewRenderer.android.cs @@ -24,17 +24,19 @@ namespace Xamarin.CommunityToolkit.UI.Views { public class CameraViewRenderer : FrameLayout, IVisualElementRenderer, IViewRenderer { + readonly MotionEventHelper motionEventHelper; + int? defaultLabelFor; bool disposed; - CameraView element; - VisualElementTracker visualElementTracker; - VisualElementRenderer visualElementRenderer; - readonly MotionEventHelper motionEventHelper; - FragmentManager fragmentManager; + CameraView? element; + VisualElementTracker? visualElementTracker; + VisualElementRenderer? visualElementRenderer; + + FragmentManager? fragmentManager; FragmentManager FragmentManager => fragmentManager ??= Context.GetFragmentManager(); - CameraFragment camerafragment; + CameraFragment? camerafragment; public CameraViewRenderer(Context context) : base(context) @@ -43,12 +45,14 @@ public CameraViewRenderer(Context context) visualElementRenderer = new VisualElementRenderer(this); } - public event EventHandler ElementChanged; + public event EventHandler? ElementChanged; - public event EventHandler ElementPropertyChanged; + public event EventHandler? ElementPropertyChanged; async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { + _ = camerafragment ?? throw new NullReferenceException(); + ElementPropertyChanged?.Invoke(this, e); switch (e.PropertyName) @@ -62,7 +66,7 @@ async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) break; case nameof(CameraView.FlashMode): camerafragment.SetFlash(); - if (Element.CaptureMode == CameraCaptureMode.Video) + if (Element?.CaptureMode == CameraCaptureMode.Video) camerafragment.UpdateRepeatingRequest(); break; case nameof(CameraView.Zoom): @@ -71,7 +75,7 @@ async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) break; case nameof(CameraView.VideoStabilization): camerafragment.SetVideoStabilization(); - if (Element.CaptureMode == CameraCaptureMode.Video) + if (Element?.CaptureMode == CameraCaptureMode.Video) camerafragment.UpdateRepeatingRequest(); break; @@ -86,15 +90,16 @@ async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) } } - void OnElementChanged(ElementChangedEventArgs e) + void OnElementChanged(ElementChangedEventArgs e) { - CameraFragment newfragment = null; + CameraFragment? newfragment = null; if (e.OldElement != null) { e.OldElement.PropertyChanged -= OnElementPropertyChanged; e.OldElement.ShutterClicked -= OnShutterClicked; - camerafragment.Dispose(); + camerafragment?.Dispose(); + camerafragment = null; } if (e.NewElement != null) @@ -115,7 +120,7 @@ void OnElementChanged(ElementChangedEventArgs e) ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement)); } - CameraView Element + CameraView? Element { get => element; set @@ -126,7 +131,7 @@ CameraView Element var oldElement = element; element = value; - OnElementChanged(new ElementChangedEventArgs(oldElement, element)); + OnElementChanged(new ElementChangedEventArgs(oldElement, element)); // this is just used to set ID's to the NativeViews along time ago for UITest with Test Cloud // https://discordapp.com/channels/732297728826277939/738043671575920700/747629874709266449 @@ -136,7 +141,7 @@ CameraView Element public override bool OnTouchEvent(MotionEvent? e) { - if (visualElementRenderer.OnTouchEvent(e) || base.OnTouchEvent(e)) + if (visualElementRenderer?.OnTouchEvent(e) is true || base.OnTouchEvent(e)) return true; return motionEventHelper.HandleMotionEvent(Parent, e); @@ -147,7 +152,8 @@ protected override void Dispose(bool disposing) if (disposed) return; - camerafragment.Dispose(); + camerafragment?.Dispose(); + camerafragment = null; disposed = true; @@ -182,25 +188,25 @@ protected override void Dispose(bool disposing) void OnShutterClicked(object sender, EventArgs e) { - switch (Element.CaptureMode) + switch (Element?.CaptureMode) { default: case CameraCaptureMode.Default: case CameraCaptureMode.Photo: - camerafragment.TakePhoto(); + camerafragment?.TakePhoto(); break; case CameraCaptureMode.Video: - if (!camerafragment.IsRecordingVideo) - camerafragment.StartRecord(); + if (camerafragment?.IsRecordingVideo is false) + camerafragment?.StartRecord(); else - camerafragment.StopRecord(); + camerafragment?.StopRecord(); break; } } void IViewRenderer.MeasureExactly() => MeasureExactly(this, Element, Context); - static void MeasureExactly(AView control, VisualElement element, Context context) + static void MeasureExactly(AView control, VisualElement? element, Context? context) { if (control == null || element == null) return; @@ -221,11 +227,11 @@ static void MeasureExactly(AView control, VisualElement element, Context context } #region IVisualElementRenderer - VisualElement IVisualElementRenderer.Element => Element; + VisualElement? IVisualElementRenderer.Element => Element; - ViewGroup IVisualElementRenderer.ViewGroup => null; + ViewGroup? IVisualElementRenderer.ViewGroup => null; - VisualElementTracker IVisualElementRenderer.Tracker => visualElementTracker; + VisualElementTracker? IVisualElementRenderer.Tracker => visualElementTracker; AView IVisualElementRenderer.View => this; @@ -238,7 +244,7 @@ SizeRequest IVisualElementRenderer.GetDesiredSize(int widthConstraint, int heigh void IVisualElementRenderer.SetElement(VisualElement element) { - if (!(element is CameraView camera)) + if (element is not CameraView camera) throw new ArgumentException($"{nameof(element)} must be of type {nameof(CameraView)}"); // Performance.Start(out var reference); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/MotionEventHelper.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/MotionEventHelper.android.cs index 1b2a3b440..01e96266f 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/MotionEventHelper.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/Android/MotionEventHelper.android.cs @@ -6,20 +6,19 @@ namespace Xamarin.CommunityToolkit.UI.Views { class MotionEventHelper { - VisualElement element; + VisualElement? element; bool isInViewCell; - public bool HandleMotionEvent(IViewParent parent, MotionEvent? motionEvent) + public bool HandleMotionEvent(IViewParent? parent, MotionEvent? motionEvent) { if (isInViewCell || element == null || motionEvent == null || motionEvent.Action == MotionEventActions.Cancel) return false; - var renderer = parent as VisualElementRenderer; - if (renderer == null || ShouldPassThroughElement()) + if (parent is not VisualElementRenderer renderer || ShouldPassThroughElement()) return false; // Let the container know that we're "fake" handling this event - // renderer.NotifyFakeHandling(); + //renderer.NotifyFakeHandling(); return true; } @@ -55,7 +54,7 @@ bool ShouldPassThroughElement() } // This is not a layout and it's transparent; the event can just pass through - if (element.InputTransparent) + if (element?.InputTransparent ?? false) return true; return false; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/UWP/CameraViewRenderer.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/UWP/CameraViewRenderer.uwp.cs index 66138156d..194ce5cba 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/UWP/CameraViewRenderer.uwp.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/CameraView/UWP/CameraViewRenderer.uwp.cs @@ -26,21 +26,19 @@ namespace Xamarin.CommunityToolkit.UI.Views { public class CameraViewRenderer : ViewRenderer { - MediaCapture mediaCapture; + readonly MediaEncodingProfile encodingProfile; + + MediaCapture? mediaCapture; bool isPreviewing; - Lamp flash; - LowLagMediaRecording mediaRecording; - string filePath; + Lamp? flash; + LowLagMediaRecording? mediaRecording; + string? filePath; bool busy; - VideoStabilizationEffect videoStabilizationEffect; - MediaEncodingProfile encodingProfile; - VideoEncodingProperties inputPropertiesBackup; - VideoEncodingProperties outputPropertiesBackup; + VideoStabilizationEffect? videoStabilizationEffect; + VideoEncodingProperties? inputPropertiesBackup; + VideoEncodingProperties? outputPropertiesBackup; - public CameraViewRenderer() - { - encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto); - } + public CameraViewRenderer() => encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto); bool IsBusy { @@ -72,13 +70,15 @@ protected override async void OnElementChanged(ElementChangedEventArgs> GetImage() + async Task> GetImage() { + _ = mediaCapture ?? throw new NullReferenceException(); + IsBusy = true; var imageProp = ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Bgra8); var lowLagCapture = await mediaCapture.PrepareLowLagPhotoCaptureAsync(imageProp); var capturedPhoto = await lowLagCapture.CaptureAsync(); await lowLagCapture.FinishAsync(); - string filePath = null; + string? filePath = null; // See TODO on CameraView.SavePhotoToFile /*if (Element.SavePhotoToFile) @@ -159,24 +161,24 @@ async Task HandleVideo() outputEncoder.SetSoftwareBitmap(capturedPhoto.Frame.SoftwareBitmap); await outputEncoder.FlushAsync(); - byte[] imageData = null; - // See TODO on CameraView.SavePhotoToFile // if (!Element.SavePhotoToFile) // { using var memoryStream = new MemoryStream(); await outputStream.AsStream().CopyToAsync(memoryStream); - imageData = memoryStream.ToArray(); + var imageData = memoryStream.ToArray(); // } IsBusy = false; - return new Tuple(filePath, imageData); + return new Tuple(filePath, imageData); } async Task StartRecord() { + _ = mediaCapture ?? throw new NullReferenceException(); + // TODO replace platform specifics // var localFolder = Element.On().GetVideoFolder(); var localFolder = "Video"; @@ -205,9 +207,9 @@ async Task StartRecord() await mediaRecording.StartAsync(); } - async Task StopRecord() + async Task StopRecord() { - if (mediaRecording == null) + if (mediaRecording == null || mediaCapture == null) return null; await mediaRecording.StopAsync(); @@ -264,6 +266,7 @@ protected override async void OnElementPropertyChanged(object sender, PropertyCh void UpdateZoom() { + _ = mediaCapture ?? throw new NullReferenceException(); var zoomControl = mediaCapture.VideoDeviceController.ZoomControl; if (!zoomControl.Supported) return; @@ -290,7 +293,7 @@ static float Clamp(double value, float min, float max) } } - DeviceInformation FilterCamera(DeviceInformationCollection cameraDevices, Windows.Devices.Enumeration.Panel panel) + DeviceInformation? FilterCamera(DeviceInformationCollection cameraDevices, Windows.Devices.Enumeration.Panel panel) { foreach (var cam in cameraDevices) { @@ -314,23 +317,15 @@ async Task InitializeCameraAsync() } IsBusy = true; - DeviceInformation device = null; - switch (Element.CameraOptions) + + var device = Element.CameraOptions switch { - default: - case CameraOptions.Default: - device = cameraDevices[0]; - break; - case CameraOptions.Front: - device = FilterCamera(cameraDevices, Windows.Devices.Enumeration.Panel.Front); - break; - case CameraOptions.Back: - device = FilterCamera(cameraDevices, Windows.Devices.Enumeration.Panel.Back); - break; - case CameraOptions.External: - device = FilterCamera(cameraDevices, Windows.Devices.Enumeration.Panel.Unknown); - break; - } + CameraOptions.Front => FilterCamera(cameraDevices, Windows.Devices.Enumeration.Panel.Front), + CameraOptions.Back => FilterCamera(cameraDevices, Windows.Devices.Enumeration.Panel.Back), + CameraOptions.External => FilterCamera(cameraDevices, Windows.Devices.Enumeration.Panel.Unknown), + _ => cameraDevices?[0], + }; + if (device == null) { Element?.RaiseMediaCaptureFailed($"{Element.CameraOptions} camera not found."); @@ -353,8 +348,10 @@ async Task InitializeCameraAsync() AudioDeviceId = selectedAudioDevice }); flash = await Lamp.GetDefaultAsync(); - if (mediaCapture?.VideoDeviceController.ZoomControl.Supported ?? false) + + if (mediaCapture.VideoDeviceController.ZoomControl.Supported) Element.MaxZoom = mediaCapture.VideoDeviceController.ZoomControl.Max; + DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape; } catch (UnauthorizedAccessException ex) @@ -415,9 +412,18 @@ protected override async void Dispose(bool disposing) async void CaptureDeviceExclusiveControlStatusChanged(MediaCapture sender, MediaCaptureDeviceExclusiveControlStatusChangedEventArgs args) { if (args.Status == MediaCaptureDeviceExclusiveControlStatus.SharedReadOnlyAvailable) + { Element?.RaiseMediaCaptureFailed("The camera preview can't be displayed because another app has exclusive access"); + } else if (args.Status == MediaCaptureDeviceExclusiveControlStatus.ExclusiveControlAvailable && !isPreviewing) - await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => await mediaCapture.StartPreviewAsync()); + { + await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => + { + if (mediaCapture != null) + await mediaCapture.StartPreviewAsync(); + }); + } + IsBusy = false; } } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/Android/GravatarImageSourceHandler.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/Android/GravatarImageSourceHandler.android.cs index 356937c6c..1ade839bc 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/Android/GravatarImageSourceHandler.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/Android/GravatarImageSourceHandler.android.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System; +using System.Threading; using System.Threading.Tasks; using Android.Content; using Android.Graphics; @@ -10,11 +11,11 @@ namespace Xamarin.CommunityToolkit.UI.Views { public partial class GravatarImageSourceHandler : IImageSourceHandler { - public async Task LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default) + public async Task LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default) { - var fileInfo = await LoadInternal(imagesource, 1, Application.Context.CacheDir.AbsolutePath); + var fileInfo = await LoadInternal(imagesource, 1, Application.Context.CacheDir?.AbsolutePath ?? throw new NullReferenceException()); - Bitmap bitmap = null; + Bitmap? bitmap = null; try { await semaphore.WaitAsync(); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/MacOS/GravatarImageSourceHandler.macos.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/MacOS/GravatarImageSourceHandler.macos.cs index 330b57075..e77db2578 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/MacOS/GravatarImageSourceHandler.macos.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/MacOS/GravatarImageSourceHandler.macos.cs @@ -8,11 +8,11 @@ namespace Xamarin.CommunityToolkit.UI.Views { public partial class GravatarImageSourceHandler : IImageSourceHandler { - public async Task LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = default, float scale = 1) + public async Task LoadImageAsync(ImageSource imagesource, CancellationToken cancelationToken = default, float scale = 1) { var fileInfo = await LoadInternal(imagesource, 1, GetCacheDirectory()); - NSImage image = null; + NSImage? image = null; try { await semaphore.WaitAsync(); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/UWP/GravatarImageSourceHandler.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/UWP/GravatarImageSourceHandler.uwp.cs index 6a9301a74..f291022ac 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/UWP/GravatarImageSourceHandler.uwp.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/UWP/GravatarImageSourceHandler.uwp.cs @@ -12,11 +12,11 @@ namespace Xamarin.CommunityToolkit.UI.Views { public partial class GravatarImageSourceHandler : IImageSourceHandler { - public async Task LoadImageAsync(FormsImageSource imagesource, CancellationToken cancellationToken = default) + public async Task LoadImageAsync(FormsImageSource imagesource, CancellationToken cancellationToken = default) { var fileInfo = await LoadInternal(imagesource, 1, ApplicationData.Current.LocalCacheFolder.Path); - BitmapImage bitmap = null; + BitmapImage? bitmap = null; try { await semaphore.WaitAsync(); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/Wpf/GravatarImageSourceHandler.wpf.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/Wpf/GravatarImageSourceHandler.wpf.cs index d2b78f88e..cd50af624 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/Wpf/GravatarImageSourceHandler.wpf.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/GravatarImageSource/Wpf/GravatarImageSourceHandler.wpf.cs @@ -12,12 +12,12 @@ namespace Xamarin.CommunityToolkit.UI.Views { public partial class GravatarImageSourceHandler : IImageSourceHandler { - public async Task LoadImageAsync(FormsImageSource imagesource, CancellationToken cancellationToken = default) + public async Task LoadImageAsync(FormsImageSource imagesource, CancellationToken cancellationToken = default) { var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); var fileInfo = await LoadInternal(imagesource, 1, appdata); - BitmapImage bitmap = null; + BitmapImage? bitmap = null; try { await semaphore.WaitAsync(); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/MediaElement/Android/MediaElementRenderer.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/MediaElement/Android/MediaElementRenderer.android.cs index 3830b61c8..b7cc3a6e2 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/MediaElement/Android/MediaElementRenderer.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/MediaElement/Android/MediaElementRenderer.android.cs @@ -126,7 +126,7 @@ void IVisualElementRenderer.SetElement(VisualElement element) if (tracker == null) SetTracker(new VisualElementTracker(this)); - OnElementChanged(new ElementChangedEventArgs(oldElement, MediaElement)); + OnElementChanged(new ElementChangedEventArgs(oldElement, MediaElement)); } void StateRequested(object sender, StateRequested e) @@ -163,7 +163,7 @@ void StateRequested(object sender, StateRequested e) void OnPositionRequested(object sender, EventArgs e) { - if (view == null && Controller == null) + if (view == null || Controller == null) return; Controller.Position = view.Position; @@ -171,7 +171,7 @@ void OnPositionRequested(object sender, EventArgs e) void SeekRequested(object sender, SeekRequested e) { - if (view == null) + if (view == null || Controller == null) return; view.SeekTo((int)e.Position.TotalMilliseconds); @@ -189,7 +189,11 @@ void IVisualElementRenderer.SetLabelFor(int? id) void SetTracker(VisualElementTracker tracker) => this.tracker = tracker; - protected virtual void UpdateBackgroundColor() => SetBackgroundColor(Element.BackgroundColor.ToAndroid()); + protected virtual void UpdateBackgroundColor() + { + if (Element != null) + SetBackgroundColor(Element.BackgroundColor.ToAndroid()); + } void IVisualElementRenderer.UpdateLayout() => tracker?.UpdateLayout(); @@ -216,7 +220,7 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } - protected virtual void OnElementChanged(ElementChangedEventArgs e) + protected virtual void OnElementChanged(ElementChangedEventArgs e) { if (e.NewElement != null) { @@ -236,7 +240,7 @@ protected virtual void OnElementChanged(ElementChangedEventArgs Controller.BufferingProgress = e.Percent / 100f; + void OnMpBufferingUpdate(object sender, MediaPlayer.BufferingUpdateEventArgs e) + { + if (Controller != null) + Controller.BufferingProgress = e.Percent / 100f; + } } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/MediaElement/MediaElement.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/MediaElement/MediaElement.shared.cs index db955addf..497935c60 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/MediaElement/MediaElement.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/MediaElement/MediaElement.shared.cs @@ -102,9 +102,9 @@ public TimeSpan Position } [Forms.TypeConverter(typeof(MediaSourceConverter))] - public MediaSource Source + public MediaSource? Source { - get => (MediaSource)GetValue(SourceProperty); + get => (MediaSource?)GetValue(SourceProperty); set => SetValue(SourceProperty, value); } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/Android/PopupRenderer.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/Android/PopupRenderer.android.cs index ba7a49ebf..9afa91448 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/Android/PopupRenderer.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/Android/PopupRenderer.android.cs @@ -125,10 +125,7 @@ void SetEvents(in BasePopup basePopup) basePopup.Dismissed += OnDismissed; } - void SetColor(in BasePopup basePopup) - { - Window.SetBackgroundDrawable(new ColorDrawable(basePopup.Color.ToAndroid())); - } + void SetColor(in BasePopup basePopup) => Window?.SetBackgroundDrawable(new ColorDrawable(basePopup.Color.ToAndroid())); void SetSize(in BasePopup basePopup) { diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/PopupOfT.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/PopupOfT.shared.cs index f091a38e4..d2c62dd92 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/PopupOfT.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/PopupOfT.shared.cs @@ -25,7 +25,7 @@ public abstract class Popup : BasePopup /// /// The result to return. /// - public void Dismiss(T result) + public void Dismiss(T? result) { taskCompletionSource.TrySetResult(result); OnDismissed(result); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/UWP/Popup.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/UWP/Popup.shared.cs index 0217ff2e1..452c9c677 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/UWP/Popup.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/UWP/Popup.shared.cs @@ -1,4 +1,5 @@ -using Xamarin.Forms; +using System; +using Xamarin.Forms; namespace Xamarin.CommunityToolkit.UI.Views.WindowsSpecific { @@ -7,10 +8,10 @@ public static class Popup public static readonly BindableProperty BorderColorProperty = BindableProperty.Create( "BorderColor", typeof(Color), typeof(Views.Popup), default(Color)); - public static void SetBorderColor(BindableObject element, Color color) => - element.SetValue(BorderColorProperty, color); + public static void SetBorderColor(BindableObject? element, Color color) => + element?.SetValue(BorderColorProperty, color); - public static Color GetBorderColor(BindableObject element) => - (Color)element.GetValue(BorderColorProperty); + public static Color GetBorderColor(BindableObject? element) => + (Color)(element?.GetValue(BorderColorProperty) ?? throw new NullReferenceException()); } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/UWP/PopupRenderer.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/UWP/PopupRenderer.uwp.cs index ef2b602ac..00d982d86 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/UWP/PopupRenderer.uwp.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/UWP/PopupRenderer.uwp.cs @@ -19,20 +19,20 @@ public class PopupRenderer : Flyout, IVisualElementRenderer const double defaultBorderThickness = 2; const double defaultSize = 600; bool isDisposed = false; - XamlStyle flyoutStyle; - XamlStyle panelStyle; + XamlStyle? flyoutStyle; + XamlStyle? panelStyle; - public BasePopup Element { get; private set; } + public BasePopup? Element { get; private set; } - internal ViewToRendererConverter.WrapperControl Control { get; private set; } + internal ViewToRendererConverter.WrapperControl? Control { get; private set; } - FrameworkElement IVisualElementRenderer.ContainerElement => null; + FrameworkElement? IVisualElementRenderer.ContainerElement => null; - VisualElement IVisualElementRenderer.Element => Element; + VisualElement? IVisualElementRenderer.Element => Element; - public event EventHandler ElementChanged; + public event EventHandler? ElementChanged; - public event EventHandler ElementPropertyChanged; + public event EventHandler? ElementPropertyChanged; public PopupRenderer() { @@ -43,7 +43,7 @@ void IVisualElementRenderer.SetElement(VisualElement element) if (element == null) throw new ArgumentNullException(nameof(element)); - if (!(element is BasePopup popup)) + if (element is not BasePopup popup) throw new ArgumentNullException("Element is not of type " + typeof(BasePopup), nameof(element)); var oldElement = Element; @@ -55,14 +55,14 @@ void IVisualElementRenderer.SetElement(VisualElement element) element.PropertyChanged += OnElementPropertyChanged; - OnElementChanged(new ElementChangedEventArgs(oldElement, Element)); + OnElementChanged(new ElementChangedEventArgs(oldElement, Element)); } void CreateControl() { - if (Control == null) + if (Control == null && Element != null) { - Control = new Xamarin.CommunityToolkit.UI.Views.ViewToRendererConverter.WrapperControl(Element.Content); + Control = new ViewToRendererConverter.WrapperControl(Element.Content); Content = Control; } } @@ -73,7 +73,7 @@ void InitializeStyles() panelStyle = new XamlStyle { TargetType = typeof(Panel) }; } - protected virtual void OnElementChanged(ElementChangedEventArgs e) + protected virtual void OnElementChanged(ElementChangedEventArgs e) { if (e.NewElement != null && !isDisposed) { @@ -110,14 +110,18 @@ void ConfigureControl() void SetEvents() { - if (Element.IsLightDismissEnabled) + if (Element?.IsLightDismissEnabled is true) Closing += OnClosing; - Element.Dismissed += OnDismissed; + if (Element != null) + Element.Dismissed += OnDismissed; } void SetSize() { + _ = Element ?? throw new NullReferenceException(); + _ = Control ?? throw new NullReferenceException(); + _ = flyoutStyle ?? throw new NullReferenceException(); var standardSize = new Size { Width = defaultSize, Height = defaultSize / 2 }; var currentSize = Element.Size != default(Size) ? Element.Size : standardSize; @@ -133,15 +137,19 @@ void SetSize() void SetLayout() { LightDismissOverlayMode = LightDismissOverlayMode.On; - SetDialogPosition(Element.VerticalOptions, Element.HorizontalOptions); + + if (Element != null) + SetDialogPosition(Element.VerticalOptions, Element.HorizontalOptions); } void SetBorderColor() { + _ = flyoutStyle ?? throw new NullReferenceException(); + flyoutStyle.Setters.Add(new Windows.UI.Xaml.Setter(FlyoutPresenter.PaddingProperty, 0)); flyoutStyle.Setters.Add(new Windows.UI.Xaml.Setter(FlyoutPresenter.BorderThicknessProperty, new UWPThickness(defaultBorderThickness))); - var borderColor = Views.WindowsSpecific.Popup.GetBorderColor(Element); + var borderColor = WindowsSpecific.Popup.GetBorderColor(Element); if (borderColor == default(Color)) flyoutStyle.Setters.Add(new Windows.UI.Xaml.Setter(FlyoutPresenter.BorderBrushProperty, Color.FromHex("#2e6da0").ToWindowsColor())); else @@ -150,6 +158,10 @@ void SetBorderColor() void SetColor() { + _ = Element ?? throw new NullReferenceException(); + _ = panelStyle ?? throw new NullReferenceException(); + _ = flyoutStyle ?? throw new NullReferenceException(); + if (Element.Content.BackgroundColor == default(Color)) panelStyle.Setters.Add(new Windows.UI.Xaml.Setter(Panel.BackgroundProperty, Element.Color.ToWindowsColor())); @@ -163,13 +175,14 @@ void SetColor() void ApplyStyles() { + _ = Control ?? throw new NullReferenceException(); Control.Style = panelStyle; FlyoutPresenterStyle = flyoutStyle; } void Show() { - if (Element.Anchor != null) + if (Element?.Anchor != null) { var anchor = Platform.GetRenderer(Element.Anchor).ContainerElement; FlyoutBase.SetAttachedFlyout(anchor, this); @@ -177,12 +190,12 @@ void Show() } else { - var frameworkElement = Platform.GetRenderer(Element.Parent as VisualElement).ContainerElement; + var frameworkElement = Platform.GetRenderer(Element?.Parent as VisualElement)?.ContainerElement; FlyoutBase.SetAttachedFlyout(frameworkElement, this); FlyoutBase.ShowAttachedFlyout(frameworkElement); } - Element.OnOpened(); + Element?.OnOpened(); } void SetDialogPosition(LayoutOptions verticalOptions, LayoutOptions horizontalOptions) @@ -203,7 +216,7 @@ void SetDialogPosition(LayoutOptions verticalOptions, LayoutOptions horizontalOp Placement = FlyoutPlacementMode.BottomEdgeAlignedLeft; else if (IsLeft()) Placement = FlyoutPlacementMode.Left; - else if (Element.Anchor == null) + else if (Element?.Anchor == null) Placement = FlyoutPlacementMode.Full; else Placement = FlyoutPlacementMode.Top; @@ -230,7 +243,7 @@ SizeRequest IVisualElementRenderer.GetDesiredSize(double widthConstraint, double return new SizeRequest(size); } - UIElement IVisualElementRenderer.GetNativeElement() => Control; + UIElement? IVisualElementRenderer.GetNativeElement() => Control; void OnDismissed(object sender, PopupDismissedEventArgs e) { @@ -239,7 +252,7 @@ void OnDismissed(object sender, PopupDismissedEventArgs e) void OnClosing(object sender, object e) { - if (IsOpen && Element.IsLightDismissEnabled) + if (IsOpen && Element?.IsLightDismissEnabled is true) Element.LightDismiss(); } @@ -253,10 +266,13 @@ protected virtual void Dispose(bool disposing) { if (!isDisposed && disposing) { - Element.Dismissed -= OnDismissed; - Element = null; + if (Element != null) + Element.Dismissed -= OnDismissed; + + if (Control != null) + Control.CleanUp(); - Control.CleanUp(); + Element = null; Control = null; Closed -= OnClosing; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/RangeSlider/ThumbFrame.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/RangeSlider/ThumbFrame.shared.cs index 09b9dcd38..3b8ede1e3 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/RangeSlider/ThumbFrame.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/RangeSlider/ThumbFrame.shared.cs @@ -1,4 +1,5 @@ -using Xamarin.Forms; +using System; +using Xamarin.Forms; namespace Xamarin.CommunityToolkit.UI.Views { @@ -9,7 +10,7 @@ public ThumbFrame() #region Required work-around to prevent linker from removing the platform-specific implementation #if __ANDROID__ if (System.DateTime.Now.Ticks < 0) - _ = new ThumbFrameRenderer(null); + _ = new ThumbFrameRenderer(ToolkitPlatform.Context ?? throw new NullReferenceException()); #endif #endregion } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Shield.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Shield.shared.cs index 716cf6b92..8d75f9c01 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Shield.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Shield.shared.cs @@ -342,7 +342,7 @@ void UpdateIsEnabled() GestureRecognizers.Clear(); } - void OnCloseButtonTapped(object sender, EventArgs e) + void OnCloseButtonTapped(object? sender, EventArgs e) { Tapped?.Invoke(this, EventArgs.Empty); Command?.Execute(CommandParameter); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/SideMenuView/SideMenuView.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/SideMenuView/SideMenuView.shared.cs index 339bb2b72..d9c4ce28c 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/SideMenuView/SideMenuView.shared.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/SideMenuView/SideMenuView.shared.cs @@ -82,7 +82,7 @@ public SideMenuView() #region Required work-around to prevent linker from removing the platform-specific implementation #if __ANDROID__ if (System.DateTime.Now.Ticks < 0) - _ = new Xamarin.CommunityToolkit.Android.UI.Views.SideMenuViewRenderer(null); + _ = new Xamarin.CommunityToolkit.Android.UI.Views.SideMenuViewRenderer(ToolkitPlatform.Context ?? throw new NullReferenceException()); #elif __IOS__ if (System.DateTime.Now.Ticks < 0) _ = new Xamarin.CommunityToolkit.iOS.UI.Views.SideMenuViewRenderer(); @@ -147,7 +147,7 @@ public static bool GetMenuGestureEnabled(BindableObject bindable) public static void SetMenuGestureEnabled(BindableObject bindable, bool value) => bindable.SetValue(MenuGestureEnabledProperty, value); - internal void OnPanUpdated(object sender, PanUpdatedEventArgs e) + internal void OnPanUpdated(object? sender, PanUpdatedEventArgs e) { var shift = e.TotalX; var verticalShift = e.TotalY; @@ -507,7 +507,7 @@ void CleanTimeShiftItems() } } - void OnChildrenCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + void OnChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { HandleChildren(e.OldItems, RemoveChild); HandleChildren(e.NewItems, AddChild); @@ -561,7 +561,7 @@ void RemoveChild(View view) inactiveMenu = null; } - void OnLayoutChanged(object sender, EventArgs e) + void OnLayoutChanged(object? sender, EventArgs e) { if (mainView == null) return; diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/SideMenuView/SideMenuViewRenderer.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/SideMenuView/SideMenuViewRenderer.android.cs index 1b4649fbe..39151aaa1 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/SideMenuView/SideMenuViewRenderer.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/SideMenuView/SideMenuViewRenderer.android.cs @@ -31,7 +31,7 @@ public class SideMenuViewRenderer : VisualElementRenderer public SideMenuViewRenderer(Context context) : base(context) - => density = context.Resources.DisplayMetrics.Density; + => density = context.Resources?.DisplayMetrics?.Density ?? throw new NullReferenceException(); double GestureThreshold => Element.GestureThreshold >= 0 ? Element.GestureThreshold diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/SnackBarLayout.uwp.wpf.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/SnackBarLayout.uwp.wpf.cs index c9280f9a7..1d6c43371 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/SnackBarLayout.uwp.wpf.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/SnackBarLayout.uwp.wpf.cs @@ -72,7 +72,8 @@ public SnackBarLayout(SnackBarOptions options) Command = new Forms.Command(async () => { OnSnackBarActionExecuted?.Invoke(); - await action.Action(); + if (action.Action != null) + await action.Action(); }), Padding = new Thickness(action.Padding.Left, action.Padding.Top, @@ -101,6 +102,6 @@ public SnackBarLayout(SnackBarOptions options) } } - public Action OnSnackBarActionExecuted; + public Action? OnSnackBarActionExecuted; } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/MacOSSnackBar.macos.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/MacOSSnackBar.macos.cs index 7d3410055..28763162c 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/MacOSSnackBar.macos.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/MacOSSnackBar.macos.cs @@ -10,9 +10,9 @@ namespace Xamarin.CommunityToolkit.UI.Views.Helpers.macOS { class NativeSnackBar { - NSTimer timer; + NSTimer? timer; - public Func TimeoutAction { get; protected set; } + public Func? TimeoutAction { get; protected set; } public List Actions { get; protected set; } = new List(); @@ -22,9 +22,9 @@ class NativeSnackBar public SnackBarLayout Layout { get; } = new SnackBarLayout(); - public string Message { get; protected set; } + public string Message { get; protected set; } = string.Empty; - protected BaseSnackBarView SnackBarView { get; set; } + protected BaseSnackBarView? SnackBarView { get; set; } public void Dismiss() { @@ -66,7 +66,8 @@ public NativeSnackBar Show() timer = NSTimer.CreateScheduledTimer(TimeSpan.FromMilliseconds(Duration), async t => { - await TimeoutAction(); + if (TimeoutAction != null) + await TimeoutAction(); Dismiss(); }); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/ActionMessageSnackBarView.macos.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/ActionMessageSnackBarView.macos.cs index 1c821a91d..00f646dc1 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/ActionMessageSnackBarView.macos.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/ActionMessageSnackBarView.macos.cs @@ -1,7 +1,4 @@ -using System; -using AppKit; - -namespace Xamarin.CommunityToolkit.UI.Views.Helpers.macOS.SnackBarViews +namespace Xamarin.CommunityToolkit.UI.Views.Helpers.macOS.SnackBarViews { class ActionMessageSnackBarView : MessageSnackBarView { @@ -15,7 +12,7 @@ protected override void Initialize() base.Initialize(); foreach (var actionButton in SnackBar.Actions) { - StackView.AddArrangedSubview(actionButton); + StackView?.AddArrangedSubview(actionButton); } } } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/BaseSnackBarView.macos.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/BaseSnackBarView.macos.cs index 8e9f4995e..1217526a7 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/BaseSnackBarView.macos.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/BaseSnackBarView.macos.cs @@ -10,7 +10,7 @@ abstract class BaseSnackBarView : NSView protected NativeSnackBar SnackBar { get; } - public NSStackView StackView { get; set; } + public NSStackView? StackView { get; set; } public virtual void Dismiss() => RemoveFromSuperview(); @@ -33,18 +33,25 @@ protected virtual void ConstrainInParent() TrailingAnchor.ConstraintGreaterThanOrEqualToAnchor(ParentView.TrailingAnchor, -SnackBar.Layout.MarginRight).Active = true; CenterXAnchor.ConstraintEqualToAnchor(ParentView.CenterXAnchor).Active = true; - StackView.LeadingAnchor.ConstraintEqualToAnchor(LeadingAnchor, SnackBar.Layout.PaddingLeft).Active = true; - StackView.TrailingAnchor.ConstraintEqualToAnchor(TrailingAnchor, -SnackBar.Layout.PaddingRight).Active = true; - StackView.BottomAnchor.ConstraintEqualToAnchor(BottomAnchor, -SnackBar.Layout.PaddingBottom).Active = true; - StackView.TopAnchor.ConstraintEqualToAnchor(TopAnchor, SnackBar.Layout.PaddingTop).Active = true; + if (StackView != null) + { + StackView.LeadingAnchor.ConstraintEqualToAnchor(LeadingAnchor, SnackBar.Layout.PaddingLeft).Active = true; + StackView.TrailingAnchor.ConstraintEqualToAnchor(TrailingAnchor, -SnackBar.Layout.PaddingRight).Active = true; + StackView.BottomAnchor.ConstraintEqualToAnchor(BottomAnchor, -SnackBar.Layout.PaddingBottom).Active = true; + StackView.TopAnchor.ConstraintEqualToAnchor(TopAnchor, SnackBar.Layout.PaddingTop).Active = true; + } } protected virtual void Initialize() { - StackView = new NSStackView(); - StackView.WantsLayer = true; + StackView = new NSStackView + { + WantsLayer = true + }; + AddSubview(StackView); - if (SnackBar.Appearance.Background != NativeSnackBarAppearance.DefaultColor) + + if (SnackBar.Appearance.Background != NativeSnackBarAppearance.DefaultColor && StackView.Layer != null) { StackView.Layer.BackgroundColor = SnackBar.Appearance.Background.CGColor; } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/MessageSnackBarView.macos.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/MessageSnackBarView.macos.cs index 17c09f5e6..dd470e02c 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/MessageSnackBarView.macos.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/macOS/SnackbarViews/MessageSnackBarView.macos.cs @@ -1,8 +1,4 @@ -using System; -using AppKit; -using CoreGraphics; - -namespace Xamarin.CommunityToolkit.UI.Views.Helpers.macOS.SnackBarViews +namespace Xamarin.CommunityToolkit.UI.Views.Helpers.macOS.SnackBarViews { class MessageSnackBarView : BaseSnackBarView { @@ -39,7 +35,7 @@ protected override void Initialize() messageLabel.Font = SnackBar.Appearance.Font; } - StackView.AddArrangedSubview(messageLabel); + StackView?.AddArrangedSubview(messageLabel); } } } \ No newline at end of file diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.android.cs index 27d9cc21a..d332bad54 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.android.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.android.cs @@ -4,6 +4,7 @@ using Xamarin.Forms.Platform.Android; using Xamarin.CommunityToolkit.UI.Views.Options; using Android.Util; +using System; #if MONOANDROID10_0 using AndroidSnackBar = Google.Android.Material.Snackbar.Snackbar; #else @@ -24,7 +25,7 @@ internal void Show(Page sender, SnackBarOptions arguments) snackBarView.SetBackgroundColor(arguments.BackgroundColor.ToAndroid()); } - var snackTextView = snackBarView.FindViewById(Resource.Id.snackbar_text); + var snackTextView = snackBarView.FindViewById(Resource.Id.snackbar_text) ?? throw new NullReferenceException(); snackTextView.SetMaxLines(10); if (arguments.MessageOptions.Padding != MessageOptions.DefaultPadding) @@ -56,13 +57,17 @@ internal void Show(Page sender, SnackBarOptions arguments) foreach (var action in arguments.Actions) { - snackBar.SetAction(action.Text, async v => await action.Action()); + snackBar.SetAction(action.Text, async v => + { + if (action?.Action != null) + await action.Action(); + }); if (action.ForegroundColor != Forms.Color.Default) { snackBar.SetActionTextColor(action.ForegroundColor.ToAndroid()); } - var snackActionButtonView = snackBarView.FindViewById(Resource.Id.snackbar_action); + var snackActionButtonView = snackBarView.FindViewById(Resource.Id.snackbar_action) ?? throw new NullReferenceException(); if (arguments.BackgroundColor != Forms.Color.Default) { snackActionButtonView.SetBackgroundColor(action.BackgroundColor.ToAndroid()); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.gtk.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.gtk.cs index 47387c01f..62f50c825 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.gtk.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.gtk.cs @@ -1,4 +1,5 @@ -using System.Timers; +using System.Linq; +using System.Timers; using Gtk; using Pango; using Xamarin.CommunityToolkit.UI.Views.Options; @@ -10,24 +11,27 @@ namespace Xamarin.CommunityToolkit.UI.Views { class SnackBar { - Timer snackBarTimer; + Timer? snackBarTimer; public void Show(Page page, SnackBarOptions arguments) { var mainWindow = (Platform.GetRenderer(page).Container.Child as Forms.Platform.GTK.Controls.Page)?.Children[0] as VBox; var snackBarLayout = GetSnackBarLayout(mainWindow, arguments); + AddSnackBarContainer(mainWindow, snackBarLayout); + snackBarTimer = new Timer(arguments.Duration.TotalMilliseconds); snackBarTimer.Elapsed += (sender, e) => { - mainWindow.Remove(snackBarLayout); + mainWindow?.Remove(snackBarLayout); snackBarTimer.Stop(); arguments.SetResult(false); }; + snackBarTimer.Start(); } - HBox GetSnackBarLayout(Container container, SnackBarOptions arguments) + HBox GetSnackBarLayout(Container? container, SnackBarOptions arguments) { var snackBarLayout = new HBox(); snackBarLayout.ModifyBg(StateType.Normal, arguments.BackgroundColor.ToGtkColor()); @@ -51,10 +55,13 @@ HBox GetSnackBarLayout(Container container, SnackBarOptions arguments) button.Clicked += async (sender, e) => { - snackBarTimer.Stop(); - await action.Action(); + snackBarTimer?.Stop(); + + if (action.Action != null) + await action.Action(); + arguments.SetResult(true); - container.Remove(snackBarLayout); + container?.Remove(snackBarLayout); }; snackBarLayout.Add(button); @@ -64,20 +71,20 @@ HBox GetSnackBarLayout(Container container, SnackBarOptions arguments) return snackBarLayout; } - void AddSnackBarContainer(Container mainWindow, Widget snackBarLayout) + void AddSnackBarContainer(Container? mainWindow, Widget snackBarLayout) { - var children = mainWindow.Children; - foreach (var child in mainWindow.Children) + var children = mainWindow?.Children ?? Enumerable.Empty(); + foreach (var child in children) { - mainWindow.Remove(child); + mainWindow?.Remove(child); } foreach (var child in children) { - mainWindow.Add(child); + mainWindow?.Add(child); } - mainWindow.Add(snackBarLayout); + mainWindow?.Add(snackBarLayout); snackBarLayout.ShowAll(); } } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.ios.macos.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.ios.macos.cs index 1bb39fbbe..42db8d690 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.ios.macos.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.ios.macos.cs @@ -100,7 +100,7 @@ internal void Show(Page sender, SnackBarOptions arguments) actionButton.SetTitleColor(action.ForegroundColor.ToUIColor(), UIControlState.Normal); } #elif __MACOS__ - if (action.BackgroundColor != Color.Default) + if (action.BackgroundColor != Color.Default && actionButton.Layer != null) { actionButton.Layer.BackgroundColor = action.BackgroundColor.ToCGColor(); } @@ -114,7 +114,8 @@ internal void Show(Page sender, SnackBarOptions arguments) { snackBar.Dismiss(); - await (action.Action?.Invoke() ?? Task.CompletedTask); + if (action.Action != null) + await action.Action(); arguments.SetResult(true); }); diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.tizen.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.tizen.cs index 8c1161cd6..408e31fb0 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.tizen.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.tizen.cs @@ -27,7 +27,10 @@ internal void Show(Forms.Page sender, SnackBarOptions arguments) ok.Clicked += async (s, evt) => { snackBarDialog.Dismiss(); - await action.Action(); + + if (action?.Action != null) + await action.Action(); + arguments.SetResult(true); }; } diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.uwp.cs index 83515a45e..b1218de27 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.uwp.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.uwp.cs @@ -10,9 +10,9 @@ namespace Xamarin.CommunityToolkit.UI.Views { class SnackBar { - DispatcherTimer snackBarTimer; + DispatcherTimer? snackBarTimer; - T FindVisualChildByName(DependencyObject parent, string name) where T : DependencyObject + T? FindVisualChildByName(DependencyObject parent, string name) where T : DependencyObject { var childrenCount = VisualTreeHelper.GetChildrenCount(parent); @@ -38,7 +38,7 @@ internal void Show(Forms.Page page, SnackBarOptions arguments) { var snackBarLayout = new SnackBarLayout(arguments); var pageControl = Platform.GetRenderer(page).ContainerElement.Parent; - var grid = FindVisualChildByName(pageControl, "BottomCommandBarArea").Parent as Grid; + var grid = (Grid)(FindVisualChildByName(pageControl, "BottomCommandBarArea")?.Parent ?? throw new NullReferenceException()); var snackBarRow = new RowDefinition() { Height = GridLength.Auto }; snackBarTimer = new DispatcherTimer { Interval = arguments.Duration }; snackBarTimer.Tick += (sender, e) => diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.wpf.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.wpf.cs index 464dc6659..9a40be781 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.wpf.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.wpf.cs @@ -9,7 +9,7 @@ namespace Xamarin.CommunityToolkit.UI.Views { class SnackBar { - Timer snackBarTimer; + Timer? snackBarTimer; internal void Show(Page page, SnackBarOptions arguments) { diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/ViewToRendererConverter.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/ViewToRendererConverter.uwp.cs index d55bb8d81..d9d30c0b9 100644 --- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/ViewToRendererConverter.uwp.cs +++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/ViewToRendererConverter.uwp.cs @@ -14,22 +14,14 @@ public class ViewToRendererConverter // This is used in the PopupRenderer.uwp.cs internal class WrapperControl : Panel { - readonly View _view; + readonly View view; FrameworkElement FrameworkElement { get; } - internal void CleanUp() - { - _view?.Cleanup(); - - if (_view != null) - _view.MeasureInvalidated -= OnMeasureInvalidated; - } - public WrapperControl(View view) { - _view = view; - _view.MeasureInvalidated += OnMeasureInvalidated; + this.view = view; + this.view.MeasureInvalidated += OnMeasureInvalidated; var renderer = Platform.CreateRenderer(view); Platform.SetRenderer(view, renderer); @@ -38,17 +30,20 @@ public WrapperControl(View view) Children.Add(renderer.ContainerElement); // make sure we re-measure once the template is applied - if (FrameworkElement != null) + FrameworkElement.Loaded += (sender, args) => { - FrameworkElement.Loaded += (sender, args) => - { - // If the view is a layout (stacklayout, grid, etc) we need to trigger a layout pass - // with all the controls in a consistent native state (i.e., loaded) so they'll actually - // have Bounds set - (_view as Layout)?.ForceLayout(); - InvalidateMeasure(); - }; - } + // If the view is a layout (stacklayout, grid, etc) we need to trigger a layout pass + // with all the controls in a consistent native state (i.e., loaded) so they'll actually + // have Bounds set + (this.view as Layout)?.ForceLayout(); + InvalidateMeasure(); + }; + } + + internal void CleanUp() + { + view.Cleanup(); + view.MeasureInvalidated -= OnMeasureInvalidated; } void OnMeasureInvalidated(object sender, EventArgs e) @@ -58,10 +53,10 @@ void OnMeasureInvalidated(object sender, EventArgs e) protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize) { - _view.IsInNativeLayout = true; - Layout.LayoutChildIntoBoundingRegion(_view, new Rectangle(0, 0, finalSize.Width, finalSize.Height)); + view.IsInNativeLayout = true; + Layout.LayoutChildIntoBoundingRegion(view, new Rectangle(0, 0, finalSize.Width, finalSize.Height)); - if (_view.Width <= 0 || _view.Height <= 0) + if (view.Width <= 0 || view.Height <= 0) { // Hide Panel when size _view is empty. // It is necessary that this element does not overlap other elements when it should be hidden. @@ -70,16 +65,16 @@ protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Si else { Opacity = 1; - FrameworkElement?.Arrange(new WRect(_view.X, _view.Y, _view.Width, _view.Height)); + FrameworkElement?.Arrange(new WRect(view.X, view.Y, view.Width, view.Height)); } - _view.IsInNativeLayout = false; + view.IsInNativeLayout = false; return finalSize; } protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Size availableSize) { - var request = _view.Measure(availableSize.Width, availableSize.Height, MeasureFlags.IncludeMargins).Request; + var request = view.Measure(availableSize.Width, availableSize.Height, MeasureFlags.IncludeMargins).Request; if (request.Height < 0) { @@ -87,7 +82,7 @@ protected override Windows.Foundation.Size MeasureOverride(Windows.Foundation.Si } Windows.Foundation.Size result; - if (_view.HorizontalOptions.Alignment == LayoutAlignment.Fill && !double.IsInfinity(availableSize.Width) && availableSize.Width != 0) + if (view.HorizontalOptions.Alignment == LayoutAlignment.Fill && !double.IsInfinity(availableSize.Width) && availableSize.Width != 0) { result = new Windows.Foundation.Size(availableSize.Width, request.Height); } diff --git a/src/Markup/Xamarin.CommunityToolkit.Markup/FuncConverter.cs b/src/Markup/Xamarin.CommunityToolkit.Markup/FuncConverter.cs index d435ea093..b5bef35c6 100644 --- a/src/Markup/Xamarin.CommunityToolkit.Markup/FuncConverter.cs +++ b/src/Markup/Xamarin.CommunityToolkit.Markup/FuncConverter.cs @@ -6,25 +6,25 @@ namespace Xamarin.CommunityToolkit.Markup { public class FuncConverter : IValueConverter { - readonly Func? convert; - readonly Func? convertBack; + readonly Func? convert; + readonly Func? convertBack; - readonly Func? convertWithParam; - readonly Func? convertBackWithParam; + readonly Func? convertWithParam; + readonly Func? convertBackWithParam; - readonly Func? convertWithParamAndCulture; - readonly Func? convertBackWithParamAndCulture; + readonly Func? convertWithParamAndCulture; + readonly Func? convertBackWithParamAndCulture; - public FuncConverter(Func? convertWithParamAndCulture = null, Func? convertBackWithParamAndCulture = null) + public FuncConverter(Func? convertWithParamAndCulture = null, Func? convertBackWithParamAndCulture = null) { this.convertWithParamAndCulture = convertWithParamAndCulture; this.convertBackWithParamAndCulture = convertBackWithParamAndCulture; } public FuncConverter(Func? convertWithParam = null, Func? convertBackWithParam = null) { this.convertWithParam = convertWithParam; this.convertBackWithParam = convertBackWithParam; } - public FuncConverter(Func? convert = null, Func? convertBack = null) + public FuncConverter(Func? convert = null, Func? convertBack = null) { this.convert = convert; this.convertBack = convertBack; } - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture) { if (convert != null) { @@ -50,7 +50,7 @@ public FuncConverter(Func? convert = null, Func