From cd3f5b635290bdbab336463cf04c90a6509591ee Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+brminnick@users.noreply.github.com> Date: Tue, 9 Mar 2021 08:24:05 -0800 Subject: [PATCH] Enable Nullable (#1009) * Enable Nullable on Unit Tests (#1008) * Enable Nullability on Xamarin.CommunityToolkit.Markup (#1013) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullability on Xamarin.CommunityToolkit.Sample (#1014) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullability for Android, GTK, iOS, Tizen, UWP & WPF Sample Projects (#1015) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullable on Android, GTK, iOS and Tizen Samples * Enable Nullable for UWP & WPF Sample Projects * Enable Nullability on Xamarin.CommunityToolkit (#1016) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullable on Android, GTK, iOS and Tizen Samples * Enable Nullable for UWP & WPF Sample Projects * Add Nullability * Enable Nullable on XamarinCommunityToolkit (#1023) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullable on Android, GTK, iOS and Tizen Samples * Enable Nullable for UWP & WPF Sample Projects * Add Nullability * Resolve Possible Null References * Removed Possible Null References * Update AppResources.Designer.cs * Handle Nullability * Updated Nullabiltiy * Update Converters & Unit Tests * Resolve MediaSource Unit Tests * Fix Unit Tests (#1036) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullable on Android, GTK, iOS and Tizen Samples * Enable Nullable for UWP & WPF Sample Projects * Add Nullability * Resolve Possible Null References * Removed Possible Null References * Update AppResources.Designer.cs * Handle Nullability * Updated Nullabiltiy * Update Converters & Unit Tests * Resolve MediaSource Unit Tests * Fix VariableMultiValueConverter * Fixed ImpliedOrderGridBehavior * Update NumericValidationBehavior.shared.cs * Resolve Nullable in SideMenuView * Move enable to Directory.Build.props * Update Xamarin.CommunityToolkit.Sample.csproj * Revert Designer.cs * Update Xamarin.CommunityToolkit.Sample.csproj * Update ItemSelectedEventArgsConverter_Tests.cs * Update SearchViewModel.cs * Update ItemTappedEventArgsConverter_Tests.cs * Update Xamarin.CommunityToolkit.UnitTests.csproj * Add Nullability * Resolve Compiler Warnings * Ignore Closing square brackets should be spaced correctly With Nullable enabled, `byte[]?` is now valid, however SA1011 was still generating a warning * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/ImpliedOrderGridBehavior.shared.cs Co-authored-by: Pedro Jesus * Update CameraFragment.android.cs * Update CameraFragment.android.cs * Update ImpliedOrderGridBehavior.shared.cs * Update MaskedBehavior.shared.cs * Update PopupRenderer.uwp.cs * Use .NET 5.0 * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Add UWP to Release Build * Update Nullability * Update Nullablity * Update TabView.shared.cs * Update Nullability * Revert "Update Nullability" This reverts commit e391b9c654e7b6b2c55d38dd9dcfffa8b5232403. * Resolved Nullable * Update azure-pipelines.yml * Revert UWP Build Properties * Update azure-pipelines.yml * Update azure-pipelines.yml * Revert "Update azure-pipelines.yml" This reverts commit 0842280e362f64df26a8cff2e028fc77d17b48cb. * Update azure-pipelines.yml * Revert "Revert UWP Build Properties" This reverts commit 77226bfd189530f67fd2f18cac1a22eedb20113b. * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Revert "Update azure-pipelines.yml" This reverts commit 4eb36f41269882f6bc25a0e96bc9647f756f4a68. * Update azure-pipelines.yml * Revert "Update azure-pipelines.yml" This reverts commit e41a477dc4c1dc79e6810f6d8a8bc1381176fe95. * Fix ValidationBehavior.ForceValidate and ValidationBehavior.DefaultForceValidateCommand * Update SelectAllTextEffect.ios.cs * Remove Nullabilty from LocalizedString.generator * Update MediaElementRenderer.ios.cs * Update PopupRenderer.uwp.cs * Update PopupRenderer.ios.cs * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/iOS/SnackbarViews/BaseSnackBarView.ios.cs Co-authored-by: Maksym Koshovyi * Update TranslateExtension.shared.cs * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.android.cs Co-authored-by: Maksym Koshovyi * Update Logic * Fix Failing ICommand Tests * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.tizen.cs Co-authored-by: Maksym Koshovyi * Throw Faulted Task * Use Cast instead of Pattern Matching * Update RangeSlider.shared.cs * Fix missing semi-colons * Throw InvalidOperationException in LocalizationResourceManager * Make TranslateExtension.StringFormat nullable * Update UserStoppedTypingBehavior.shared.cs * Update SearchPage.logic.cs * Update TouchEffectCollectionViewPage.xaml.cs * Update AppResources.Designer.cs * Update AppResources.Designer.cs * Update EnumToBoolConverterViewModel.cs * Update EnumToBoolConverter_Tests.cs * Update IntToBoolConverter_Tests.cs * Update InvertedBoolConverter_Tests.cs * Update IsNotNullOrEmptyConverter_Tests.cs * Update MultiConverter_Tests.cs * Update NotEqualConverter_Tests.cs * Update TextCaseConverter_Tests.cs * Update MockPlatformServices.cs * Update MockPlatformServices.cs * Update Namespace_Tests.cs * Update ObservableRangeCollection_Tests.cs * Update ObservableRangeCollection_Tests.cs * Use `async Task` instead of `async void` * Update MultiValidationBehavior.shared.cs * Update EnumToBoolConverter.shared.cs * Update EnumToBoolConverter.shared.cs * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/NotEqualConverter.shared.cs Co-authored-by: Pedro Jesus * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/StateToBooleanConverter.shared.cs Co-authored-by: Pedro Jesus * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TextCaseConverter.shared.cs Co-authored-by: Pedro Jesus * Update IconTintColorEffectRouter.android.cs * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/SelectAllText/SelectAllTextEffect.android.cs Co-authored-by: Pedro Jesus * Update SelectAllTextEffect.android.cs * Update SelectAllTextEffect.ios.cs * Update PlatformTouchEffect.ios.cs * Update PlatformTouchEffect.uwp.cs * Update PlatformTouchEffect.uwp.cs * Update PlatformTouchEffect.macos.cs * Update PlatformTouchEffect.uwp.cs * Update PlatformTouchEffect.uwp.cs * Ensure nullable results from BindableProperties are still resolved * Update ImageResourceExtension.shared.cs * Update BaseCommand.android.cs * Use protected private constructor for BaseCommand * Update BadgeView.shared.cs * Update CameraFragment.android.cs * Fix Android Media Bugs * Update async/await * Update CameraView_Tests.cs * Update CameraView * Update UriTypeConverter.shared.cs * Update PopupRenderer.uwp.cs * Update PopoverArrowDirection.shared.cs * Update PopoverArrowDirection.shared.cs * Update TabView.shared.cs * Improve AsyncCommand Tests * Ensure Context is non nullable * Remove Missing Translations * Fix async/await in TouchEffect.shared.cs * Make Easing Nullable * Update Samples * Fix Null Exception * Resolve NullReferenceExceptions * Make IBadgeAnimation Nullable * Add ShutterCommandValueCreator null check * Add Timeout to prevent race conditions from stalling tests * Unsubscribe Event Handlers for AsyncCommand Tests * Update azure-pipelines.yml * For WPF, Use Cross-Platform Implementation for `BaseCommand.IsMainThread` and `BaseCommand.BeginInvokeOnMainThread` (#965) * Add Non-WPF Support to .NET Core 3.1 * Update comments * Merge .NET Standard and WPF Functionality * Fix Null Reference * Update ICommand_AsyncValueCommand_Tests.cs * Add volatile keyword * Update AsyncValueCommand_Tests.cs * Remove Timeouts * Fix Event Unsubscription * Add .ConfigureAwait(false); * Run dotnet test serially * Use SemaphoreSlim to prevent Race Conditions Co-authored-by: Pedro Jesus Co-authored-by: Maksym Koshovyi --- .editorconfig | 6 + Directory.Build.props | 4 +- Xamarin.CommunityToolkit.ruleset | 1 - azure-pipelines.yml | 54 +- samples/XCT.Sample.Android/SplashActivity.cs | 2 +- samples/XCT.Sample.UWP/App.xaml.cs | 4 +- .../Renderers/NoLineNavigationRenderer.cs | 7 +- samples/XCT.Sample.sln | 9 +- samples/XCT.Sample/App.xaml.cs | 4 +- samples/XCT.Sample/Helpers/RelayCommand.cs | 84 ++- samples/XCT.Sample/Helpers/XLog.cs | 26 +- samples/XCT.Sample/Pages/AboutPage.xaml.cs | 3 +- .../Pages/Base/BaseNavigationPage.cs | 1 + samples/XCT.Sample/Pages/Base/BasePage.cs | 19 +- .../Behaviors/AnimationBehaviorPage.xaml | 2 +- .../Behaviors/AnimationBehaviorPage.xaml.cs | 3 +- .../ImpliedOrderGridBehaviorLabel.cs | 2 +- .../ImpliedOrderGridBehaviorPage.xaml.cs | 8 +- .../MaxLengthReachedBehaviorPage.xaml.cs | 2 +- .../BoolToObjectConverterPage.xaml.cs | 14 +- .../DoubleToIntConverterPage.xaml.cs | 14 +- .../EnumToBoolConverterPage.xaml.cs | 13 +- .../Converters/EqualConverterPage.xaml.cs | 14 +- .../IndexToArrayItemConverterPage.xaml.cs | 14 +- .../Converters/IntToBoolConverterPage.xaml.cs | 14 +- .../InvertedBoolConverterPage.xaml.cs | 7 +- .../IsNotNullOrEmptyConverterPage.xaml.cs | 14 +- .../ListToStringConverterPage.xaml.cs | 14 +- .../Converters/NotEqualConverterPage.xaml.cs | 14 +- .../Converters/TextCaseConverterPage.xaml.cs | 7 +- .../Effects/IconTintColorEffectPage.xaml.cs | 3 +- .../Pages/Effects/LifeCycleEffectPage.xaml.cs | 6 +- .../Pages/Effects/SafeAreaEffectPage.xaml.cs | 2 +- .../Pages/Effects/ShadowEffectPage.xaml.cs | 8 +- .../Pages/Markup/SearchPage.logic.cs | 11 +- samples/XCT.Sample/Pages/SettingPage.xaml | 2 +- samples/XCT.Sample/Pages/SettingPage.xaml.cs | 3 +- .../TestCases/MediaElementSourcePage.xaml.cs | 16 +- .../TouchEffectCollectionViewPage.xaml.cs | 17 +- .../Pages/Views/AvatarViewPage.xaml | 2 +- .../XCT.Sample/Pages/Views/BadgeViewPage.xaml | 2 +- .../Pages/Views/CameraViewPage.xaml.cs | 14 +- .../Pages/Views/MediaElementPage.xaml.cs | 10 +- .../Pages/Views/Popups/ButtonPopup.xaml.cs | 2 +- .../Views/Popups/MultipleButtonPopup.xaml.cs | 4 +- .../Views/Popups/NoLightDismissPopup.xaml.cs | 2 +- .../Popups/OpenedEventSimplePopup.xaml.cs | 2 +- .../Views/Popups/PopupAnchorPage.xaml.cs | 2 +- .../Views/Popups/ReturnResultPopup.xaml.cs | 2 +- .../Views/Popups/ToggleSizePopup.xaml.cs | 2 +- .../Pages/Views/RangeSliderPage.xaml.cs | 6 +- .../XCT.Sample/Pages/Views/ShieldPage.xaml.cs | 2 +- .../Pages/Views/SideMenuViewPage.xaml.cs | 4 +- .../Pages/Views/SnackBarPage.xaml.cs | 9 +- .../Views/TabView/CustomTabsPage.xaml.cs | 2 +- .../Pages/Views/TabView/TabBadgePage.xaml.cs | 4 +- .../Views/TabView/TabPlacementPage.xaml.cs | 2 +- samples/XCT.Sample/Pages/WelcomePage.xaml.cs | 4 +- samples/XCT.Sample/Resx/AppResources.en.resx | 135 ++++ .../XCT.Sample/ViewModels/AboutViewModel.cs | 6 +- .../ViewModels/Base/BaseGalleryViewModel.cs | 4 +- .../MaxLengthReachedBehaviorViewModel.cs | 2 +- .../ProgressBarAnimationBehaviorViewModel.cs | 34 +- .../UserStoppedTypingBehaviorViewModel.cs | 6 +- .../ByteArrayToImageSourceViewModel.cs | 4 +- .../EnumToBoolConverterViewModel.cs | 2 +- .../IndexToArrayItemConverterViewModel.cs | 4 +- .../IsNullOrEmptyConverterViewModel.cs | 14 +- .../ItemSelectedEventArgsViewModel.cs | 2 +- .../ItemTappedEventArgsViewModel.cs | 17 +- .../VariableMultiValueConverterViewModel.cs | 3 +- .../Effects/EffectsGalleryViewModel.cs | 11 +- .../ViewModels/Markup/SearchViewModel.cs | 13 +- .../XCT.Sample/ViewModels/SettingViewModel.cs | 37 +- .../ViewModels/Views/ExpanderViewModel.cs | 2 +- .../ViewModels/Views/PopupControlViewModel.cs | 23 +- .../ViewModels/Views/StateLayoutViewModel.cs | 2 +- .../Views/TabItemsSourceViewModel.cs | 205 +++--- .../Views/Tabs/LazyTestViewModel.cs | 2 +- .../Views/Tabs/NormalTestViewModel.cs | 2 +- .../Xamarin.CommunityToolkit.Sample.csproj | 5 + .../CharactersValidationBehavior_Tests.cs | 13 +- .../MaxLengthReachedBehavior_Tests.cs | 4 +- .../MultiValidationBehavior_Tests.cs | 16 +- .../NumericValidationBehavior_Tests.cs | 35 +- .../RequiredStringValidationBehavior_Tests.cs | 35 +- .../Behaviors/UriValidationBehavior_Tests.cs | 11 +- .../UserStoppedTypingBehavior_Tests.cs | 4 +- .../ByteArrayToImageSourceConverter_Tests.cs | 22 +- .../Converters/DoubleToIntConverter_Tests.cs | 4 +- .../Converters/EnumToBoolConverter_Tests.cs | 50 +- .../Converters/IntToBoolConverter_Tests.cs | 2 +- .../Converters/InvertedBoolConverter_Tests.cs | 2 +- .../IsNotNullOrEmptyConverter_Tests.cs | 2 +- .../ItemSelectedEventArgsConverter_Tests.cs | 6 +- .../ItemTappedEventArgsConverter_Tests.cs | 6 +- .../ListIsNotNullOrEmptyConverter_Tests.cs | 15 +- .../ListIsNullOrEmptyConverter_Tests.cs | 17 +- .../Converters/ListToStringConverter_Tests.cs | 21 +- .../MultiConverterParameter_Tests.cs | 3 +- .../Converters/MultiConverter_Tests.cs | 11 +- .../Converters/NotEqualConverter_Tests.cs | 2 +- .../Converters/TextCaseConverter_Tests.cs | 2 +- .../EnableInitOnlyProperties.cs | 4 + .../LocalizationResourceManagerTests.cs | 2 +- .../LocalizedStringTests.cs | 4 +- ...DelegateWeakEventManager_Delegate_Tests.cs | 36 +- ...gateWeakEventManager_EventHandler_Tests.cs | 6 + .../WeakEventManager_ActionT_Tests.cs | 32 +- .../WeakEventManager_EventHandlerT_Tests.cs | 42 +- .../Mocks/MockPlatformServices.cs | 37 +- .../Mocks/MockResourceManager.cs | 2 +- .../Namespace_Tests.cs | 37 +- .../AsyncCommandTests/AsyncCommand_Tests.cs | 167 ++++- .../AsyncCommandTests/IAsyncCommand_Tests.cs | 37 +- .../ICommand_AsyncCommand_Tests.cs | 79 ++- .../AsyncValueCommand_Tests.cs | 121 +++- .../BaseAsyncValueCommandTests.cs | 2 +- .../IAsyncValueCommand_Tests.cs | 8 +- .../ICommand_AsyncValueCommand_Tests.cs | 85 ++- .../ICommandTests/BaseCommandTests.cs | 14 +- .../CommandFactory_AsyncCommand_Tests.cs | 30 +- .../CommandFactory_AsyncValueCommand_Tests.cs | 28 +- .../CommandFactory_Command_Tests.cs | 19 +- .../ObjectModel/ObservableObject_Tests.cs | 19 +- .../ObservableRangeCollection_Tests.cs | 19 +- .../ObjectModel/Person.cs | 10 +- .../Views/CameraView_Tests.cs | 4 +- .../Views/MediaElement_Tests.cs | 2 +- .../Views/MediaSource_Tests.cs | 34 +- .../Xamarin.CommunityToolkit.UnitTests.csproj | 1 - .../Animations/AnimationBehavior.shared.cs | 11 +- .../AnimationTypes/AnimationBase.shared.cs | 2 +- .../AnimationTypes/FadeAnimation.shared.cs | 9 +- .../FlipHorizontalAnimation.shared.cs | 9 +- .../FlipVerticalAnimation.shared.cs | 9 +- .../AnimationTypes/RotateAnimation.shared.cs | 9 +- .../AnimationTypes/ScaleAnimation.shared.cs | 9 +- .../AnimationTypes/ShakeAnimation.shared.cs | 15 +- .../Behaviors/BaseBehavior.shared.cs | 12 +- .../EventToCommandBehavior.shared.cs | 21 +- .../ImpliedOrderGridBehavior.shared.cs | 14 +- .../Behaviors/MaskedBehavior.shared.cs | 36 +- .../MaxLengthReachedBehavior.shared.cs | 8 +- .../ProgressBarAnimationBehavior.shared.cs | 13 +- .../UserStoppedTypingBehavior.shared.cs | 21 +- .../CharactersValidationBehavior.shared.cs | 6 +- .../EmailValidationBehavior.shared.cs | 2 +- .../MultiValidationBehavior.shared.cs | 21 +- .../NumericValidationBehavior.shared.cs | 17 +- ...RequiredStringValidationBehavior.shared.cs | 6 +- .../TextValidationBehavior.shared.cs | 10 +- .../UriValidationBehavior.shared.cs | 2 +- .../Validators/ValidationBehavior.shared.cs | 41 +- .../BoolToObjectConverter.shared.cs | 8 +- .../ByteArrayToImageSourceConverter.shared.cs | 4 +- .../DateTimeOffsetConverter.shared.cs | 4 +- .../Converters/DoubleToIntConverter.shared.cs | 6 +- .../Converters/EnumToBoolConverter.shared.cs | 12 +- .../Converters/EqualConverter.shared.cs | 10 +- .../IndexToArrayItemConverter.shared.cs | 10 +- .../Converters/IntToBoolConverter.shared.cs | 4 +- .../InvertedBoolConverter.shared.cs | 6 +- .../IsNotNullOrEmptyConverter.shared.cs | 6 +- .../IsNullOrEmptyConverter.shared.cs | 8 +- .../ItemSelectedEventArgsConverter.shared.cs | 4 +- .../ItemTappedEventArgsConverter.shared.cs | 4 +- .../ListIsNotNullOrEmptyConverter.shared.cs | 15 +- .../ListIsNullOrEmptyConverter.shared.cs | 6 +- .../ListToStringConverter.shared.cs | 10 +- .../Converters/MultiConverter.shared.cs | 4 +- .../MultiConverterParameter.shared.cs | 4 +- .../Converters/NotEqualConverter.shared.cs | 8 +- .../StateToBooleanConverter.shared.cs | 8 +- .../Converters/TextCaseConverter.shared.cs | 46 +- .../TimeSpanToDoubleConverter.shared.cs | 4 +- .../VariableMultiValueConverter.shared.cs | 6 +- .../Core/FileMediaSource.shared.cs | 6 +- .../Core/MediaSource.shared.cs | 17 +- .../Core/MediaSourceConverter.shared.cs | 3 +- .../Core/StreamMediaSource.shared.cs | 18 +- .../Core/UriMediaSource.shared.cs | 4 +- .../Effects/EffectIds.shared.cs | 5 +- .../IconTintColorEffectRouter.android.cs | 2 +- .../LifeCycleEffectRouter.android.cs | 20 +- .../LifeCycle/LifeCycleEffectRouter.ios.cs | 8 +- .../LifeCycle/LifeCycleEffectRouter.uwp.cs | 22 +- .../RemoveBorderEffect.android.cs | 13 +- .../RemoveBorder/RemoveBorderEffect.ios.cs | 2 +- .../SafeArea/SafeAreaEffectRouter.ios.cs | 8 +- .../SelectAllTextEffect.android.cs | 4 +- .../SelectAllText/SelectAllTextEffect.ios.cs | 33 +- .../SelectAllTextEffect.shared.cs | 2 +- .../Shadow/PlatformShadowEffect.ios.macos.cs | 54 +- .../TouchCompletedEventArgs.shared.cs | 4 +- .../Effects/Touch/GestureManager.shared.cs | 141 ++-- .../Touch/PlatformTouchEffect.android.cs | 145 +++-- .../Effects/Touch/PlatformTouchEffect.ios.cs | 72 +- .../Touch/PlatformTouchEffect.macos.cs | 68 +- .../Touch/PlatformTouchEffect.tizen.cs | 47 +- .../Effects/Touch/PlatformTouchEffect.uwp.cs | 99 +-- .../Effects/Touch/TouchEffect.shared.cs | 616 ++++++++++-------- .../Effects/VisualFeedback/TouchEvents.ios.cs | 8 +- .../VisualFeedbackEffectRouter.android.cs | 76 ++- .../VisualFeedbackEffectRouter.ios.cs | 59 +- .../ImageResourceExtension.shared.cs | 10 +- .../NavigableElementExtensions.shared.cs | 2 +- .../NavigationExtensions.android.cs | 2 +- .../Navigation/NavigationExtensions.ios.cs | 2 +- .../Navigation/NavigationExtensions.shared.cs | 2 +- .../Navigation/NavigationExtensions.uwp.cs | 4 +- .../Extensions/TranslateExtension.shared.cs | 10 +- .../VisualElementExtension.shared.cs | 18 +- .../DelegateWeakEventManager.shared.cs | 16 +- .../LocalizationResourceManager.shared.cs | 19 +- .../Helpers/LocalizedString.shared.cs | 6 +- .../Helpers/SafeArea.shared.cs | 8 +- .../Helpers/Subscription.shared.cs | 4 +- .../Helpers/WeakEventManager.shared.cs | 26 +- .../Helpers/WeakEventManagerService.shared.cs | 27 +- .../ObjectModel/AsyncCommand.shared.cs | 22 +- .../ObjectModel/AsyncValueCommand.shared.cs | 22 +- .../CommandFactory.Command.shared.cs | 2 +- .../CommandFactory.IAsyncCommand.shared.cs | 38 +- ...ommandFactory.IAsyncValueCommand.shared.cs | 24 +- .../INotifyPropertyChangedExtension.shared.cs | 6 +- .../Internals/BaseAsyncCommand.shared.cs | 24 +- .../Internals/BaseAsyncValueCommand.shared.cs | 24 +- .../Internals/BaseCommand.android.cs | 10 +- .../Internals/BaseCommand.netstandard.wpf.cs | 2 +- .../Internals/BaseCommand.shared.cs | 20 +- .../ObjectModel/ObservableObject.shared.cs | 4 +- .../Startup/ToolkitPlatform.android.cs | 7 +- .../Views/AvatarView/AvatarView.shared.cs | 43 +- .../Views/AvatarView/ColorTheme.shared.cs | 1 - .../IImageSourceValidator.shared.cs | 2 +- ...tor.android.ios.macos.uwp.wpf.gtk.tizen.cs | 4 +- .../AvatarView/ImageSourceValidator.shared.cs | 2 +- .../Views/BadgeView/BadgeView.shared.cs | 88 +-- .../Views/BaseTemplatedView.shared.cs | 15 +- .../Android/AutoFitTextureView.android.cs | 6 +- .../Android/CameraCaptureListener.android.cs | 2 +- .../CameraCaptureStateListener.android.cs | 4 +- .../Android/CameraFragment.android.cs | 322 +++++---- .../Android/CameraStateListener.android.cs | 13 +- .../Android/CameraViewRenderer.android.cs | 67 +- .../Android/ImageAvailableListener.android.cs | 16 +- .../Android/MotionEventHelper.android.cs | 9 +- .../Views/CameraView/CameraView.shared.cs | 18 +- .../MediaCapturedEventArgs.shared.cs | 30 +- .../CameraView/UWP/CameraViewRenderer.uwp.cs | 92 +-- .../CameraView/iOS/CameraViewRenderer.ios.cs | 23 +- .../CameraView/iOS/FormsCameraView.ios.cs | 79 ++- .../Views/Expander/Expander.shared.cs | 43 +- .../GravatarImageSourceHandler.android.cs | 9 +- .../GravatarImageSource.shared.cs | 4 +- .../MacOS/GravatarImageSourceHandler.macos.cs | 4 +- ...Handler.android.ios.macos.tizen.uwp.wpf.cs | 8 +- .../GravatarImageSourceHandler.ios.macos.cs | 9 +- .../UWP/GravatarImageSourceHandler.uwp.cs | 4 +- .../Wpf/GravatarImageSourceHandler.wpf.cs | 4 +- .../iOS/GravatarImageSourceHandler.ios.cs | 4 +- .../Android/FormsVideoView.android.cs | 39 +- .../Android/MediaElementRenderer.android.cs | 115 ++-- .../Views/MediaElement/MediaElement.shared.cs | 24 +- .../UWP/MediaElementRenderer.uwp.cs | 18 +- .../MediaElement/UriTypeConverter.shared.cs | 4 +- .../iOS/MediaElementRenderer.ios.cs | 53 +- .../Popup/Android/PopupRenderer.android.cs | 169 +++-- .../Views/Popup/BasePopup.shared.cs | 8 +- .../Popup/PopupDismissedEventArgs.shared.cs | 4 +- .../Views/Popup/PopupOfT.shared.cs | 12 +- .../Views/Popup/UWP/Popup.shared.cs | 11 +- .../Views/Popup/UWP/PopupRenderer.uwp.cs | 74 ++- .../Popup/iOS/PopoverArrowDirection.shared.cs | 4 +- .../Views/Popup/iOS/Popup.shared.cs | 20 +- .../Views/Popup/iOS/PopupRenderer.ios.cs | 66 +- .../Views/RangeSlider/RangeSlider.shared.cs | 37 +- .../Views/RangeSlider/ThumbFrame.shared.cs | 5 +- .../Views/Shield.shared.cs | 20 +- .../Views/SideMenuView/SideMenuView.shared.cs | 38 +- .../SideMenuViewRenderer.android.cs | 2 +- .../SideMenuView/SideMenuViewRenderer.ios.cs | 8 +- .../Helpers/NativeSnackButton.ios.macos.cs | 10 +- .../Helpers/SnackBarLayout.uwp.wpf.cs | 5 +- .../Snackbar/Helpers/iOS/IOSSnackBar.ios.cs | 17 +- .../ActionMessageSnackBarView.ios.cs | 5 +- .../iOS/SnackbarViews/BaseSnackBarView.ios.cs | 17 +- .../SnackbarViews/MessageSnackBarView.ios.cs | 4 +- .../Helpers/macOS/MacOSSnackBar.macos.cs | 11 +- .../ActionMessageSnackBarView.macos.cs | 7 +- .../SnackbarViews/BaseSnackBarView.macos.cs | 23 +- .../MessageSnackBarView.macos.cs | 8 +- .../Snackbar/Options/MessageOptions.shared.cs | 2 +- .../Options/SnackBarActionOptions.shared.cs | 6 +- .../Views/Snackbar/SnackBar.android.cs | 13 +- .../Views/Snackbar/SnackBar.gtk.cs | 33 +- .../Views/Snackbar/SnackBar.ios.macos.cs | 7 +- ...s => SnackBar.netstandard.tvos.watchos.cs} | 6 +- .../Views/Snackbar/SnackBar.tizen.cs | 11 +- .../Views/Snackbar/SnackBar.uwp.cs | 6 +- .../Views/Snackbar/SnackBar.wpf.cs | 2 +- .../Views/StateLayout/StateLayout.shared.cs | 22 +- .../StateLayoutController.shared.cs | 20 +- .../Views/StateLayout/StateView.shared.cs | 8 +- .../Views/TabView/TabBadgeView.shared.cs | 86 ++- .../Views/TabView/TabView.shared.cs | 105 +-- .../Views/TabView/TabViewItem.shared.cs | 34 +- .../Views/ViewToRendererConverter.uwp.cs | 53 +- .../BindableObjectExtensions.cs | 82 +-- .../BindableObjectMultiBindExtensions.cs | 74 +-- .../ElementExtensions.cs | 4 +- .../ElementGesturesExtensions.cs | 18 +- .../FuncConverter.cs | 28 +- .../FuncMultiConverter.cs | 94 +-- .../RelativeLayout.cs | 8 +- .../Xamarin.CommunityToolkit.Markup/Style.cs | 2 +- 317 files changed, 4011 insertions(+), 3117 deletions(-) create mode 100644 samples/XCT.Sample/Resx/AppResources.en.resx mode change 100755 => 100644 src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Converters/EnumToBoolConverter_Tests.cs create mode 100644 src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/EnableInitOnlyProperties.cs mode change 100755 => 100644 src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/EnumToBoolConverter.shared.cs rename src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/{SnackBar.shared.cs => SnackBar.netstandard.tvos.watchos.cs} (78%) diff --git a/.editorconfig b/.editorconfig index c71598a71..a596b627e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -107,3 +107,9 @@ csharp_new_line_before_catch = true csharp_new_line_before_finally = true csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true + +# SA1011: Closing square brackets should be spaced correctly +dotnet_diagnostic.SA1011.severity = none + +# CS4014: Because this call is not awaited, execution of the current method continues before the call is completed +dotnet_diagnostic.CS4014.severity = error diff --git a/Directory.Build.props b/Directory.Build.props index 891e273b7..e7f7d987f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,9 @@ - 8.0 + 9.0 + enable + nullable diff --git a/Xamarin.CommunityToolkit.ruleset b/Xamarin.CommunityToolkit.ruleset index 0d4b31f43..047684820 100644 --- a/Xamarin.CommunityToolkit.ruleset +++ b/Xamarin.CommunityToolkit.ruleset @@ -15,7 +15,6 @@ - diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 10bb75744..a0ee31d07 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -7,10 +7,12 @@ variables: #MONO_VERSION: 6_4_0 #XCODE_VERSION: 11.4 NETCORE_VERSION: '5.0.x' - NETCORE_TEST_VERSION: '5.0.x' + NETCORE_TEST_VERSION_3_1: '3.1.x' + NETCORE_TEST_VERSION_2_1: '2.1.x' RunPoliCheck: 'false' PathToCsproj: 'src/CommunityToolkit/Xamarin.CommunityToolkit/Xamarin.CommunityToolkit.csproj' PathToMarkupCsproj: 'src/Markup/Xamarin.CommunityToolkit.Markup/Xamarin.CommunityToolkit.Markup.csproj' + PathToUnitTestCsproj: 'src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Xamarin.CommunityToolkit.UnitTests.csproj' PathToSln: 'samples/XCT.Sample.sln' resources: @@ -68,6 +70,21 @@ jobs: pool: vmImage: windows-2019 steps: + - task: UseDotNet@2 + displayName: 'Install .NET SDK' + inputs: + version: $(NETCORE_VERSION) + includePreviewVersions: false + - task: UseDotNet@2 + displayName: 'Install .NET 3.1 Test SDK' + inputs: + version: $(NETCORE_TEST_VERSION_3_1) + includePreviewVersions: false + - task: UseDotNet@2 + displayName: 'Install .NET 2.1 Test SDK' + inputs: + version: $(NETCORE_TEST_VERSION_2_1) + includePreviewVersions: false # if this is a tagged build, then update the version number - powershell: | $buildSourceBranch = "$(Build.SourceBranch)" @@ -112,12 +129,10 @@ jobs: # command: 'custom' # custom: 'nuget' # arguments: 'push --source https://nuget.pkg.github.com/xamarin/index.json --api-key $(GitHub.NuGet.Token) "$(Build.ArtifactStagingDirectory)\nuget\*.nupkg"' - - task: DotNetCoreCLI@2 - displayName: Run Tests + - task: CmdLine@2 + displayName: 'Run Unit Tests' inputs: - command: test - projects: '**/*.UnitTests.csproj' - arguments: '--configuration Release --collect "Code coverage"' + script: dotnet test $(PathToUnitTestCsproj) -c Release --collect "Code coverage" -p:BuildInParallel=false # publish the packages - task: PublishBuildArtifacts@1 displayName: 'Publish Unsigned NuGets' @@ -161,27 +176,28 @@ jobs: # displayName: Switch to the latest Xcode # restore, build and pack the packages - task: UseDotNet@2 - displayName: 'Use .Net Core sdk' + displayName: 'Install .NET SDK' inputs: version: $(NETCORE_VERSION) includePreviewVersions: false - task: UseDotNet@2 - displayName: 'Use .Net Core sdk' + displayName: 'Install .NET 3.1 Test SDK' inputs: - version: $(NETCORE_TEST_VERSION) + version: $(NETCORE_TEST_VERSION_3_1) includePreviewVersions: false - - task: MSBuild@1 - displayName: Build Solution + - task: UseDotNet@2 + displayName: 'Install .NET 2.1 Test SDK' inputs: - solution: $(PathToCsproj) - configuration: Release - msbuildArguments: '/restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false' - - task: MSBuild@1 - displayName: Pack NuGets + version: $(NETCORE_TEST_VERSION_2_1) + includePreviewVersions: false + - task: CmdLine@2 + displayName: 'Build Solution' inputs: - solution: $(PathToCsproj) - configuration: Release - msbuildArguments: '/t:Pack /p:PackageVersion=$(NugetPackageVersion) /p:PackageOutputPath="$(Build.ArtifactStagingDirectory)/nuget"' + script: 'mono /Applications/Visual\ studio.app/Contents/Resources/lib/monodevelop/bin/MSBuild/Current/bin/MSBuild.dll $(PathToCsproj) /p:Configuration=Release /restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false' + - task: CmdLine@2 + displayName: 'Pack NuGets' + inputs: + script: 'mono /Applications/Visual\ studio.app/Contents/Resources/lib/monodevelop/bin/MSBuild/Current/bin/MSBuild.dll $(PathToCsproj) /p:Configuration=Release /t:Pack /p:PackageVersion=$(NugetPackageVersion) /p:PackageOutputPath="$(Build.ArtifactStagingDirectory)/nuget"' - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: - template: sign-artifacts/jobs/v2.yml@internal-templates diff --git a/samples/XCT.Sample.Android/SplashActivity.cs b/samples/XCT.Sample.Android/SplashActivity.cs index c9d8f69df..2883e4e55 100644 --- a/samples/XCT.Sample.Android/SplashActivity.cs +++ b/samples/XCT.Sample.Android/SplashActivity.cs @@ -9,7 +9,7 @@ namespace Xamarin.CommunityToolkit.Sample.Droid [Activity(Label = "XamarinCommunityToolkitSample", Icon = "@mipmap/icon", Theme = "@style/SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class SplashActivity : AppCompatActivity { - protected override void OnCreate(Bundle savedInstanceState) + protected override void OnCreate(Bundle? savedInstanceState) { base.OnCreate(savedInstanceState); var intent = new Intent(this, typeof(MainActivity)); diff --git a/samples/XCT.Sample.UWP/App.xaml.cs b/samples/XCT.Sample.UWP/App.xaml.cs index 2a60dbd76..29871212c 100644 --- a/samples/XCT.Sample.UWP/App.xaml.cs +++ b/samples/XCT.Sample.UWP/App.xaml.cs @@ -85,7 +85,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e) /// /// The Frame which failed navigation /// Details about the navigation failure - void OnNavigationFailed(object sender, NavigationFailedEventArgs e) + void OnNavigationFailed(object? sender, NavigationFailedEventArgs e) { throw new Exception("Failed to load Page " + e.SourcePageType.FullName); } @@ -97,7 +97,7 @@ void OnNavigationFailed(object sender, NavigationFailedEventArgs e) /// /// The source of the suspend request. /// Details about the suspend request. - void OnSuspending(object sender, SuspendingEventArgs e) + void OnSuspending(object? sender, SuspendingEventArgs e) { var deferral = e.SuspendingOperation.GetDeferral(); diff --git a/samples/XCT.Sample.iOS/Renderers/NoLineNavigationRenderer.cs b/samples/XCT.Sample.iOS/Renderers/NoLineNavigationRenderer.cs index f1231d834..af6c3fc37 100644 --- a/samples/XCT.Sample.iOS/Renderers/NoLineNavigationRenderer.cs +++ b/samples/XCT.Sample.iOS/Renderers/NoLineNavigationRenderer.cs @@ -25,8 +25,11 @@ public override void ViewWillAppear(bool animated) // Newest iOS version fix - trycatch isn't optimal try { - NavigationBar.ScrollEdgeAppearance.ShadowImage = new UIKit.UIImage(); - NavigationBar.ScrollEdgeAppearance.ShadowColor = null; + if (NavigationBar.ScrollEdgeAppearance != null) + { + NavigationBar.ScrollEdgeAppearance.ShadowImage = new UIKit.UIImage(); + NavigationBar.ScrollEdgeAppearance.ShadowColor = null; + } } catch (Exception) { diff --git a/samples/XCT.Sample.sln b/samples/XCT.Sample.sln index fcf418bc7..eab396c70 100644 --- a/samples/XCT.Sample.sln +++ b/samples/XCT.Sample.sln @@ -18,9 +18,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.CommunityToolkit.Sa EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F695F5E8-420F-475F-A4CF-F5BB3FA6E818}" ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - Directory.Build.props = Directory.Build.props - Xamarin.CommunityToolkit.ruleset = Xamarin.CommunityToolkit.ruleset + ..\.editorconfig = ..\.editorconfig + ..\Directory.Build.props = ..\Directory.Build.props + ..\Xamarin.CommunityToolkit.ruleset = ..\Xamarin.CommunityToolkit.ruleset EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.CommunityToolkit.Sample.WPF", "XCT.Sample.WPF\Xamarin.CommunityToolkit.Sample.WPF.csproj", "{C4D6CD2D-8DF4-4D46-936C-1AB31C87B5EA}" @@ -62,6 +62,7 @@ Global {8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Debug|x86.Build.0 = Debug|Any CPU {8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|Any CPU.Build.0 = Release|Any CPU + {8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|Any CPU.Deploy.0 = Release|Any CPU {8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|ARM.ActiveCfg = Release|Any CPU {8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|ARM.Build.0 = Release|Any CPU {8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|iPhone.ActiveCfg = Release|Any CPU @@ -191,6 +192,8 @@ Global {91C748B4-E9ED-4543-880A-26747B03DE3A}.Debug|x86.Build.0 = Debug|x86 {91C748B4-E9ED-4543-880A-26747B03DE3A}.Debug|x86.Deploy.0 = Debug|x86 {91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|Any CPU.ActiveCfg = Release|x86 + {91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|Any CPU.Build.0 = Release|x86 + {91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|Any CPU.Deploy.0 = Release|x86 {91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|ARM.ActiveCfg = Release|ARM {91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|ARM.Build.0 = Release|ARM {91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|ARM.Deploy.0 = Release|ARM diff --git a/samples/XCT.Sample/App.xaml.cs b/samples/XCT.Sample/App.xaml.cs index b5a234305..6e2137b3b 100644 --- a/samples/XCT.Sample/App.xaml.cs +++ b/samples/XCT.Sample/App.xaml.cs @@ -1,4 +1,5 @@ -using Xamarin.CommunityToolkit.Helpers; +using System.Globalization; +using Xamarin.CommunityToolkit.Helpers; using Xamarin.CommunityToolkit.Sample.Pages; using Xamarin.CommunityToolkit.Sample.Resx; using Xamarin.Forms.PlatformConfiguration; @@ -14,6 +15,7 @@ public App() LocalizationResourceManager.Current.PropertyChanged += (sender, e) => AppResources.Culture = LocalizationResourceManager.Current.CurrentCulture; LocalizationResourceManager.Current.Init(AppResources.ResourceManager); + LocalizationResourceManager.Current.CurrentCulture = new CultureInfo("en"); InitializeComponent(); MainPage = new BaseNavigationPage(new WelcomePage()); diff --git a/samples/XCT.Sample/Helpers/RelayCommand.cs b/samples/XCT.Sample/Helpers/RelayCommand.cs index 453460545..d82836760 100644 --- a/samples/XCT.Sample/Helpers/RelayCommand.cs +++ b/samples/XCT.Sample/Helpers/RelayCommand.cs @@ -7,25 +7,21 @@ namespace Xamarin.CommunityToolkit.Sample { public class RelayCommand : ICommand { - readonly Action execute; - readonly Func asyncExecute; + readonly Action? execute; + readonly Func? asyncExecute; + readonly Func? canExecute; - Func canExecute; int executingCount; - public RelayCommand(Action execute, Func canExecute = null) + public RelayCommand(Action execute, Func? canExecute = null) { - if (execute == null) - throw new ArgumentNullException(nameof(execute)); - this.execute = execute; + this.execute = execute ?? throw new ArgumentNullException(nameof(execute)); this.canExecute = canExecute; } - protected RelayCommand(Func execute, Func canExecute = null) // This ctor is protected here and public in a derived class, to allow simple initialization like new RelayCommand(MyMethod) without errors due to ambiguity + protected RelayCommand(Func execute, Func? canExecute = null) // This ctor is protected here and public in a derived class, to allow simple initialization like new RelayCommand(MyMethod) without errors due to ambiguity { - if (execute == null) - throw new ArgumentNullException(nameof(execute)); - asyncExecute = execute; + asyncExecute = execute ?? throw new ArgumentNullException(nameof(execute)); this.canExecute = canExecute; } @@ -34,7 +30,7 @@ public RelayCommand(Action execute, Func canExecute = null) /// /// Ignored; this is the paremeterless command class /// - public bool CanExecute(object parameter = null) + public bool CanExecute(object? parameter = null) { try { @@ -47,15 +43,12 @@ public bool CanExecute(object parameter = null) } } - public event EventHandler CanExecuteChanged; + public event EventHandler? CanExecuteChanged; - public void RaiseCanExecuteChanged() - { - CanExecuteChanged?.Invoke(this, EventArgs.Empty); - } + public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); // Asynchronous command handling based on http://stackoverflow.com/a/31595509/6043538 - public async void Execute(object parameter = null) + public async void Execute(object? parameter = null) { var couldExecuteBeforeExecute = CanExecute(); if (!couldExecuteBeforeExecute) @@ -70,8 +63,10 @@ public async void Execute(object parameter = null) { if (execute != null) execute(); - else + else if (asyncExecute != null) await asyncExecute(); + else + throw new Exception("Execute is null"); } catch (Exception ex) { @@ -89,31 +84,30 @@ public async void Execute(object parameter = null) public class RelayCommandAsync : RelayCommand { - public RelayCommandAsync(Func execute, Func canExecute = null) - : base(execute, canExecute) { } // This ctor is public here and protected in the base class, to allow simple initialization like new RelayCommandAsync(MyMethod) without errors due to ambiguity + public RelayCommandAsync(Func execute, Func? canExecute = null) + : base(execute, canExecute) + { + // This ctor is public here and protected in the base class, to allow simple initialization like new RelayCommandAsync(MyMethod) without errors due to ambiguity + } } public class RelayCommand : ICommand { - readonly Action execute; - readonly Func asyncExecute; + readonly Action? execute; + readonly Func? asyncExecute; + readonly Func? canExecute; - Func canExecute; int executingCount; - public RelayCommand(Action execute, Func canExecute = null) + public RelayCommand(Action execute, Func? canExecute = null) { - if (execute == null) - throw new ArgumentNullException(nameof(execute)); - this.execute = execute; + this.execute = execute ?? throw new ArgumentNullException(nameof(execute)); this.canExecute = canExecute; } - protected RelayCommand(Func execute, Func canExecute = null) // This ctor is protected here and public in a derived class, to allow simple initialization like new RelayCommand(MyMethod) without errors due to ambiguity + protected RelayCommand(Func execute, Func? canExecute = null) // This ctor is protected here and public in a derived class, to allow simple initialization like new RelayCommand(MyMethod) without errors due to ambiguity { - if (execute == null) - throw new ArgumentNullException(nameof(execute)); - asyncExecute = execute; + asyncExecute = execute ?? throw new ArgumentNullException(nameof(execute)); this.canExecute = canExecute; } @@ -122,11 +116,11 @@ public RelayCommand(Action execute, Func canExecut /// /// /// - public bool CanExecute(object parameter = null) + public bool CanExecute(object? parameter = null) { try { - return canExecute != null ? canExecute((TParameter)parameter) : executingCount == 0; + return canExecute != null ? canExecute((TParameter?)parameter) : executingCount == 0; } catch (Exception ex) { @@ -135,12 +129,9 @@ public bool CanExecute(object parameter = null) } } - public event EventHandler CanExecuteChanged; + public event EventHandler? CanExecuteChanged; - public void RaiseCanExecuteChanged() - { - CanExecuteChanged?.Invoke(this, EventArgs.Empty); - } + public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); // Asynchronous command handling based on http://stackoverflow.com/a/31595509/6043538 public async void Execute(object parameterAsObject) @@ -159,13 +150,11 @@ public async void Execute(object parameterAsObject) var parameter = (TParameter)parameterAsObject; if (execute != null) - { execute(parameter); - } - else - { + else if (asyncExecute != null) await asyncExecute(parameter); - } + else + throw new Exception("Execute is null"); } catch (Exception ex) { @@ -183,7 +172,10 @@ public async void Execute(object parameterAsObject) public class RelayCommandAsync : RelayCommand { - public RelayCommandAsync(Func execute, Func canExecute = null) - : base(execute, canExecute) { } // This ctor is public here and protected in the base class, to allow simple initialization like new RelayCommandAsync(MyMethod) without errors due to ambiguity + public RelayCommandAsync(Func execute, Func? canExecute = null) + : base(execute, canExecute) + { + // This ctor is public here and protected in the base class, to allow simple initialization like new RelayCommandAsync(MyMethod) without errors due to ambiguity + } } } \ No newline at end of file diff --git a/samples/XCT.Sample/Helpers/XLog.cs b/samples/XCT.Sample/Helpers/XLog.cs index 88dd1c65c..79e77b027 100644 --- a/samples/XCT.Sample/Helpers/XLog.cs +++ b/samples/XCT.Sample/Helpers/XLog.cs @@ -13,7 +13,7 @@ namespace Xamarin.CommunityToolkit.Sample /// public static class XLog { - static string rootFolderPattern = null; + static string? rootFolderPattern = null; #if WINDOWS_UWP static LoggingChannel loggingChannel; #endif @@ -22,7 +22,7 @@ public static class XLog /// Call this before logging starts. /// /// Should match the top folder name(s) within the source control repository, e.g. @"\MobileRealtimePush\MobileRealtimePush\". Any folders before the first match of this pattern are omitted from the logged source file paths - public static void Init(string rootFolderPattern = null) + public static void Init(string? rootFolderPattern = null) { XLog.rootFolderPattern = rootFolderPattern; #if WINDOWS_UWP @@ -46,10 +46,10 @@ public static void Init(string rootFolderPattern = null) /// supplied by compiler, no need to specify in code unless you want to pass a deeper call context [Conditional("DEBUG")] public static void Debug( - object data = null, - string tag = null, - [CallerMemberName] string memberName = null, - [CallerFilePath] string sourceFilePath = null, + object? data = null, + string? tag = null, + [CallerMemberName] string? memberName = null, + [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = -1) { var message = FormatLogString(data, tag, memberName, sourceFilePath, sourceLineNumber); @@ -75,10 +75,10 @@ public static void Debug( /// supplied by compiler, no need to specify in code unless you want to pass a deeper call context [Conditional("TRACE")] public static void Trace( - object data = null, - string tag = null, - [CallerMemberName] string memberName = null, - [CallerFilePath] string sourceFilePath = null, + object? data = null, + string? tag = null, + [CallerMemberName] string? memberName = null, + [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = -1) { var message = FormatLogString(data, tag, memberName, sourceFilePath, sourceLineNumber); @@ -90,9 +90,9 @@ public static void Trace( #endif } - public static string TruncateAt(this string s, int maxLength, string truncatedSuffix = "...") => s?.Length <= maxLength ? s : s.Substring(0, maxLength) + truncatedSuffix; + public static string TruncateAt(this string? s, int maxLength, string truncatedSuffix = "...") => s?.Length <= maxLength ? s : s?.Substring(0, maxLength) + truncatedSuffix; - static string FormatLogString(object data = null, string tag = null, string memberName = null, string sourceFilePath = null, int sourceLineNumber = -1) + static string FormatLogString(object? data, string? tag, string? memberName, string? sourceFilePath, int sourceLineNumber) { var line = new StringBuilder(); @@ -121,7 +121,7 @@ static string FormatLogString(object data = null, string tag = null, string memb line.Append(dataString); } - if (!string.IsNullOrEmpty(sourceFilePath)) + if (sourceFilePath != null && !string.IsNullOrEmpty(sourceFilePath)) { if (!string.IsNullOrEmpty(rootFolderPattern)) { diff --git a/samples/XCT.Sample/Pages/AboutPage.xaml.cs b/samples/XCT.Sample/Pages/AboutPage.xaml.cs index 2c1826452..40374940d 100644 --- a/samples/XCT.Sample/Pages/AboutPage.xaml.cs +++ b/samples/XCT.Sample/Pages/AboutPage.xaml.cs @@ -1,5 +1,4 @@ using System; -using Xamarin.CommunityToolkit.Sample.ViewModels; namespace Xamarin.CommunityToolkit.Sample.Pages { @@ -8,7 +7,7 @@ public partial class AboutPage : BasePage public AboutPage() => InitializeComponent(); - async void OnCloseClicked(object sender, EventArgs e) + async void OnCloseClicked(object? sender, EventArgs e) => await Navigation.PopModalAsync(); } } \ No newline at end of file diff --git a/samples/XCT.Sample/Pages/Base/BaseNavigationPage.cs b/samples/XCT.Sample/Pages/Base/BaseNavigationPage.cs index 758b1e85e..cd61318df 100644 --- a/samples/XCT.Sample/Pages/Base/BaseNavigationPage.cs +++ b/samples/XCT.Sample/Pages/Base/BaseNavigationPage.cs @@ -9,6 +9,7 @@ public class BaseNavigationPage : XF.NavigationPage public BaseNavigationPage(XF.Page root) : base(root) { + On().SetPrefersHomeIndicatorAutoHidden(true); On().SetModalPresentationStyle(UIModalPresentationStyle.FormSheet); On().DisableTranslucentNavigationBar(); On().SetHideNavigationBarSeparator(true); diff --git a/samples/XCT.Sample/Pages/Base/BasePage.cs b/samples/XCT.Sample/Pages/Base/BasePage.cs index 8e7a5071f..fc558e1ec 100644 --- a/samples/XCT.Sample/Pages/Base/BasePage.cs +++ b/samples/XCT.Sample/Pages/Base/BasePage.cs @@ -1,21 +1,34 @@ using System; +using System.Threading.Tasks; using System.Windows.Input; using Xamarin.CommunityToolkit.ObjectModel; using Xamarin.CommunityToolkit.Sample.Models; using Xamarin.Forms; +using Xamarin.Forms.PlatformConfiguration; +using Xamarin.Forms.PlatformConfiguration.iOSSpecific; namespace Xamarin.CommunityToolkit.Sample.Pages { public class BasePage : ContentPage { - public BasePage() => - NavigateCommand = CommandFactory.Create(sectionModel => Navigation.PushAsync(PreparePage(sectionModel))); + public BasePage() + { + On().SetPrefersHomeIndicatorAutoHidden(true); + + NavigateCommand = CommandFactory.Create(sectionModel => + { + if (sectionModel != null) + return Navigation.PushAsync(PreparePage(sectionModel)); + + return Task.CompletedTask; + }); + } public Color DetailColor { get; set; } public ICommand NavigateCommand { get; } - Page PreparePage(SectionModel model) + Forms.Page PreparePage(SectionModel model) { var page = (BasePage)Activator.CreateInstance(model.Type); page.Title = model.Title; diff --git a/samples/XCT.Sample/Pages/Behaviors/AnimationBehaviorPage.xaml b/samples/XCT.Sample/Pages/Behaviors/AnimationBehaviorPage.xaml index ed8116e73..a4f582554 100644 --- a/samples/XCT.Sample/Pages/Behaviors/AnimationBehaviorPage.xaml +++ b/samples/XCT.Sample/Pages/Behaviors/AnimationBehaviorPage.xaml @@ -48,7 +48,7 @@ -