From 0e742c7a8fe20b9d21781e977f66430acb6a359c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Fri, 27 Feb 2026 20:12:43 +0100 Subject: [PATCH] Resolving warnings and treating warnings as errors in WinUI project. (#824) --- Directory.Packages.props | 2 +- ...mapSynchronizerCalDavConfigurationTests.cs | 2 +- .../Activation/ActivationHandler.cs | 7 +- Wino.Mail.WinUI/App.xaml.cs | 10 +-- .../AccountCreationDialogControl.xaml.cs | 8 +-- .../Calendar/CustomCalendarFlipView.cs | 2 +- .../Controls/Calendar/DayColumnControl.cs | 12 ++-- .../Controls/Calendar/DayHeaderControl.cs | 2 +- .../Controls/Calendar/WinoCalendarControl.cs | 18 ++--- .../Controls/Calendar/WinoCalendarFlipView.cs | 6 +- .../Controls/Calendar/WinoCalendarPanel.cs | 2 +- .../WinoCalendarTypeSelectorControl.cs | 22 +++--- .../Controls/Calendar/WinoCalendarView.cs | 21 +++--- .../Calendar/WinoDayTimelineCanvas.cs | 68 +++++++++++-------- Wino.Mail.WinUI/Controls/WinoInfoBar.cs | 2 +- .../Dialogs/AccountCreationDialog.xaml.cs | 4 +- .../Dialogs/AccountPickerDialog.xaml.cs | 4 +- .../Dialogs/CustomThemeBuilderDialog.xaml.cs | 14 ++-- .../Dialogs/NewAccountDialog.xaml.cs | 25 ++++--- Wino.Mail.WinUI/Dialogs/PrintDialog.xaml.cs | 2 +- .../Extensions/AnimationExtensions.cs | 2 +- .../CompositionExtensions.Implicit.cs | 20 +++--- Wino.Mail.WinUI/Extensions/UtilExtensions.cs | 15 ++-- .../Helpers/CalendarXamlHelpers.cs | 2 +- .../Helpers/WinoVisualTreeHelper.cs | 14 ++-- Wino.Mail.WinUI/Helpers/XamlHelpers.cs | 10 ++- .../Models/PrintDialogViewModel.cs | 8 +-- .../AppThemePreviewTemplateSelector.cs | 8 +-- ...alendarItemShowAsStripeTemplateSelector.cs | 12 ++-- .../CustomWinoMessageDialogIconSelector.cs | 12 ++-- .../Selectors/FileAttachmentTypeSelector.cs | 20 +++--- .../NavigationMenuTemplateSelector.cs | 42 ++++++------ .../RsvpStatusIconTemplateSelector.cs | 10 +-- .../WinoCalendarItemTemplateSelector.cs | 6 +- .../Services/ApplicationResourceManager.cs | 2 +- .../Services/ConfigurationService.cs | 13 ++-- Wino.Mail.WinUI/Services/DialogService.cs | 2 +- Wino.Mail.WinUI/Services/DialogServiceBase.cs | 34 +++++++--- Wino.Mail.WinUI/Services/NativeAppService.cs | 6 +- Wino.Mail.WinUI/Services/NavigationService.cs | 5 +- .../Services/NavigationServiceBase.cs | 2 +- Wino.Mail.WinUI/Services/NewThemeService.cs | 28 +++++--- .../Services/NotificationBuilder.cs | 7 +- .../Services/PreferencesService.cs | 10 +-- Wino.Mail.WinUI/Services/PrintService.cs | 21 ++++-- .../Services/SmimeCertificateService.cs | 4 +- .../Services/StatePersistenceService.cs | 8 ++- Wino.Mail.WinUI/Services/ThumbnailService.cs | 14 ++-- .../Views/Calendar/CalendarPage.xaml.cs | 2 +- .../Settings/AliasManagementPage.xaml.cs | 2 +- .../Views/Settings/ContactsPage.xaml.cs | 2 +- Wino.Mail.WinUI/Wino.Mail.WinUI.csproj | 4 +- Wino.Mail.WinUI/WinoApplication.cs | 22 +++--- .../Translator/TranslatorGenerator.cs | 2 +- .../Wino.SourceGenerators.csproj | 1 + 55 files changed, 336 insertions(+), 269 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 28a2ef2a..8c993a36 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,7 @@ - + diff --git a/Wino.Core.Tests/Synchronizers/ImapSynchronizerCalDavConfigurationTests.cs b/Wino.Core.Tests/Synchronizers/ImapSynchronizerCalDavConfigurationTests.cs index 2f103309..334edefe 100644 --- a/Wino.Core.Tests/Synchronizers/ImapSynchronizerCalDavConfigurationTests.cs +++ b/Wino.Core.Tests/Synchronizers/ImapSynchronizerCalDavConfigurationTests.cs @@ -89,7 +89,7 @@ public class ImapSynchronizerCalDavConfigurationTests private static ImapSynchronizer CreateSynchronizer(string appDataFolder, CustomServerInformation serverInformation, - IAutoDiscoveryService autoDiscoveryService = null) + IAutoDiscoveryService? autoDiscoveryService = null) { var account = new MailAccount { diff --git a/Wino.Mail.WinUI/Activation/ActivationHandler.cs b/Wino.Mail.WinUI/Activation/ActivationHandler.cs index 3f347ce1..845d8bae 100644 --- a/Wino.Mail.WinUI/Activation/ActivationHandler.cs +++ b/Wino.Mail.WinUI/Activation/ActivationHandler.cs @@ -18,13 +18,16 @@ public abstract class ActivationHandler : ActivationHandler public override async Task HandleAsync(object args) { - await HandleInternalAsync(args as T); + if (args is T typedArgs) + { + await HandleInternalAsync(typedArgs); + } } public override bool CanHandle(object args) { // CanHandle checks the args is of type you have configured - return args is T && CanHandleInternal(args as T); + return args is T typedArgs && CanHandleInternal(typedArgs); } // You can override this method to add extra validation on activation args diff --git a/Wino.Mail.WinUI/App.xaml.cs b/Wino.Mail.WinUI/App.xaml.cs index 031915f5..b303ec45 100644 --- a/Wino.Mail.WinUI/App.xaml.cs +++ b/Wino.Mail.WinUI/App.xaml.cs @@ -181,7 +181,7 @@ public partial class App : WinoApplication, else { // Normal launch - show and activate the window. - MainWindow.Activate(); + MainWindow?.Activate(); LogActivation("Window created and activated."); } } @@ -259,8 +259,8 @@ public partial class App : WinoApplication, } else { - MainWindow.BringToFront(); - MainWindow.Activate(); + MainWindow?.BringToFront(); + MainWindow?.Activate(); } navigationService.ChangeApplicationMode(Core.Domain.Enums.WinoApplicationMode.Calendar); @@ -300,7 +300,7 @@ public partial class App : WinoApplication, // App is already running - send message and bring window to front. navigationService.ChangeApplicationMode(Core.Domain.Enums.WinoApplicationMode.Mail); WeakReferenceMessenger.Default.Send(message); - MainWindow.BringToFront(); + MainWindow?.BringToFront(); } } @@ -405,7 +405,7 @@ public partial class App : WinoApplication, // Initialize theme service after window is created. await NewThemeService.InitializeAsync(); - MainWindow.Activate(); + MainWindow?.Activate(); LogActivation("Window created and activated."); } diff --git a/Wino.Mail.WinUI/Controls/AccountCreationDialogControl.xaml.cs b/Wino.Mail.WinUI/Controls/AccountCreationDialogControl.xaml.cs index 90590fbc..09ddcc55 100644 --- a/Wino.Mail.WinUI/Controls/AccountCreationDialogControl.xaml.cs +++ b/Wino.Mail.WinUI/Controls/AccountCreationDialogControl.xaml.cs @@ -14,9 +14,9 @@ namespace Wino.Mail.WinUI.Controls; public sealed partial class AccountCreationDialogControl : UserControl, IRecipient { - private string copyClipboardURL; + private string copyClipboardURL = string.Empty; - public event EventHandler CancelClicked; + public event EventHandler? CancelClicked; public AccountCreationDialogState State { @@ -67,10 +67,10 @@ public sealed partial class AccountCreationDialogControl : UserControl, IRecipie { if (string.IsNullOrEmpty(copyClipboardURL)) return; - var clipboardService = WinoApplication.Current.Services.GetService(); + var clipboardService = WinoApplication.Current.Services.GetRequiredService(); await clipboardService.CopyClipboardAsync(copyClipboardURL); } - private void CancelButtonClicked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) => CancelClicked?.Invoke(this, null); + private void CancelButtonClicked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) => CancelClicked?.Invoke(this, EventArgs.Empty); } diff --git a/Wino.Mail.WinUI/Controls/Calendar/CustomCalendarFlipView.cs b/Wino.Mail.WinUI/Controls/Calendar/CustomCalendarFlipView.cs index 36a291a3..55b94128 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/CustomCalendarFlipView.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/CustomCalendarFlipView.cs @@ -63,7 +63,7 @@ public partial class CustomCalendarFlipView : FlipView private void FlipViewSelectionChanged(object sender, SelectionChangedEventArgs e) => OnSelectedItemChanged(e.RemovedItems.FirstOrDefault(), e.AddedItems.FirstOrDefault()); - protected virtual void OnSelectedItemChanged(object oldValue, object newValue) { } + protected virtual void OnSelectedItemChanged(object? oldValue, object? newValue) { } protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { diff --git a/Wino.Mail.WinUI/Controls/Calendar/DayColumnControl.cs b/Wino.Mail.WinUI/Controls/Calendar/DayColumnControl.cs index 2f0838e1..9ac8d81b 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/DayColumnControl.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/DayColumnControl.cs @@ -18,11 +18,11 @@ public partial class DayColumnControl : Control private const string TodayState = nameof(TodayState); private const string NotTodayState = nameof(NotTodayState); - private TextBlock HeaderDateDayText; - private TextBlock ColumnHeaderText; - private Border IsTodayBorder; - private ItemsControl AllDayItemsControl; - private CalendarEventCollection _boundEventsCollection; + private TextBlock? HeaderDateDayText; + private TextBlock? ColumnHeaderText; + private Border? IsTodayBorder; + private ItemsControl? AllDayItemsControl; + private CalendarEventCollection? _boundEventsCollection; public CalendarDayModel DayModel { @@ -97,7 +97,7 @@ public partial class DayColumnControl : Control _boundEventsCollection = null; } - private void EventsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void EventsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { UpdateEventItemsSource(); } diff --git a/Wino.Mail.WinUI/Controls/Calendar/DayHeaderControl.cs b/Wino.Mail.WinUI/Controls/Calendar/DayHeaderControl.cs index d7154ef2..675fa753 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/DayHeaderControl.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/DayHeaderControl.cs @@ -8,7 +8,7 @@ namespace Wino.Calendar.Controls; public partial class DayHeaderControl : Control { private const string PART_DayHeaderTextBlock = nameof(PART_DayHeaderTextBlock); - private TextBlock HeaderTextblock; + private TextBlock? HeaderTextblock; public DayHeaderDisplayType DisplayType { diff --git a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs index 2b6d4d0a..ab33d8fb 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs @@ -18,10 +18,10 @@ public partial class WinoCalendarControl : Control private const string PART_WinoFlipView = nameof(PART_WinoFlipView); private const string PART_IdleGrid = nameof(PART_IdleGrid); - public event EventHandler TimelineCellSelected; - public event EventHandler TimelineCellUnselected; + public event EventHandler? TimelineCellSelected; + public event EventHandler? TimelineCellUnselected; - public event EventHandler ScrollPositionChanging; + public event EventHandler? ScrollPositionChanging; #region Dependency Properties @@ -66,8 +66,8 @@ public partial class WinoCalendarControl : Control #endregion - private WinoCalendarFlipView InternalFlipView; - private Grid IdleGrid; + private WinoCalendarFlipView? InternalFlipView; + private Grid? IdleGrid; private ScrollViewer? _previousScrollViewer; private WinoDayTimelineCanvas? _previousCanvas; @@ -183,7 +183,7 @@ public partial class WinoCalendarControl : Control scrollViewer.ViewChanging -= ScrollViewChanging; } - private void ScrollViewChanging(object sender, ScrollViewerViewChangingEventArgs e) + private void ScrollViewChanging(object? sender, ScrollViewerViewChangingEventArgs e) => ScrollPositionChanging?.Invoke(this, EventArgs.Empty); private void CalendarSizeChanged(object sender, SizeChangedEventArgs e) @@ -233,10 +233,10 @@ public partial class WinoCalendarControl : Control } } - private void ActiveTimelineCellUnselected(object sender, TimelineCellUnselectedArgs e) + private void ActiveTimelineCellUnselected(object? sender, TimelineCellUnselectedArgs e) => TimelineCellUnselected?.Invoke(this, e); - private void ActiveTimelineCellSelected(object sender, TimelineCellSelectedArgs e) + private void ActiveTimelineCellSelected(object? sender, TimelineCellSelectedArgs e) => TimelineCellSelected?.Invoke(this, e); public void NavigateToDay(DateTime dateTime) => InternalFlipView?.NavigateToDay(dateTime); @@ -289,6 +289,6 @@ public partial class WinoCalendarControl : Control public CalendarItemControl GetCalendarItemControl(CalendarItemViewModel calendarItemViewModel) { - return this.FindDescendants().FirstOrDefault(a => a.CalendarItem == calendarItemViewModel); + return this.FindDescendants().FirstOrDefault(a => a.CalendarItem == calendarItemViewModel)!; } } diff --git a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarFlipView.cs b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarFlipView.cs index f4b0dc1c..7aa9b2c5 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarFlipView.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarFlipView.cs @@ -81,7 +81,7 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView UpdateIdleState(); } - protected override void OnSelectedItemChanged(object oldValue, object newValue) + protected override void OnSelectedItemChanged(object? oldValue, object? newValue) { base.OnSelectedItemChanged(oldValue, newValue); @@ -101,7 +101,7 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView } } - private void ItemsSourceUpdated(object sender, NotifyCollectionChangedEventArgs e) + private void ItemsSourceUpdated(object? sender, NotifyCollectionChangedEventArgs e) { UpdateIdleState(); } @@ -205,7 +205,7 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView }); } - private ObservableRangeCollection GetItemsSource() + private ObservableRangeCollection? GetItemsSource() => ItemsSource as ObservableRangeCollection; } diff --git a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarPanel.cs b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarPanel.cs index 76e29ed7..e62e50eb 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarPanel.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarPanel.cs @@ -120,7 +120,7 @@ public partial class WinoCalendarPanel : Panel if (!calendarControls.Any()) return base.ArrangeOverride(finalSize); - var events = calendarControls.Select(a => a.Content as CalendarItemViewModel); + var events = calendarControls.Select(a => a.Content as CalendarItemViewModel).OfType(); LayoutEvents(events); diff --git a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarTypeSelectorControl.cs b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarTypeSelectorControl.cs index af396931..7403eeb6 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarTypeSelectorControl.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarTypeSelectorControl.cs @@ -21,9 +21,9 @@ public partial class WinoCalendarTypeSelectorControl : Control public static readonly DependencyProperty DisplayDayCountProperty = DependencyProperty.Register(nameof(DisplayDayCount), typeof(int), typeof(WinoCalendarTypeSelectorControl), new PropertyMetadata(0)); public static readonly DependencyProperty TodayClickedCommandProperty = DependencyProperty.Register(nameof(TodayClickedCommand), typeof(ICommand), typeof(WinoCalendarTypeSelectorControl), new PropertyMetadata(null)); - public ICommand TodayClickedCommand + public ICommand? TodayClickedCommand { - get { return (ICommand)GetValue(TodayClickedCommandProperty); } + get { return (ICommand?)GetValue(TodayClickedCommandProperty); } set { SetValue(TodayClickedCommandProperty, value); } } @@ -39,10 +39,10 @@ public partial class WinoCalendarTypeSelectorControl : Control set { SetValue(DisplayDayCountProperty, value); } } - private AppBarButton _todayButton; - private AppBarToggleButton _dayToggle; - private AppBarToggleButton _weekToggle; - private AppBarToggleButton _monthToggle; + private AppBarButton? _todayButton; + private AppBarToggleButton? _dayToggle; + private AppBarToggleButton? _weekToggle; + private AppBarToggleButton? _monthToggle; public WinoCalendarTypeSelectorControl() { @@ -65,16 +65,16 @@ public partial class WinoCalendarTypeSelectorControl : Control Guard.IsNotNull(_weekToggle, nameof(_weekToggle)); Guard.IsNotNull(_monthToggle, nameof(_monthToggle)); - _todayButton.Click += TodayClicked; + _todayButton!.Click += TodayClicked; - _dayToggle.Click += (s, e) => { SetSelectedType(CalendarDisplayType.Day); }; - _weekToggle.Click += (s, e) => { SetSelectedType(CalendarDisplayType.Week); }; - _monthToggle.Click += (s, e) => { SetSelectedType(CalendarDisplayType.Month); }; + _dayToggle!.Click += (s, e) => { SetSelectedType(CalendarDisplayType.Day); }; + _weekToggle!.Click += (s, e) => { SetSelectedType(CalendarDisplayType.Week); }; + _monthToggle!.Click += (s, e) => { SetSelectedType(CalendarDisplayType.Month); }; UpdateToggleButtonStates(); } - private void TodayClicked(object sender, RoutedEventArgs e) => TodayClickedCommand?.Execute(null); + private void TodayClicked(object? sender, RoutedEventArgs e) => TodayClickedCommand?.Execute(null); private void SetSelectedType(CalendarDisplayType type) { diff --git a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarView.cs b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarView.cs index 96135b13..7ff9dd51 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarView.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarView.cs @@ -18,7 +18,7 @@ public partial class WinoCalendarView : Control public static readonly DependencyProperty HighlightedDateRangeProperty = DependencyProperty.Register(nameof(HighlightedDateRange), typeof(DateRange), typeof(WinoCalendarView), new PropertyMetadata(null, new PropertyChangedCallback(OnHighlightedDateRangeChanged))); public static readonly DependencyProperty VisibleDateBackgroundProperty = DependencyProperty.Register(nameof(VisibleDateBackground), typeof(Brush), typeof(WinoCalendarView), new PropertyMetadata(null, new PropertyChangedCallback(OnPropertiesChanged))); public static readonly DependencyProperty DateClickedCommandProperty = DependencyProperty.Register(nameof(DateClickedCommand), typeof(ICommand), typeof(WinoCalendarView), new PropertyMetadata(null)); - public static readonly DependencyProperty TodayBackgroundColorProperty = DependencyProperty.Register(nameof(TodayBackgroundColor), typeof(Color), typeof(WinoCalendarView), new PropertyMetadata(null)); + public static readonly DependencyProperty TodayBackgroundColorProperty = DependencyProperty.Register(nameof(TodayBackgroundColor), typeof(Color), typeof(WinoCalendarView), new PropertyMetadata(new Color())); public Color TodayBackgroundColor { @@ -30,30 +30,30 @@ public partial class WinoCalendarView : Control /// Gets or sets the command to execute when a date is picked. /// Unused. /// - public ICommand DateClickedCommand + public ICommand? DateClickedCommand { - get { return (ICommand)GetValue(DateClickedCommandProperty); } + get { return (ICommand?)GetValue(DateClickedCommandProperty); } set { SetValue(DateClickedCommandProperty, value); } } /// /// Gets or sets the highlighted range of dates. /// - public DateRange HighlightedDateRange + public DateRange? HighlightedDateRange { - get { return (DateRange)GetValue(HighlightedDateRangeProperty); } + get { return (DateRange?)GetValue(HighlightedDateRangeProperty); } set { SetValue(HighlightedDateRangeProperty, value); } } - public Brush VisibleDateBackground + public Brush? VisibleDateBackground { - get { return (Brush)GetValue(VisibleDateBackgroundProperty); } + get { return (Brush?)GetValue(VisibleDateBackgroundProperty); } set { SetValue(VisibleDateBackgroundProperty, value); } } - private CalendarView CalendarView; + private CalendarView? CalendarView; public WinoCalendarView() { @@ -67,6 +67,7 @@ public partial class WinoCalendarView : Control CalendarView = GetTemplateChild(PART_CalendarView) as CalendarView; Guard.IsNotNull(CalendarView, nameof(CalendarView)); + if (CalendarView == null) return; CalendarView.SelectedDatesChanged -= InternalCalendarViewSelectionChanged; CalendarView.SelectedDatesChanged += InternalCalendarViewSelectionChanged; @@ -92,7 +93,7 @@ public partial class WinoCalendarView : Control } // Reset selection, we don't show selected dates but react to them. - CalendarView.SelectedDates.Clear(); + CalendarView?.SelectedDates.Clear(); } private static void OnPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) @@ -107,7 +108,7 @@ public partial class WinoCalendarView : Control // Changing selected dates will trigger the selection changed event. // It will behave like user clicked the date. - public void GoToDay(DateTime dateTime) => CalendarView.SelectedDates.Add(dateTime); + public void GoToDay(DateTime dateTime) => CalendarView?.SelectedDates.Add(dateTime); private static void OnHighlightedDateRangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { diff --git a/Wino.Mail.WinUI/Controls/Calendar/WinoDayTimelineCanvas.cs b/Wino.Mail.WinUI/Controls/Calendar/WinoDayTimelineCanvas.cs index b318388e..c1c52900 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/WinoDayTimelineCanvas.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/WinoDayTimelineCanvas.cs @@ -17,11 +17,11 @@ namespace Wino.Calendar.Controls; public partial class WinoDayTimelineCanvas : Control, IDisposable { - public event EventHandler TimelineCellSelected; - public event EventHandler TimelineCellUnselected; + public event EventHandler? TimelineCellSelected; + public event EventHandler? TimelineCellUnselected; private const string PART_InternalCanvas = nameof(PART_InternalCanvas); - private SKXamlCanvas Canvas; + private SKXamlCanvas? Canvas; public static readonly DependencyProperty RenderOptionsProperty = DependencyProperty.Register(nameof(RenderOptions), typeof(CalendarRenderOptions), typeof(WinoDayTimelineCanvas), new PropertyMetadata(null, new PropertyChangedCallback(OnRenderingPropertiesChanged))); public static readonly DependencyProperty SeperatorColorProperty = DependencyProperty.Register(nameof(SeperatorColor), typeof(SolidColorBrush), typeof(WinoDayTimelineCanvas), new PropertyMetadata(null, new PropertyChangedCallback(OnRenderingPropertiesChanged))); @@ -31,39 +31,39 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable public static readonly DependencyProperty SelectedDateTimeProperty = DependencyProperty.Register(nameof(SelectedDateTime), typeof(DateTime?), typeof(WinoDayTimelineCanvas), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedDateTimeChanged))); public static readonly DependencyProperty PositionerUIElementProperty = DependencyProperty.Register(nameof(PositionerUIElement), typeof(UIElement), typeof(WinoDayTimelineCanvas), new PropertyMetadata(null)); - public UIElement PositionerUIElement + public UIElement? PositionerUIElement { - get { return (UIElement)GetValue(PositionerUIElementProperty); } + get { return (UIElement?)GetValue(PositionerUIElementProperty); } set { SetValue(PositionerUIElementProperty, value); } } - public CalendarRenderOptions RenderOptions + public CalendarRenderOptions? RenderOptions { - get { return (CalendarRenderOptions)GetValue(RenderOptionsProperty); } + get { return (CalendarRenderOptions?)GetValue(RenderOptionsProperty); } set { SetValue(RenderOptionsProperty, value); } } - public SolidColorBrush HalfHourSeperatorColor + public SolidColorBrush? HalfHourSeperatorColor { - get { return (SolidColorBrush)GetValue(HalfHourSeperatorColorProperty); } + get { return (SolidColorBrush?)GetValue(HalfHourSeperatorColorProperty); } set { SetValue(HalfHourSeperatorColorProperty, value); } } - public SolidColorBrush SeperatorColor + public SolidColorBrush? SeperatorColor { - get { return (SolidColorBrush)GetValue(SeperatorColorProperty); } + get { return (SolidColorBrush?)GetValue(SeperatorColorProperty); } set { SetValue(SeperatorColorProperty, value); } } - public SolidColorBrush WorkingHourCellBackgroundColor + public SolidColorBrush? WorkingHourCellBackgroundColor { - get { return (SolidColorBrush)GetValue(WorkingHourCellBackgroundColorProperty); } + get { return (SolidColorBrush?)GetValue(WorkingHourCellBackgroundColorProperty); } set { SetValue(WorkingHourCellBackgroundColorProperty, value); } } - public SolidColorBrush SelectedCellBackgroundBrush + public SolidColorBrush? SelectedCellBackgroundBrush { - get { return (SolidColorBrush)GetValue(SelectedCellBackgroundBrushProperty); } + get { return (SolidColorBrush?)GetValue(SelectedCellBackgroundBrushProperty); } set { SetValue(SelectedCellBackgroundBrushProperty, value); } } @@ -106,9 +106,11 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable TimelineCellUnselected?.Invoke(this, new TimelineCellUnselectedArgs()); } - private void OnCanvasPointerPressed(object sender, PointerRoutedEventArgs e) + private void OnCanvasPointerPressed(object? sender, PointerRoutedEventArgs e) { if (RenderOptions == null) return; + var canvas = Canvas; + if (canvas == null) return; var hourHeight = RenderOptions.CalendarSettings.HourHeight; @@ -119,12 +121,15 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable PositionerUIElement = this.FindParents().LastOrDefault(a => a is Grid); } + if (PositionerUIElement == null) + return; + PointerPoint positionerRootPoint = e.GetCurrentPoint(PositionerUIElement); - PointerPoint canvasPointerPoint = e.GetCurrentPoint(Canvas); + PointerPoint canvasPointerPoint = e.GetCurrentPoint(canvas); Point touchPoint = canvasPointerPoint.Position; - var singleDayWidth = (Canvas.ActualWidth / RenderOptions.TotalDayCount); + var singleDayWidth = (canvas.ActualWidth / RenderOptions.TotalDayCount); int day = (int)(touchPoint.X / singleDayWidth); int hour = (int)(touchPoint.Y / hourHeight); @@ -187,9 +192,14 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable && SelectedCellBackgroundBrush != null; } - private void OnCanvasPaintSurface(object sender, SKPaintSurfaceEventArgs e) + private void OnCanvasPaintSurface(object? sender, SKPaintSurfaceEventArgs e) { if (!CanDrawTimeline()) return; + var renderOptions = RenderOptions!; + var workingHourCellBackgroundColor = WorkingHourCellBackgroundColor!; + var seperatorColor = SeperatorColor!; + var halfHourSeperatorColor = HalfHourSeperatorColor!; + var selectedCellBackgroundBrush = SelectedCellBackgroundBrush!; var canvas = e.Surface.Canvas; canvas.Clear(SKColors.Transparent); @@ -203,13 +213,13 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable // Calculate the width of each rectangle (1 day column) // Equal distribution of the whole width. - double rectWidth = canvasWidth / RenderOptions.TotalDayCount; + double rectWidth = canvasWidth / renderOptions.TotalDayCount; // Calculate the height of each rectangle (1 hour row) - double rectHeight = RenderOptions.CalendarSettings.HourHeight; + double rectHeight = renderOptions.CalendarSettings.HourHeight; // Define stroke and fill colors - var strokeColor = ToSKColor(SeperatorColor.Color); + var strokeColor = ToSKColor(seperatorColor.Color); float strokeThickness = 0.5f; // Create paints for drawing @@ -229,18 +239,18 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable using var dashedPaint = new SKPaint { - Color = ToSKColor(HalfHourSeperatorColor.Color), + Color = ToSKColor(halfHourSeperatorColor.Color), StrokeWidth = strokeThickness, Style = SKPaintStyle.Stroke, PathEffect = SKPathEffect.CreateDash([2f, 2f], 0), IsAntialias = true }; - for (int day = 0; day < RenderOptions.TotalDayCount; day++) + for (int day = 0; day < renderOptions.TotalDayCount; day++) { - var currentDay = RenderOptions.DateRange.StartDate.AddDays(day); + var currentDay = renderOptions.DateRange.StartDate.AddDays(day); - bool isWorkingDay = RenderOptions.CalendarSettings.WorkingDays.Contains(currentDay.DayOfWeek); + bool isWorkingDay = renderOptions.CalendarSettings.WorkingDays.Contains(currentDay.DayOfWeek); // Loop through each hour (rows) for (int hour = 0; hour < hours; hour++) @@ -263,12 +273,12 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable // Fill another rectangle with the working hour background color // This rectangle must be placed with -1 margin to prevent invisible borders of the main rectangle. - if (isWorkingDay && renderTime >= RenderOptions.CalendarSettings.WorkingHourStart && renderTime <= RenderOptions.CalendarSettings.WorkingHourEnd) + if (isWorkingDay && renderTime >= renderOptions.CalendarSettings.WorkingHourStart && renderTime <= renderOptions.CalendarSettings.WorkingHourEnd) { var backgroundRectangle = new SKRect(x + 1, y + 1, x + width - 1, y + height - 1); canvas.DrawRect(backgroundRectangle, strokePaint); - fillPaint.Color = ToSKColor(WorkingHourCellBackgroundColor.Color); + fillPaint.Color = ToSKColor(workingHourCellBackgroundColor.Color); canvas.DrawRect(backgroundRectangle, fillPaint); } @@ -298,7 +308,7 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable (float)(day * rectWidth + rectWidth), (float)(selectedY + selectionRectHeight)); - fillPaint.Color = ToSKColor(SelectedCellBackgroundBrush.Color); + fillPaint.Color = ToSKColor(selectedCellBackgroundBrush.Color); canvas.DrawRect(selectedRectangle, fillPaint); } } diff --git a/Wino.Mail.WinUI/Controls/WinoInfoBar.cs b/Wino.Mail.WinUI/Controls/WinoInfoBar.cs index 291e50e3..08a986cd 100644 --- a/Wino.Mail.WinUI/Controls/WinoInfoBar.cs +++ b/Wino.Mail.WinUI/Controls/WinoInfoBar.cs @@ -71,7 +71,7 @@ public partial class WinoInfoBar : InfoBar } } - private async void TimerTick(object sender, object e) + private async void TimerTick(object? sender, object e) { _dispatcherTimer.Stop(); _dispatcherTimer.Tick -= TimerTick; diff --git a/Wino.Mail.WinUI/Dialogs/AccountCreationDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/AccountCreationDialog.xaml.cs index 0db3fa3a..06c14b6a 100644 --- a/Wino.Mail.WinUI/Dialogs/AccountCreationDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/AccountCreationDialog.xaml.cs @@ -10,7 +10,7 @@ namespace Wino.Dialogs; public sealed partial class AccountCreationDialog : ContentDialog, IAccountCreationDialog { private TaskCompletionSource dialogOpened = new TaskCompletionSource(); - public CancellationTokenSource CancellationTokenSource { get; private set; } + public CancellationTokenSource? CancellationTokenSource { get; private set; } public AccountCreationDialogState State { @@ -41,7 +41,7 @@ public sealed partial class AccountCreationDialog : ContentDialog, IAccountCreat // Unregister from closing event. Closing -= DialogClosing; - if (cancel && !CancellationTokenSource.IsCancellationRequested) + if (cancel && CancellationTokenSource != null && !CancellationTokenSource.IsCancellationRequested) { CancellationTokenSource.Cancel(); } diff --git a/Wino.Mail.WinUI/Dialogs/AccountPickerDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/AccountPickerDialog.xaml.cs index f90d5e41..1c8c19c6 100644 --- a/Wino.Mail.WinUI/Dialogs/AccountPickerDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/AccountPickerDialog.xaml.cs @@ -6,9 +6,9 @@ namespace Wino.Dialogs; public sealed partial class AccountPickerDialog : ContentDialog { - public MailAccount PickedAccount { get; set; } + public MailAccount? PickedAccount { get; set; } - public List AvailableAccounts { get; set; } + public List AvailableAccounts { get; set; } = []; public AccountPickerDialog(List availableAccounts) { diff --git a/Wino.Mail.WinUI/Dialogs/CustomThemeBuilderDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/CustomThemeBuilderDialog.xaml.cs index a3c53cc4..89671202 100644 --- a/Wino.Mail.WinUI/Dialogs/CustomThemeBuilderDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/CustomThemeBuilderDialog.xaml.cs @@ -10,21 +10,21 @@ namespace Wino.Dialogs; public sealed partial class CustomThemeBuilderDialog : ContentDialog { - public byte[] WallpaperData { get; private set; } - public string AccentColor { get; private set; } + public byte[] WallpaperData { get; private set; } = Array.Empty(); + public string AccentColor { get; private set; } = string.Empty; - private INewThemeService _themeService; + private readonly INewThemeService _themeService; public CustomThemeBuilderDialog() { InitializeComponent(); - _themeService = WinoApplication.Current.Services.GetService(); + _themeService = WinoApplication.Current.Services.GetRequiredService(); } private async void ApplyClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args) { - if (Array.Empty() == WallpaperData) + if (WallpaperData.Length == 0) return; var deferal = args.GetDeferral(); @@ -45,11 +45,11 @@ public sealed partial class CustomThemeBuilderDialog : ContentDialog private async void BrowseWallpaperClicked(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) { - var dialogService = WinoApplication.Current.Services.GetService(); + var dialogService = WinoApplication.Current.Services.GetRequiredService(); var pickedFileData = await dialogService.PickWindowsFileContentAsync(".jpg", ".png"); - if (pickedFileData == Array.Empty()) return; + if (pickedFileData.Length == 0) return; IsPrimaryButtonEnabled = true; diff --git a/Wino.Mail.WinUI/Dialogs/NewAccountDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/NewAccountDialog.xaml.cs index 1655a356..7622945b 100644 --- a/Wino.Mail.WinUI/Dialogs/NewAccountDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/NewAccountDialog.xaml.cs @@ -15,7 +15,7 @@ namespace Wino.Mail.WinUI.Dialogs; public sealed partial class NewAccountDialog : ContentDialog { - private Dictionary helpingLinks = new Dictionary() + private readonly Dictionary helpingLinks = new Dictionary() { { SpecialImapProvider.iCloud, "https://support.apple.com/en-us/102654" }, { SpecialImapProvider.Yahoo, "http://help.yahoo.com/kb/SLN15241.html" }, @@ -28,9 +28,9 @@ public sealed partial class NewAccountDialog : ContentDialog public static readonly DependencyProperty SelectedCalendarModeIndexProperty = DependencyProperty.Register(nameof(SelectedCalendarModeIndex), typeof(int), typeof(NewAccountDialog), new PropertyMetadata(0)); - public AppColorViewModel SelectedColor + public AppColorViewModel? SelectedColor { - get { return (AppColorViewModel)GetValue(SelectedColorProperty); } + get { return (AppColorViewModel?)GetValue(SelectedColorProperty); } set { SetValue(SelectedColorProperty, value); } } @@ -43,9 +43,9 @@ public sealed partial class NewAccountDialog : ContentDialog /// /// Gets or sets current selected mail provider in the dialog. /// - public ProviderDetail SelectedMailProvider + public ProviderDetail? SelectedMailProvider { - get { return (ProviderDetail)GetValue(SelectedMailProviderProperty); } + get { return (ProviderDetail?)GetValue(SelectedMailProviderProperty); } set { SetValue(SelectedMailProviderProperty, value); } } @@ -64,9 +64,9 @@ public sealed partial class NewAccountDialog : ContentDialog // List of available mail providers for now. - public List Providers { get; set; } + public List Providers { get; set; } = []; - public List AvailableColors { get; set; } + public List AvailableColors { get; set; } = []; public List CalendarModeOptions { get; } = [ Translator.ImapCalDavSettingsPage_CalendarModeCalDav, @@ -75,7 +75,7 @@ public sealed partial class NewAccountDialog : ContentDialog ]; - public AccountCreationDialogResult Result = null; + public AccountCreationDialogResult? Result = null; public NewAccountDialog() { @@ -113,6 +113,9 @@ public sealed partial class NewAccountDialog : ContentDialog private void CreateClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args) { + if (SelectedMailProvider == null) + return; + if (IsSpecialImapServerPartVisible) { // Special imap detail input. @@ -198,7 +201,11 @@ public sealed partial class NewAccountDialog : ContentDialog private async void AppSpecificHelpButtonClicked(object sender, RoutedEventArgs e) { - var helpUrl = helpingLinks[SelectedMailProvider.SpecialImapProvider]; + if (SelectedMailProvider == null || + !helpingLinks.TryGetValue(SelectedMailProvider.SpecialImapProvider, out var helpUrl)) + { + return; + } await Launcher.LaunchUriAsync(new Uri(helpUrl)); } diff --git a/Wino.Mail.WinUI/Dialogs/PrintDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/PrintDialog.xaml.cs index a6eed4f7..75b7768b 100644 --- a/Wino.Mail.WinUI/Dialogs/PrintDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/PrintDialog.xaml.cs @@ -25,7 +25,7 @@ public sealed partial class PrintDialog : ContentDialog /// Initializes the dialog with existing print settings. /// /// The initial print settings to load. - public PrintDialog(WebView2PrintSettingsModel printSettings = null) + public PrintDialog(WebView2PrintSettingsModel printSettings = default!) { if (printSettings != null) PrintSettings = printSettings; diff --git a/Wino.Mail.WinUI/Extensions/AnimationExtensions.cs b/Wino.Mail.WinUI/Extensions/AnimationExtensions.cs index f97b70dc..444b7d54 100644 --- a/Wino.Mail.WinUI/Extensions/AnimationExtensions.cs +++ b/Wino.Mail.WinUI/Extensions/AnimationExtensions.cs @@ -76,7 +76,7 @@ public static class AnimationExtensions public static void Animate(this DependencyObject target, double? from, double to, string propertyPath, int duration = 400, int startTime = 0, - EasingFunctionBase easing = null, Action completed = null, bool enableDependentAnimation = false) + EasingFunctionBase? easing = null, Action? completed = null, bool enableDependentAnimation = false) { if (easing == null) { diff --git a/Wino.Mail.WinUI/Extensions/CompositionExtensions.Implicit.cs b/Wino.Mail.WinUI/Extensions/CompositionExtensions.Implicit.cs index 5e49e033..64f0cfbe 100644 --- a/Wino.Mail.WinUI/Extensions/CompositionExtensions.Implicit.cs +++ b/Wino.Mail.WinUI/Extensions/CompositionExtensions.Implicit.cs @@ -17,12 +17,12 @@ public static partial class CompositionExtensions var compositor = elementVisual.Compositor; ElementCompositionPreview.SetIsTranslationEnabled(element, true); - ScalarKeyFrameAnimation hideOpacityAnimation = null; - ScalarKeyFrameAnimation showOpacityAnimation = null; - ScalarKeyFrameAnimation hideOffsetAnimation = null; - ScalarKeyFrameAnimation showOffsetAnimation = null; - Vector2KeyFrameAnimation hideScaleAnimation = null; - Vector2KeyFrameAnimation showeScaleAnimation = null; + ScalarKeyFrameAnimation? hideOpacityAnimation = null; + ScalarKeyFrameAnimation? showOpacityAnimation = null; + ScalarKeyFrameAnimation? hideOffsetAnimation = null; + ScalarKeyFrameAnimation? showOffsetAnimation = null; + Vector2KeyFrameAnimation? hideScaleAnimation = null; + Vector2KeyFrameAnimation? showeScaleAnimation = null; if (animateOpacity) { @@ -119,7 +119,7 @@ public static partial class CompositionExtensions } public static void EnableImplicitAnimation(this UIElement element, VisualPropertyType typeToAnimate, - double duration = 800, double delay = 0, CompositionEasingFunction easing = null) + double duration = 800, double delay = 0, CompositionEasingFunction? easing = null) { var visual = element.Visual(); var compositor = visual.Compositor; @@ -142,7 +142,7 @@ public static partial class CompositionExtensions } public static void EnableImplicitAnimation(this Visual visual, VisualPropertyType typeToAnimate, - double duration = 800, double delay = 0, CompositionEasingFunction easing = null) + double duration = 800, double delay = 0, CompositionEasingFunction? easing = null) { var compositor = visual.Compositor; @@ -163,8 +163,8 @@ public static partial class CompositionExtensions visual.ImplicitAnimations = animationCollection; } - private static KeyFrameAnimation CreateAnimationByType(Compositor compositor, VisualPropertyType type, - double duration = 800, double delay = 0, CompositionEasingFunction easing = null) + private static KeyFrameAnimation? CreateAnimationByType(Compositor compositor, VisualPropertyType type, + double duration = 800, double delay = 0, CompositionEasingFunction? easing = null) { KeyFrameAnimation animation; diff --git a/Wino.Mail.WinUI/Extensions/UtilExtensions.cs b/Wino.Mail.WinUI/Extensions/UtilExtensions.cs index b7c43b3e..8ea7d554 100644 --- a/Wino.Mail.WinUI/Extensions/UtilExtensions.cs +++ b/Wino.Mail.WinUI/Extensions/UtilExtensions.cs @@ -22,9 +22,9 @@ public static class UtilExtensions { var child = VisualTreeHelper.GetChild(parent, i); - if (child is FrameworkElement) + if (child is FrameworkElement frameworkElement) { - list.Add(child as FrameworkElement); + list.Add(frameworkElement); } list.AddRange(Children(child)); @@ -33,20 +33,13 @@ public static class UtilExtensions return list; } - public static T GetChildByName(this DependencyObject parent, string name) + public static T? GetChildByName(this DependencyObject parent, string name) where T : class { var childControls = Children(parent); var controls = childControls.OfType(); - if (controls == null) - { - return default(T); - } - var control = controls - .Where(x => x.Name.Equals(name)) - .Cast() - .First(); + .FirstOrDefault(x => x.Name.Equals(name)) as T; return control; } diff --git a/Wino.Mail.WinUI/Helpers/CalendarXamlHelpers.cs b/Wino.Mail.WinUI/Helpers/CalendarXamlHelpers.cs index 8db6c8b5..8f9d4eab 100644 --- a/Wino.Mail.WinUI/Helpers/CalendarXamlHelpers.cs +++ b/Wino.Mail.WinUI/Helpers/CalendarXamlHelpers.cs @@ -15,7 +15,7 @@ namespace Wino.Calendar.Helpers; public static class CalendarXamlHelpers { public static CalendarItemViewModel GetFirstAllDayEvent(CalendarEventCollection collection) - => (CalendarItemViewModel)collection.AllDayEvents.FirstOrDefault(); + => collection.AllDayEvents.OfType().FirstOrDefault()!; /// /// Returns full date + duration info in Event Details page details title. diff --git a/Wino.Mail.WinUI/Helpers/WinoVisualTreeHelper.cs b/Wino.Mail.WinUI/Helpers/WinoVisualTreeHelper.cs index a572e2b4..0082d243 100644 --- a/Wino.Mail.WinUI/Helpers/WinoVisualTreeHelper.cs +++ b/Wino.Mail.WinUI/Helpers/WinoVisualTreeHelper.cs @@ -6,18 +6,20 @@ namespace Wino.Helpers; public static class WinoVisualTreeHelper { - public static T GetChildObject(DependencyObject obj, string name) where T : FrameworkElement + public static T? GetChildObject(DependencyObject? obj, string name) where T : FrameworkElement { - DependencyObject child = null; - T grandChild = null; + if (obj == null) return null; + + DependencyObject? child = null; + T? grandChild = null; for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++) { child = VisualTreeHelper.GetChild(obj, i); - if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name))) + if (child is T typedChild && (typedChild.Name == name || string.IsNullOrEmpty(name))) { - return (T)child; + return typedChild; } else { @@ -31,7 +33,7 @@ public static class WinoVisualTreeHelper return null; } - public static IEnumerable FindDescendants(this DependencyObject depObj) where T : DependencyObject + public static IEnumerable FindDescendants(this DependencyObject? depObj) where T : DependencyObject { if (depObj != null) { diff --git a/Wino.Mail.WinUI/Helpers/XamlHelpers.cs b/Wino.Mail.WinUI/Helpers/XamlHelpers.cs index f3e2f135..05891966 100644 --- a/Wino.Mail.WinUI/Helpers/XamlHelpers.cs +++ b/Wino.Mail.WinUI/Helpers/XamlHelpers.cs @@ -51,7 +51,7 @@ public static class XamlHelpers public static ListViewSelectionMode BoolToSelectionMode(bool isSelectionMode) => isSelectionMode ? ListViewSelectionMode.Multiple : ListViewSelectionMode.None; public static string BoolToSelectionModeText(bool isSelectionMode) => isSelectionMode ? Translator.Buttons_Cancel : Translator.Buttons_Multiselect; - public static Microsoft.UI.Xaml.Media.Imaging.BitmapImage Base64ToBitmapImage(string base64String) + public static Microsoft.UI.Xaml.Media.Imaging.BitmapImage? Base64ToBitmapImage(string base64String) { if (string.IsNullOrEmpty(base64String)) return null; @@ -154,7 +154,7 @@ public static class XamlHelpers if (groupObject is string stringObject) return stringObject; - object dateObject = null; + object? dateObject = null; // From regular mail header template if (groupObject is DateTime groupedDate) @@ -180,7 +180,7 @@ public static class XamlHelpers } else - return dateObject.ToString(); + return dateObject.ToString() ?? string.Empty; } return Translator.UnknownDateHeader; @@ -321,6 +321,10 @@ public static class XamlHelpers "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>" + "" + pathMarkup + ""; var path = XamlReader.Load(xaml) as Microsoft.UI.Xaml.Shapes.Path; + if (path?.Data == null) + { + return new PathGeometry(); + } Geometry geometry = path.Data; path.Data = null; diff --git a/Wino.Mail.WinUI/Models/PrintDialogViewModel.cs b/Wino.Mail.WinUI/Models/PrintDialogViewModel.cs index 8b18e0de..5f4498ac 100644 --- a/Wino.Mail.WinUI/Models/PrintDialogViewModel.cs +++ b/Wino.Mail.WinUI/Models/PrintDialogViewModel.cs @@ -17,7 +17,7 @@ public class PrintDialogViewModel : INotifyPropertyChanged private bool _isCustomPageRange = false; private WebView2PrintSettingsModel _printSettings = new(); - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; public PrintDialogViewModel() { @@ -208,7 +208,7 @@ public class PrintDialogViewModel : INotifyPropertyChanged /// Initializes the dialog with the provided print settings. /// /// The initial print settings. - public void Initialize(WebView2PrintSettingsModel printSettings = null) + public void Initialize(WebView2PrintSettingsModel printSettings = default!) { if (printSettings != null) { @@ -237,7 +237,7 @@ public class PrintDialogViewModel : INotifyPropertyChanged } } - private void OnPrintSettingsChanged(object sender, PropertyChangedEventArgs e) + private void OnPrintSettingsChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(WebView2PrintSettingsModel.ScaleFactor)) { @@ -273,4 +273,4 @@ public class PrintDialogViewModel : INotifyPropertyChanged { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } -} \ No newline at end of file +} diff --git a/Wino.Mail.WinUI/Selectors/AppThemePreviewTemplateSelector.cs b/Wino.Mail.WinUI/Selectors/AppThemePreviewTemplateSelector.cs index 487c9670..71c02fc5 100644 --- a/Wino.Mail.WinUI/Selectors/AppThemePreviewTemplateSelector.cs +++ b/Wino.Mail.WinUI/Selectors/AppThemePreviewTemplateSelector.cs @@ -6,9 +6,9 @@ namespace Wino.Mail.WinUI.Selectors; public partial class AppThemePreviewTemplateSelector : DataTemplateSelector { - public DataTemplate SystemThemeTemplate { get; set; } - public DataTemplate PreDefinedThemeTemplate { get; set; } - public DataTemplate CustomAppTemplate { get; set; } + public DataTemplate SystemThemeTemplate { get; set; } = null!; + public DataTemplate PreDefinedThemeTemplate { get; set; } = null!; + public DataTemplate CustomAppTemplate { get; set; } = null!; protected override DataTemplate SelectTemplateCore(object item) { @@ -19,6 +19,6 @@ public partial class AppThemePreviewTemplateSelector : DataTemplateSelector else if (item is CustomAppTheme) return CustomAppTemplate; - return base.SelectTemplateCore(item); + return base.SelectTemplateCore(item) ?? SystemThemeTemplate; } } diff --git a/Wino.Mail.WinUI/Selectors/CalendarItemShowAsStripeTemplateSelector.cs b/Wino.Mail.WinUI/Selectors/CalendarItemShowAsStripeTemplateSelector.cs index e24fe86b..a492eda4 100644 --- a/Wino.Mail.WinUI/Selectors/CalendarItemShowAsStripeTemplateSelector.cs +++ b/Wino.Mail.WinUI/Selectors/CalendarItemShowAsStripeTemplateSelector.cs @@ -10,11 +10,11 @@ namespace Wino.Selectors; /// public partial class CalendarItemShowAsStripeTemplateSelector : DataTemplateSelector { - public DataTemplate FreeTemplate { get; set; } - public DataTemplate TentativeTemplate { get; set; } - public DataTemplate BusyTemplate { get; set; } - public DataTemplate OutOfOfficeTemplate { get; set; } - public DataTemplate WorkingElsewhereTemplate { get; set; } + public DataTemplate FreeTemplate { get; set; } = null!; + public DataTemplate TentativeTemplate { get; set; } = null!; + public DataTemplate BusyTemplate { get; set; } = null!; + public DataTemplate OutOfOfficeTemplate { get; set; } = null!; + public DataTemplate WorkingElsewhereTemplate { get; set; } = null!; protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { @@ -31,6 +31,6 @@ public partial class CalendarItemShowAsStripeTemplateSelector : DataTemplateSele }; } - return base.SelectTemplateCore(item, container); + return base.SelectTemplateCore(item, container) ?? BusyTemplate; } } diff --git a/Wino.Mail.WinUI/Selectors/CustomWinoMessageDialogIconSelector.cs b/Wino.Mail.WinUI/Selectors/CustomWinoMessageDialogIconSelector.cs index 63555836..fc4403fc 100644 --- a/Wino.Mail.WinUI/Selectors/CustomWinoMessageDialogIconSelector.cs +++ b/Wino.Mail.WinUI/Selectors/CustomWinoMessageDialogIconSelector.cs @@ -7,14 +7,14 @@ namespace Wino.Mail.WinUI.Selectors; public partial class CustomWinoMessageDialogIconSelector : DataTemplateSelector { - public DataTemplate InfoIconTemplate { get; set; } - public DataTemplate WarningIconTemplate { get; set; } - public DataTemplate QuestionIconTemplate { get; set; } - public DataTemplate ErrorIconTemplate { get; set; } + public DataTemplate InfoIconTemplate { get; set; } = null!; + public DataTemplate WarningIconTemplate { get; set; } = null!; + public DataTemplate QuestionIconTemplate { get; set; } = null!; + public DataTemplate ErrorIconTemplate { get; set; } = null!; protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { - if (item == null) return null; + if (item == null) return InfoIconTemplate; if (item is WinoCustomMessageDialogIcon icon) { @@ -32,6 +32,6 @@ public partial class CustomWinoMessageDialogIconSelector : DataTemplateSelector throw new Exception("Unknown custom message dialog icon."); } } - return base.SelectTemplateCore(item, container); + return base.SelectTemplateCore(item, container) ?? InfoIconTemplate; } } diff --git a/Wino.Mail.WinUI/Selectors/FileAttachmentTypeSelector.cs b/Wino.Mail.WinUI/Selectors/FileAttachmentTypeSelector.cs index 71a588fe..0bff79bc 100644 --- a/Wino.Mail.WinUI/Selectors/FileAttachmentTypeSelector.cs +++ b/Wino.Mail.WinUI/Selectors/FileAttachmentTypeSelector.cs @@ -6,16 +6,16 @@ namespace Wino.Mail.WinUI.Selectors; public partial class FileAttachmentTypeSelector : DataTemplateSelector { - public DataTemplate None { get; set; } - public DataTemplate Executable { get; set; } - public DataTemplate Image { get; set; } - public DataTemplate Audio { get; set; } - public DataTemplate Video { get; set; } - public DataTemplate PDF { get; set; } - public DataTemplate HTML { get; set; } - public DataTemplate RarArchive { get; set; } - public DataTemplate Archive { get; set; } - public DataTemplate Other { get; set; } + public DataTemplate None { get; set; } = null!; + public DataTemplate Executable { get; set; } = null!; + public DataTemplate Image { get; set; } = null!; + public DataTemplate Audio { get; set; } = null!; + public DataTemplate Video { get; set; } = null!; + public DataTemplate PDF { get; set; } = null!; + public DataTemplate HTML { get; set; } = null!; + public DataTemplate RarArchive { get; set; } = null!; + public DataTemplate Archive { get; set; } = null!; + public DataTemplate Other { get; set; } = null!; protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { diff --git a/Wino.Mail.WinUI/Selectors/NavigationMenuTemplateSelector.cs b/Wino.Mail.WinUI/Selectors/NavigationMenuTemplateSelector.cs index 492977c0..69864a9e 100644 --- a/Wino.Mail.WinUI/Selectors/NavigationMenuTemplateSelector.cs +++ b/Wino.Mail.WinUI/Selectors/NavigationMenuTemplateSelector.cs @@ -6,23 +6,23 @@ namespace Wino.Mail.WinUI.Selectors; public partial class NavigationMenuTemplateSelector : DataTemplateSelector { - public DataTemplate MenuItemTemplate { get; set; } - public DataTemplate ContactsMenuItemTemplate { get; set; } - public DataTemplate AccountManagementTemplate { get; set; } - public DataTemplate ClickableAccountMenuTemplate { get; set; } - public DataTemplate MergedAccountTemplate { get; set; } - public DataTemplate MergedAccountFolderTemplate { get; set; } - public DataTemplate MergedAccountMoreExpansionItemTemplate { get; set; } - public DataTemplate FolderMenuTemplate { get; set; } - public DataTemplate SettingsItemTemplate { get; set; } - public DataTemplate MoreItemsFolderTemplate { get; set; } - public DataTemplate RatingItemTemplate { get; set; } - public DataTemplate CreateNewFolderTemplate { get; set; } - public DataTemplate SeperatorTemplate { get; set; } - public DataTemplate NewMailTemplate { get; set; } - public DataTemplate CategoryItemsTemplate { get; set; } - public DataTemplate FixAuthenticationIssueTemplate { get; set; } - public DataTemplate FixMissingFolderConfigTemplate { get; set; } + public DataTemplate MenuItemTemplate { get; set; } = null!; + public DataTemplate ContactsMenuItemTemplate { get; set; } = null!; + public DataTemplate AccountManagementTemplate { get; set; } = null!; + public DataTemplate ClickableAccountMenuTemplate { get; set; } = null!; + public DataTemplate MergedAccountTemplate { get; set; } = null!; + public DataTemplate MergedAccountFolderTemplate { get; set; } = null!; + public DataTemplate MergedAccountMoreExpansionItemTemplate { get; set; } = null!; + public DataTemplate FolderMenuTemplate { get; set; } = null!; + public DataTemplate SettingsItemTemplate { get; set; } = null!; + public DataTemplate MoreItemsFolderTemplate { get; set; } = null!; + public DataTemplate RatingItemTemplate { get; set; } = null!; + public DataTemplate CreateNewFolderTemplate { get; set; } = null!; + public DataTemplate SeperatorTemplate { get; set; } = null!; + public DataTemplate NewMailTemplate { get; set; } = null!; + public DataTemplate CategoryItemsTemplate { get; set; } = null!; + public DataTemplate FixAuthenticationIssueTemplate { get; set; } = null!; + public DataTemplate FixMissingFolderConfigTemplate { get; set; } = null!; protected override DataTemplate SelectTemplateCore(object item) { @@ -34,7 +34,7 @@ public partial class NavigationMenuTemplateSelector : DataTemplateSelector return SettingsItemTemplate; else if (item is SeperatorItem) return SeperatorTemplate; - else if (item is AccountMenuItem accountMenuItem) + else if (item is AccountMenuItem) // Merged inbox account menu items must be nested. return ClickableAccountMenuTemplate; else if (item is ManageAccountsMenuItem) @@ -52,10 +52,6 @@ public partial class NavigationMenuTemplateSelector : DataTemplateSelector else if (item is FixAccountIssuesMenuItem fixAccountIssuesMenuItem) return fixAccountIssuesMenuItem.Account.AttentionReason == Wino.Core.Domain.Enums.AccountAttentionReason.MissingSystemFolderConfiguration ? FixMissingFolderConfigTemplate : FixAuthenticationIssueTemplate; - else - { - var type = item.GetType(); - return null; - } + return MenuItemTemplate; } } diff --git a/Wino.Mail.WinUI/Selectors/RsvpStatusIconTemplateSelector.cs b/Wino.Mail.WinUI/Selectors/RsvpStatusIconTemplateSelector.cs index fd07abd1..9e60f18a 100644 --- a/Wino.Mail.WinUI/Selectors/RsvpStatusIconTemplateSelector.cs +++ b/Wino.Mail.WinUI/Selectors/RsvpStatusIconTemplateSelector.cs @@ -6,10 +6,10 @@ namespace Wino.Mail.WinUI.Selectors; public partial class RsvpStatusIconTemplateSelector : DataTemplateSelector { - public DataTemplate NotRespondedTemplate { get; set; } - public DataTemplate ConfirmedTemplate { get; set; } - public DataTemplate TentativeTemplate { get; set; } - public DataTemplate CancelledTemplate { get; set; } + public DataTemplate NotRespondedTemplate { get; set; } = null!; + public DataTemplate ConfirmedTemplate { get; set; } = null!; + public DataTemplate TentativeTemplate { get; set; } = null!; + public DataTemplate CancelledTemplate { get; set; } = null!; protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { @@ -25,6 +25,6 @@ public partial class RsvpStatusIconTemplateSelector : DataTemplateSelector }; } - return base.SelectTemplateCore(item, container); + return base.SelectTemplateCore(item, container) ?? NotRespondedTemplate; } } diff --git a/Wino.Mail.WinUI/Selectors/WinoCalendarItemTemplateSelector.cs b/Wino.Mail.WinUI/Selectors/WinoCalendarItemTemplateSelector.cs index 84f0d336..3f8fc4f5 100644 --- a/Wino.Mail.WinUI/Selectors/WinoCalendarItemTemplateSelector.cs +++ b/Wino.Mail.WinUI/Selectors/WinoCalendarItemTemplateSelector.cs @@ -8,8 +8,8 @@ public partial class WinoCalendarItemTemplateSelector : DataTemplateSelector { public CalendarDisplayType DisplayType { get; set; } - public DataTemplate DayWeekWorkWeekTemplate { get; set; } - public DataTemplate MonthlyTemplate { get; set; } + public DataTemplate DayWeekWorkWeekTemplate { get; set; } = null!; + public DataTemplate MonthlyTemplate { get; set; } = null!; protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) @@ -26,6 +26,6 @@ public partial class WinoCalendarItemTemplateSelector : DataTemplateSelector break; } - return base.SelectTemplateCore(item, container); + return base.SelectTemplateCore(item, container) ?? DayWeekWorkWeekTemplate; } } diff --git a/Wino.Mail.WinUI/Services/ApplicationResourceManager.cs b/Wino.Mail.WinUI/Services/ApplicationResourceManager.cs index 4c11f2e8..aea5d5fd 100644 --- a/Wino.Mail.WinUI/Services/ApplicationResourceManager.cs +++ b/Wino.Mail.WinUI/Services/ApplicationResourceManager.cs @@ -16,7 +16,7 @@ public class ApplicationResourceManager : IApplicationResourceManager WinoApplication.Current.Resources.ContainsKey(resourceKey); public ResourceDictionary GetLastResource() - => WinoApplication.Current.Resources.MergedDictionaries.LastOrDefault(); + => WinoApplication.Current.Resources.MergedDictionaries.LastOrDefault()!; public void ReplaceResource(string resourceKey, object resource) => WinoApplication.Current.Resources[resourceKey] = resource; diff --git a/Wino.Mail.WinUI/Services/ConfigurationService.cs b/Wino.Mail.WinUI/Services/ConfigurationService.cs index acd0ee2e..afdc47c1 100644 --- a/Wino.Mail.WinUI/Services/ConfigurationService.cs +++ b/Wino.Mail.WinUI/Services/ConfigurationService.cs @@ -9,10 +9,10 @@ namespace Wino.Mail.WinUI.Services; public class ConfigurationService : IConfigurationService { - public T Get(string key, T defaultValue = default) + public T Get(string key, T defaultValue = default!) => GetInternal(key, ApplicationData.Current.LocalSettings.Values, defaultValue); - public T GetRoaming(string key, T defaultValue = default) + public T GetRoaming(string key, T defaultValue = default!) => GetInternal(key, ApplicationData.Current.RoamingSettings.Values, defaultValue); public void Set(string key, object value) @@ -21,11 +21,13 @@ public class ConfigurationService : IConfigurationService public void SetRoaming(string key, object value) => SetInternal(key, value, ApplicationData.Current.RoamingSettings.Values); - private static T GetInternal(string key, IPropertySet collection, T defaultValue = default) + private static T GetInternal(string key, IPropertySet collection, T defaultValue = default!) { - if (collection.TryGetValue(key, out object value)) + if (collection.TryGetValue(key, out object? value)) { var stringValue = value?.ToString(); + if (string.IsNullOrWhiteSpace(stringValue)) + return defaultValue; if (typeof(T).IsEnum) return (T)Enum.Parse(typeof(T), stringValue); @@ -40,7 +42,8 @@ public class ConfigurationService : IConfigurationService return (T)(object)TimeSpan.Parse(stringValue); } - return (T)Convert.ChangeType(stringValue, typeof(T)); + var converted = Convert.ChangeType(stringValue, typeof(T)); + return converted is T typed ? typed : defaultValue; } return defaultValue; diff --git a/Wino.Mail.WinUI/Services/DialogService.cs b/Wino.Mail.WinUI/Services/DialogService.cs index 2b342435..14ca7585 100644 --- a/Wino.Mail.WinUI/Services/DialogService.cs +++ b/Wino.Mail.WinUI/Services/DialogService.cs @@ -119,7 +119,7 @@ public class DialogService : DialogServiceBase, IMailDialogService await HandleDialogPresentationAsync(accountPicker); - return accountPicker.PickedAccount; + return accountPicker.PickedAccount ?? null!; } public async Task ShowSignatureEditorDialog(AccountSignature? signatureModel = null) diff --git a/Wino.Mail.WinUI/Services/DialogServiceBase.cs b/Wino.Mail.WinUI/Services/DialogServiceBase.cs index f4ce9cb4..74b7d081 100644 --- a/Wino.Mail.WinUI/Services/DialogServiceBase.cs +++ b/Wino.Mail.WinUI/Services/DialogServiceBase.cs @@ -40,7 +40,7 @@ public class DialogServiceBase : IDialogServiceBase ApplicationResourceManager = applicationResourceManager; } - protected XamlRoot GetXamlRoot() + protected XamlRoot? GetXamlRoot() { return WinoApplication.MainWindow?.Content?.XamlRoot; } @@ -54,7 +54,10 @@ public class DialogServiceBase : IDialogServiceBase picker.FileTypeFilter.Add("*"); - nint windowHandle = WindowNative.GetWindowHandle(WinoApplication.MainWindow); + var mainWindow = WinoApplication.MainWindow; + if (mainWindow == null) return string.Empty; + + nint windowHandle = WindowNative.GetWindowHandle(mainWindow); InitializeWithWindow.Initialize(picker, windowHandle); var folder = await picker.PickSingleFolderAsync(); @@ -94,7 +97,10 @@ public class DialogServiceBase : IDialogServiceBase picker.FileTypeFilter.Add(filter.ToString()); } - nint windowHandle = WindowNative.GetWindowHandle(WinoApplication.MainWindow); + var mainWindow = WinoApplication.MainWindow; + if (mainWindow == null) return returnList; + + nint windowHandle = WindowNative.GetWindowHandle(mainWindow); InitializeWithWindow.Initialize(picker, windowHandle); var files = await picker.PickMultipleFilesAsync(); @@ -111,7 +117,7 @@ public class DialogServiceBase : IDialogServiceBase return returnList; } - private async Task PickFileAsync(params object[] typeFilters) + private async Task PickFileAsync(params object[] typeFilters) { var picker = new FileOpenPicker { @@ -123,7 +129,10 @@ public class DialogServiceBase : IDialogServiceBase picker.FileTypeFilter.Add(filter.ToString()); } - nint windowHandle = WindowNative.GetWindowHandle(WinoApplication.MainWindow); + var mainWindow = WinoApplication.MainWindow; + if (mainWindow == null) return null; + + nint windowHandle = WindowNative.GetWindowHandle(mainWindow); InitializeWithWindow.Initialize(picker, windowHandle); var file = await picker.PickSingleFileAsync(); @@ -174,7 +183,7 @@ public class DialogServiceBase : IDialogServiceBase if (isDontAskEnabled && ConfigurationService.Get(dontAskAgainConfigurationKey, false)) return false; - var informationContainer = new CustomMessageDialogInformationContainer(title, description, icon.Value, isDontAskEnabled); + var informationContainer = new CustomMessageDialogInformationContainer(title, description, icon ?? WinoCustomMessageDialogIcon.Information, isDontAskEnabled); var dialog = new ContentDialog { @@ -270,7 +279,10 @@ public class DialogServiceBase : IDialogServiceBase picker.FileTypeFilter.Add("*"); - nint windowHandle = WindowNative.GetWindowHandle(WinoApplication.MainWindow); + var mainWindow = WinoApplication.MainWindow; + if (mainWindow == null) return string.Empty; + + nint windowHandle = WindowNative.GetWindowHandle(mainWindow); InitializeWithWindow.Initialize(picker, windowHandle); var pickedFolder = await picker.PickSingleFolderAsync(); @@ -307,10 +319,10 @@ public class DialogServiceBase : IDialogServiceBase await HandleDialogPresentationAsync(dialog); - return dialog.Result; + return dialog.Result ?? null!; } - public async Task ShowPrintDialogAsync(WebView2PrintSettingsModel initialSettings = null) + public async Task ShowPrintDialogAsync(WebView2PrintSettingsModel initialSettings = default!) { try { @@ -334,13 +346,13 @@ public class DialogServiceBase : IDialogServiceBase // Return the settings if user clicked Print, otherwise null return result == ContentDialogResult.Primary ? dialog.PrintSettings - : null; + : null!; } catch (Exception ex) { // Log the exception if logging is available Log.Error(ex, "Error showing print dialog"); - return null; + return null!; } } } diff --git a/Wino.Mail.WinUI/Services/NativeAppService.cs b/Wino.Mail.WinUI/Services/NativeAppService.cs index bf030f8d..aa3b665a 100644 --- a/Wino.Mail.WinUI/Services/NativeAppService.cs +++ b/Wino.Mail.WinUI/Services/NativeAppService.cs @@ -16,10 +16,10 @@ namespace Wino.Services; public class NativeAppService : INativeAppService { - private string _mimeMessagesFolder; - private string _editorBundlePath; + private string _mimeMessagesFolder = string.Empty; + private string _editorBundlePath = string.Empty; - public Func GetCoreWindowHwnd { get; set; } + public Func GetCoreWindowHwnd { get; set; } = static () => IntPtr.Zero; public string GetWebAuthenticationBrokerUri() { diff --git a/Wino.Mail.WinUI/Services/NavigationService.cs b/Wino.Mail.WinUI/Services/NavigationService.cs index 71bde73e..0597ab32 100644 --- a/Wino.Mail.WinUI/Services/NavigationService.cs +++ b/Wino.Mail.WinUI/Services/NavigationService.cs @@ -100,7 +100,10 @@ public class NavigationService : NavigationServiceBase, INavigationService if (frameType == NavigationReferenceFrame.ShellFrame) return shellWindow.GetMainFrame(); - return WinoVisualTreeHelper.GetChildObject(mainFrame.Content as UIElement, frameType.ToString()); + var contentRoot = mainFrame.Content as UIElement; + if (contentRoot == null) return mainFrame; + + return WinoVisualTreeHelper.GetChildObject(contentRoot, frameType.ToString()) ?? mainFrame; } public bool ChangeApplicationMode(WinoApplicationMode mode) diff --git a/Wino.Mail.WinUI/Services/NavigationServiceBase.cs b/Wino.Mail.WinUI/Services/NavigationServiceBase.cs index 21f9d2c8..b52c3190 100644 --- a/Wino.Mail.WinUI/Services/NavigationServiceBase.cs +++ b/Wino.Mail.WinUI/Services/NavigationServiceBase.cs @@ -17,7 +17,7 @@ public class NavigationServiceBase }; } - public Type GetCurrentFrameType(ref Frame _frame) + public Type? GetCurrentFrameType(ref Frame _frame) { if (_frame != null && _frame.Content != null) return _frame.Content.GetType(); diff --git a/Wino.Mail.WinUI/Services/NewThemeService.cs b/Wino.Mail.WinUI/Services/NewThemeService.cs index 4e4186d9..6de49e12 100644 --- a/Wino.Mail.WinUI/Services/NewThemeService.cs +++ b/Wino.Mail.WinUI/Services/NewThemeService.cs @@ -45,9 +45,9 @@ public class NewThemeService : INewThemeService private static string _snowflakeThemeId = "e143ddde-2e28-4846-9d98-dad63d6505f1"; private static string _gardenThemeId = "698e4466-f88c-4799-9c61-f0ea1308ed49"; - public event EventHandler ElementThemeChanged; - public event EventHandler AccentColorChanged; - public event EventHandler BackdropChanged; + public event EventHandler? ElementThemeChanged; + public event EventHandler? AccentColorChanged; + public event EventHandler? BackdropChanged; private const string AccentColorKey = nameof(AccentColorKey); private const string CurrentApplicationThemeKey = nameof(CurrentApplicationThemeKey); @@ -125,7 +125,7 @@ public class NewThemeService : INewThemeService } } - private string accentColor; + private string accentColor = string.Empty; public string AccentColor { @@ -218,7 +218,7 @@ public class NewThemeService : INewThemeService try { - Microsoft.UI.Xaml.Media.SystemBackdrop backdrop = backdropType switch + Microsoft.UI.Xaml.Media.SystemBackdrop? backdrop = backdropType switch { WindowBackdropType.Mica => new MicaBackdrop() { Kind = Microsoft.UI.Composition.SystemBackdrops.MicaKind.Base }, WindowBackdropType.MicaAlt => new MicaBackdrop() { Kind = Microsoft.UI.Composition.SystemBackdrops.MicaKind.BaseAlt }, @@ -385,7 +385,7 @@ public class NewThemeService : INewThemeService return; } - AppThemeBase applyingTheme = null; + AppThemeBase? applyingTheme = null; var controlThemeList = new List(preDefinedThemes); @@ -416,13 +416,19 @@ public class NewThemeService : INewThemeService } } + if (applyingTheme == null) + { + Debug.WriteLine($"Theme with ID {currentApplicationThemeId} not found, skipping theme application"); + return; + } + try { var existingThemeDictionary = _applicationResourceManager.GetLastResource(); - if (existingThemeDictionary != null && existingThemeDictionary.TryGetValue("ThemeName", out object themeNameString)) + if (existingThemeDictionary != null && existingThemeDictionary.TryGetValue("ThemeName", out object? themeNameString)) { - var themeName = themeNameString.ToString(); + var themeName = themeNameString?.ToString(); // Applying different theme. if (themeName != applyingTheme.ThemeName) @@ -430,6 +436,10 @@ public class NewThemeService : INewThemeService var resourceDictionaryContent = await applyingTheme.GetThemeResourceDictionaryContentAsync(); var resourceDictionary = XamlReader.Load(resourceDictionaryContent) as ResourceDictionary; + if (resourceDictionary == null) + { + return; + } // Custom themes require special attention for background image because // they share the same base theme resource dictionary. @@ -561,7 +571,7 @@ public class NewThemeService : INewThemeService return results; } - private async Task GetCustomMetadataAsync(IStorageFile file) + private async Task GetCustomMetadataAsync(IStorageFile file) { var fileContent = await FileIO.ReadTextAsync(file); diff --git a/Wino.Mail.WinUI/Services/NotificationBuilder.cs b/Wino.Mail.WinUI/Services/NotificationBuilder.cs index 8c959082..3221452d 100644 --- a/Wino.Mail.WinUI/Services/NotificationBuilder.cs +++ b/Wino.Mail.WinUI/Services/NotificationBuilder.cs @@ -215,7 +215,12 @@ public class NotificationBuilder : INotificationBuilder XmlDocument badgeXml = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber); // Set the value of the badge in the XML to our number - XmlElement badgeElement = badgeXml.SelectSingleNode("/badge") as XmlElement; + XmlElement? badgeElement = badgeXml.SelectSingleNode("/badge") as XmlElement; + if (badgeElement == null) + { + badgeUpdater.Clear(); + return; + } badgeElement.SetAttribute("value", totalUnreadCount.ToString()); // Create the badge notification diff --git a/Wino.Mail.WinUI/Services/PreferencesService.cs b/Wino.Mail.WinUI/Services/PreferencesService.cs index bbdc8c1f..9f952022 100644 --- a/Wino.Mail.WinUI/Services/PreferencesService.cs +++ b/Wino.Mail.WinUI/Services/PreferencesService.cs @@ -17,20 +17,20 @@ public class PreferencesService(IConfigurationService configurationService) : Ob { private readonly IConfigurationService _configurationService = configurationService; - public event EventHandler PreferenceChanged; + public event EventHandler? PreferenceChanged; protected override void OnPropertyChanged(PropertyChangedEventArgs e) { base.OnPropertyChanged(e); - PreferenceChanged?.Invoke(this, e.PropertyName); + PreferenceChanged?.Invoke(this, e.PropertyName ?? string.Empty); } - private void SaveProperty(string propertyName, object value) => _configurationService.Set(propertyName, value); + private void SaveProperty(string propertyName, object? value) => _configurationService.Set(propertyName, value ?? string.Empty); - private void SetPropertyAndSave(string propertyName, object value) + private void SetPropertyAndSave(string propertyName, object? value) { - _configurationService.Set(propertyName, value); + _configurationService.Set(propertyName, value ?? string.Empty); OnPropertyChanged(propertyName); Debug.WriteLine($"PreferencesService -> {propertyName}:{value?.ToString()}"); diff --git a/Wino.Mail.WinUI/Services/PrintService.cs b/Wino.Mail.WinUI/Services/PrintService.cs index b332b8a8..513ee582 100644 --- a/Wino.Mail.WinUI/Services/PrintService.cs +++ b/Wino.Mail.WinUI/Services/PrintService.cs @@ -24,10 +24,10 @@ namespace Wino.Mail.WinUI.Services; public class PrintService : IPrintService { - private TaskCompletionSource _taskCompletionSource; - private CanvasPrintDocument printDocument; - private PrintTask printTask; - private PdfDocument pdfDocument; + private TaskCompletionSource? _taskCompletionSource; + private CanvasPrintDocument? printDocument; + private PrintTask? printTask; + private PdfDocument? pdfDocument; private List bitmaps = new(); private Vector2 largestBitmap; @@ -41,7 +41,7 @@ public class PrintService : IPrintService private int bitmapsPerPage; private int pageCount = -1; - private PrintInformation _currentPrintInformation; + private PrintInformation? _currentPrintInformation; public async Task PrintPdfFileAsync(string pdfFilePath, string printTitle) { @@ -125,6 +125,9 @@ public class PrintService : IPrintService printTask = args.Request.CreatePrintTask(_currentPrintInformation.PDFTitle, (createPrintTaskArgs) => { + if (printDocument == null) + return; + createPrintTaskArgs.SetSource(printDocument); }); @@ -191,6 +194,9 @@ public class PrintService : IPrintService private async Task LoadPDFPageBitmapsAsync(CanvasPrintDocument sender) { + if (pdfDocument == null) + return; + ClearBitmaps(); bitmaps ??= new List(); @@ -226,6 +232,9 @@ public class PrintService : IPrintService { var detailedOptions = PrintTaskOptionDetails.GetFromPrintTaskOptions(args.PrintTaskOptions); + if (pdfDocument == null) + return; + int pageCountToPrint = (int)pdfDocument.PageCount; for (uint i = 1; i <= pageCountToPrint; ++i) @@ -239,7 +248,7 @@ public class PrintService : IPrintService private void DrawPdfPage(CanvasPrintDocument sender, CanvasDrawingSession ds, uint pageNumber) { - if (bitmaps?.Count == 0) return; + if (bitmaps.Count == 0) return; var cellAcross = new Vector2(cellSize.X, 0); var cellDown = new Vector2(0, cellSize.Y); diff --git a/Wino.Mail.WinUI/Services/SmimeCertificateService.cs b/Wino.Mail.WinUI/Services/SmimeCertificateService.cs index 45351659..ec6c4801 100644 --- a/Wino.Mail.WinUI/Services/SmimeCertificateService.cs +++ b/Wino.Mail.WinUI/Services/SmimeCertificateService.cs @@ -17,7 +17,7 @@ public class SmimeCertificateService : ISmimeCertificateService /// private key and at least one extension. The store is opened in read-only mode. /// An enumerable collection of objects representing the personal certificates that /// meet the specified criteria. If no matching certificates are found, the collection will be empty. - public IEnumerable GetCertificates(StoreName storeName = StoreName.My, StoreLocation storeLocation = StoreLocation.CurrentUser, string emailAddress = null) + public IEnumerable GetCertificates(StoreName storeName = StoreName.My, StoreLocation storeLocation = StoreLocation.CurrentUser, string? emailAddress = null) { using var store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadOnly); @@ -26,7 +26,7 @@ public class SmimeCertificateService : ISmimeCertificateService } - public void ImportCertificate(string fileExtension, byte[] rawData, string password = null, StoreName storeName = StoreName.My, StoreLocation storeLocation = StoreLocation.CurrentUser) + public void ImportCertificate(string fileExtension, byte[] rawData, string? password = null, StoreName storeName = StoreName.My, StoreLocation storeLocation = StoreLocation.CurrentUser) { X509Certificate2Collection collection = []; diff --git a/Wino.Mail.WinUI/Services/StatePersistenceService.cs b/Wino.Mail.WinUI/Services/StatePersistenceService.cs index 155d1386..de50a3ad 100644 --- a/Wino.Mail.WinUI/Services/StatePersistenceService.cs +++ b/Wino.Mail.WinUI/Services/StatePersistenceService.cs @@ -198,7 +198,13 @@ public class StatePersistenceService : ObservableObject, IStatePersistanceServic } } - private void UpdateAppCoreWindowTitle() => WinoApplication.MainWindow.Title = CoreWindowTitle; + private void UpdateAppCoreWindowTitle() + { + if (WinoApplication.MainWindow != null) + { + WinoApplication.MainWindow.Title = CoreWindowTitle; + } + } private static CalendarDisplayType EnsureValidCalendarDisplayType(CalendarDisplayType displayType) { diff --git a/Wino.Mail.WinUI/Services/ThumbnailService.cs b/Wino.Mail.WinUI/Services/ThumbnailService.cs index b9e4c3f9..de3a402a 100644 --- a/Wino.Mail.WinUI/Services/ThumbnailService.cs +++ b/Wino.Mail.WinUI/Services/ThumbnailService.cs @@ -21,7 +21,7 @@ public class ThumbnailService(IPreferencesService preferencesService, IDatabaseS private static readonly HttpClient _httpClient = new(); private bool _isInitialized = false; - private ConcurrentDictionary _cache; + private ConcurrentDictionary _cache = []; private readonly ConcurrentDictionary _requests = []; private static readonly List _excludedFaviconDomains = [ @@ -43,7 +43,7 @@ public class ThumbnailService(IPreferencesService preferencesService, IDatabaseS "rediffmail.com" ]; - public async ValueTask GetThumbnailAsync(string email, bool awaitLoad = false) + public async ValueTask GetThumbnailAsync(string email, bool awaitLoad = false) { if (string.IsNullOrWhiteSpace(email)) return null; @@ -55,8 +55,8 @@ public class ThumbnailService(IPreferencesService preferencesService, IDatabaseS { var thumbnailsList = await _databaseService.Connection.Table().ToListAsync(); - _cache = new ConcurrentDictionary( - thumbnailsList.ToDictionary(x => x.Domain, x => (x.Gravatar, x.Favicon))); + _cache = new ConcurrentDictionary( + thumbnailsList.ToDictionary(x => x.Domain, x => ((string?)x.Gravatar, (string?)x.Favicon))); _isInitialized = true; } @@ -84,7 +84,7 @@ public class ThumbnailService(IPreferencesService preferencesService, IDatabaseS await _databaseService.Connection.DeleteAllAsync(); } - private async ValueTask<(string gravatar, string favicon)> GetThumbnailInternal(string email, bool awaitLoad) + private async ValueTask<(string? gravatar, string? favicon)> GetThumbnailInternal(string email, bool awaitLoad) { if (_cache.TryGetValue(email, out var cached)) return cached; @@ -136,7 +136,7 @@ public class ThumbnailService(IPreferencesService preferencesService, IDatabaseS WeakReferenceMessenger.Default.Send(new ThumbnailAdded(email)); } - private static async Task GetGravatarBase64(string email) + private static async Task GetGravatarBase64(string email) { try { @@ -156,7 +156,7 @@ public class ThumbnailService(IPreferencesService preferencesService, IDatabaseS return null; } - private static async Task GetFaviconBase64(string email) + private static async Task GetFaviconBase64(string email) { try { diff --git a/Wino.Mail.WinUI/Views/Calendar/CalendarPage.xaml.cs b/Wino.Mail.WinUI/Views/Calendar/CalendarPage.xaml.cs index caf18b1d..53962966 100644 --- a/Wino.Mail.WinUI/Views/Calendar/CalendarPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/Calendar/CalendarPage.xaml.cs @@ -26,7 +26,7 @@ public sealed partial class CalendarPage : CalendarPageAbstract, ViewModel.DetailsShowCalendarItemChanged += CalendarItemDetailContextChanged; } - private void CalendarItemDetailContextChanged(object sender, EventArgs e) + private void CalendarItemDetailContextChanged(object? sender, EventArgs e) { if (ViewModel.DisplayDetailsCalendarItemViewModel != null) { diff --git a/Wino.Mail.WinUI/Views/Settings/AliasManagementPage.xaml.cs b/Wino.Mail.WinUI/Views/Settings/AliasManagementPage.xaml.cs index 2310f467..b3b89fb9 100644 --- a/Wino.Mail.WinUI/Views/Settings/AliasManagementPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/Settings/AliasManagementPage.xaml.cs @@ -37,7 +37,7 @@ public sealed partial class AliasManagementPage : AliasManagementPageAbstract } } - private static (MailAccountAlias alias, X509Certificate2 cert) GetAliasAndSelectedCertificateForCombobox(object sender) + private static (MailAccountAlias? alias, X509Certificate2? cert) GetAliasAndSelectedCertificateForCombobox(object sender) { var comboBox = sender as ComboBox; var alias = comboBox?.DataContext as MailAccountAlias; diff --git a/Wino.Mail.WinUI/Views/Settings/ContactsPage.xaml.cs b/Wino.Mail.WinUI/Views/Settings/ContactsPage.xaml.cs index 58f1a75d..50d0259a 100644 --- a/Wino.Mail.WinUI/Views/Settings/ContactsPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/Settings/ContactsPage.xaml.cs @@ -89,7 +89,7 @@ public sealed partial class ContactsPage : ContactsPageAbstract ClearSelection(); } - private void ViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) + private void ViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(ContactsPageViewModel.IsSelectionMode) && !ViewModel.IsSelectionMode) { diff --git a/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj b/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj index 7d4b13af..1c7628cf 100644 --- a/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj +++ b/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj @@ -5,6 +5,7 @@ 10.0.17763.0 Wino.Mail.WinUI app.manifest + x64 x86;x64;ARM64 win-x86;win-x64;win-arm64 win-$(Platform).pubxml @@ -15,7 +16,8 @@ False True - False + True + $(NoWarn);CS8305 true False True diff --git a/Wino.Mail.WinUI/WinoApplication.cs b/Wino.Mail.WinUI/WinoApplication.cs index 8f1e7aa4..1b84d7ac 100644 --- a/Wino.Mail.WinUI/WinoApplication.cs +++ b/Wino.Mail.WinUI/WinoApplication.cs @@ -38,7 +38,7 @@ public abstract class WinoApplication : Application, IRecipient protected IDatabaseService DatabaseService { get; } protected ITranslationService TranslationService { get; } - public static WindowEx MainWindow { get; set; } + public static WindowEx? MainWindow { get; set; } protected WinoApplication() { @@ -50,14 +50,14 @@ public abstract class WinoApplication : Application, IRecipient TaskScheduler.UnobservedTaskException += OnUnobservedTaskException; UnhandledException += OnAppUnhandledException; - LogInitializer = Services.GetService(); - AppConfiguration = Services.GetService(); + LogInitializer = Services.GetRequiredService(); + AppConfiguration = Services.GetRequiredService(); - NewThemeService = Services.GetService(); - DatabaseService = Services.GetService(); - TranslationService = Services.GetService(); - UnderlyingThemeService = Services.GetService(); - ThumbnailService = Services.GetService(); + NewThemeService = Services.GetRequiredService(); + DatabaseService = Services.GetRequiredService(); + TranslationService = Services.GetRequiredService(); + UnderlyingThemeService = Services.GetRequiredService(); + ThumbnailService = Services.GetRequiredService(); // Make sure the paths are setup on app start. AppConfiguration.ApplicationDataFolderPath = ApplicationData.Current.LocalFolder.Path; @@ -67,10 +67,10 @@ public abstract class WinoApplication : Application, IRecipient ConfigureLogging(); } - private void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e) + private void CurrentDomain_UnhandledException(object? sender, System.UnhandledExceptionEventArgs e) => Log.Fatal(e.ExceptionObject as Exception, "AppDomain Unhandled Exception"); - private void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) + private void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e) => Log.Error(e.Exception, "Unobserved Task Exception"); private void OnAppUnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) @@ -83,7 +83,7 @@ public abstract class WinoApplication : Application, IRecipient { yield return DatabaseService; yield return TranslationService; - yield return Services.GetService(); + yield return Services.GetRequiredService(); } public Task InitializeServicesAsync() => GetActivationServices().Select(a => a.InitializeAsync()).WhenAll(); diff --git a/Wino.SourceGenerators/Translator/TranslatorGenerator.cs b/Wino.SourceGenerators/Translator/TranslatorGenerator.cs index 2d42194f..2d70ad41 100644 --- a/Wino.SourceGenerators/Translator/TranslatorGenerator.cs +++ b/Wino.SourceGenerators/Translator/TranslatorGenerator.cs @@ -43,7 +43,7 @@ namespace Wino.Core.SourceGeneration.Translator // Get the JSON schema and track changes var jsonSchema = context.AdditionalTextsProvider - .Where(static file => file.Path.EndsWith("en_US\\resources.json")) + .Where(static file => file.Path.Replace("\\", "/").EndsWith("en_US/resources.json", StringComparison.OrdinalIgnoreCase)) .Select((text, _) => (text, text.GetText())) .Collect() .WithTrackingName("JsonSchema"); diff --git a/Wino.SourceGenerators/Wino.SourceGenerators.csproj b/Wino.SourceGenerators/Wino.SourceGenerators.csproj index 39f0885b..0a66288e 100644 --- a/Wino.SourceGenerators/Wino.SourceGenerators.csproj +++ b/Wino.SourceGenerators/Wino.SourceGenerators.csproj @@ -3,6 +3,7 @@ netstandard2.0 enable + latest false AnyCPU true