diff --git a/.editorconfig b/.editorconfig index b06e6570..ba6b725a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,9 @@ dotnet_style_operator_placement_when_wrapping = beginning_of_line tab_width = 4 indent_size = 4 end_of_line = crlf +[XamlTypeInfo.g.cs] +dotnet_diagnostic.CS0612.severity = none +dotnet_diagnostic.CS0618.severity = none dotnet_style_coalesce_expression = true:suggestion dotnet_style_null_propagation = true:suggestion dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion @@ -289,4 +292,4 @@ csharp_style_prefer_readonly_struct = true:suggestion csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent csharp_style_prefer_primary_constructors = true:silent -csharp_prefer_system_threading_lock = true:suggestion \ No newline at end of file +csharp_prefer_system_threading_lock = true:suggestion diff --git a/Wino.Mail.WinUI/Activation/DefaultActivationHandler.cs b/Wino.Mail.WinUI/Activation/DefaultActivationHandler.cs deleted file mode 100644 index b2b9d3a3..00000000 --- a/Wino.Mail.WinUI/Activation/DefaultActivationHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Threading.Tasks; -using Windows.ApplicationModel.Activation; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media.Animation; -using Wino.Views; - -namespace Wino.Activation; - -internal class DefaultActivationHandler : ActivationHandler -{ - protected override Task HandleInternalAsync(IActivatedEventArgs args) - { - (Window.Current.Content as Frame).Navigate(typeof(AppShell), null, new DrillInNavigationTransitionInfo()); - - return Task.CompletedTask; - } - - // Only navigate if Frame content doesn't exist. - protected override bool CanHandleInternal(IActivatedEventArgs args) - => (Window.Current?.Content as Frame)?.Content == null; -} diff --git a/Wino.Mail.WinUI/Activation/FileActivationHandler.cs b/Wino.Mail.WinUI/Activation/FileActivationHandler.cs deleted file mode 100644 index a0774bf9..00000000 --- a/Wino.Mail.WinUI/Activation/FileActivationHandler.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Windows.ApplicationModel.Activation; -using Windows.Storage; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media.Animation; -using Wino.Core.Domain.Enums; -using Wino.Core.Domain.Interfaces; -using Wino.Core.WinUI.Extensions; -using Wino.Views; - -namespace Wino.Activation; - -internal class FileActivationHandler : ActivationHandler -{ - private readonly INativeAppService _nativeAppService; - private readonly IMimeFileService _mimeFileService; - private readonly IStatePersistanceService _statePersistanceService; - private readonly INavigationService _winoNavigationService; - - public FileActivationHandler(INativeAppService nativeAppService, - IMimeFileService mimeFileService, - IStatePersistanceService statePersistanceService, - INavigationService winoNavigationService) - { - _nativeAppService = nativeAppService; - _mimeFileService = mimeFileService; - _statePersistanceService = statePersistanceService; - _winoNavigationService = winoNavigationService; - } - - protected override async Task HandleInternalAsync(FileActivatedEventArgs args) - { - // Always handle the last item passed. - // Multiple files are not supported. - - var file = args.Files.Last() as StorageFile; - - // Only EML files are supported now. - var fileExtension = Path.GetExtension(file.Path); - - if (string.Equals(fileExtension, ".eml", StringComparison.OrdinalIgnoreCase)) - { - var fileBytes = await file.ToByteArrayAsync(); - var directoryName = Path.GetDirectoryName(file.Path); - - var messageInformation = await _mimeFileService.GetMimeMessageInformationAsync(fileBytes, directoryName).ConfigureAwait(false); - - if (_nativeAppService.IsAppRunning()) - { - // TODO: Activate another Window and go to mail rendering page. - _winoNavigationService.Navigate(WinoPage.MailRenderingPage, messageInformation, NavigationReferenceFrame.RenderingFrame); - } - else - { - _statePersistanceService.ShouldShiftMailRenderingDesign = true; - (Window.Current.Content as Frame).Navigate(typeof(MailRenderingPage), messageInformation, new DrillInNavigationTransitionInfo()); - } - } - } - - protected override bool CanHandleInternal(FileActivatedEventArgs args) => args.Files.Any(); - -} diff --git a/Wino.Mail.WinUI/Activation/ToastNotificationActivationHandler.cs b/Wino.Mail.WinUI/Activation/ToastNotificationActivationHandler.cs deleted file mode 100644 index ad2fa421..00000000 --- a/Wino.Mail.WinUI/Activation/ToastNotificationActivationHandler.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Threading.Tasks; -using CommunityToolkit.Mvvm.Messaging; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Toolkit.Uwp.Notifications; -using Serilog; -using Windows.ApplicationModel.Activation; -using Wino.Core.Domain; -using Wino.Core.Domain.Interfaces; -using Wino.Mail.WinUI; -using Wino.Messaging.Client.Accounts; - -namespace Wino.Activation; - -/// -/// This handler will only handle the toasts that runs on foreground. -/// Background executions are not handled here like mark as read or delete. -/// -internal class ToastNotificationActivationHandler : ActivationHandler -{ - private readonly IMailService _mailService; - private readonly IFolderService _folderService; - - private ToastArguments _toastArguments; - - public ToastNotificationActivationHandler(IMailService mailService, - IFolderService folderService) - { - _mailService = mailService; - _folderService = folderService; - } - - protected override async Task HandleInternalAsync(ToastNotificationActivatedEventArgs args) - { - // Create the mail item navigation event. - // If the app is running, it'll be picked up by the Messenger. - // Otherwise we'll save it and handle it when the shell loads all accounts. - - // Parse the mail unique id and perform above actions. - if (Guid.TryParse(_toastArguments[Constants.ToastMailUniqueIdKey], out Guid mailItemUniqueId)) - { - var account = await _mailService.GetMailAccountByUniqueIdAsync(mailItemUniqueId).ConfigureAwait(false); - if (account == null) return; - - var mailItem = await _mailService.GetSingleMailItemAsync(mailItemUniqueId).ConfigureAwait(false); - if (mailItem == null) return; - - var message = new AccountMenuItemExtended(mailItem.AssignedFolder.Id, mailItem); - - // Delegate this event to LaunchProtocolService so app shell can pick it up on launch if app doesn't work. - var launchProtocolService = App.Current.Services.GetRequiredService(); - launchProtocolService.LaunchParameter = message; - - // Send the messsage anyways. Launch protocol service will be ignored if the message is picked up by subscriber shell. - WeakReferenceMessenger.Default.Send(message); - } - } - - protected override bool CanHandleInternal(ToastNotificationActivatedEventArgs args) - { - try - { - _toastArguments = ToastArguments.Parse(args.Argument); - - return - _toastArguments.Contains(Constants.ToastMailUniqueIdKey) && - _toastArguments.Contains(Constants.ToastActionKey); - } - catch (Exception ex) - { - Log.Error(ex, "Couldn't handle parsing toast notification arguments for foreground navigate."); - } - - return false; - } -} diff --git a/Wino.Mail.WinUI/AppShell.xaml.cs b/Wino.Mail.WinUI/AppShell.xaml.cs index 898aff16..ce543a03 100644 --- a/Wino.Mail.WinUI/AppShell.xaml.cs +++ b/Wino.Mail.WinUI/AppShell.xaml.cs @@ -75,6 +75,9 @@ public sealed partial class AppShell : AppShellAbstract, var mailCopies = new List(); var dragPackage = e.DataView.Properties[nameof(MailDragPackage)] as MailDragPackage; + + if (dragPackage == null) return; + e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Move; // Extract mail copies from IMailItem. @@ -116,7 +119,7 @@ public sealed partial class AppShell : AppShellAbstract, var dragPackage = args.DataView.Properties[nameof(MailDragPackage)] as MailDragPackage; // Invalid package. - if (!dragPackage.DraggingMails.Any()) return false; + if (dragPackage == null || !dragPackage.DraggingMails.Any()) return false; // Check whether source and target folder are the same. if (interactingContainer.IsSelected) return false; @@ -144,6 +147,8 @@ public sealed partial class AppShell : AppShellAbstract, var draggingFolder = droppedContainer.DataContext as IBaseFolderMenuItem; + if (draggingFolder == null) return; + e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Move; e.DragUIOverride.Caption = string.Format(Translator.DragMoveToFolderCaption, draggingFolder.FolderName); } @@ -235,7 +240,7 @@ public sealed partial class AppShell : AppShellAbstract, private void ShellFrameContentNavigated(object sender, Microsoft.UI.Xaml.Navigation.NavigationEventArgs e) => TopShellContent = ((BasePage)e.Content).ShellContent; - partial void OnTopShellContentChanged(UIElement newValue) => WeakReferenceMessenger.Default.Send(new TitleBarShellContentUpdated()); + partial void OnTopShellContentChanged(UIElement? newValue) => WeakReferenceMessenger.Default.Send(new TitleBarShellContentUpdated()); private async void MenuItemContextRequested(UIElement sender, ContextRequestedEventArgs args) { diff --git a/Wino.Mail.WinUI/Behaviors/BindableCommandBarBehavior.cs b/Wino.Mail.WinUI/Behaviors/BindableCommandBarBehavior.cs index a29e96ea..4daad1ab 100644 --- a/Wino.Mail.WinUI/Behaviors/BindableCommandBarBehavior.cs +++ b/Wino.Mail.WinUI/Behaviors/BindableCommandBarBehavior.cs @@ -17,13 +17,13 @@ namespace Wino.Behaviors; public partial class BindableCommandBarBehavior : Behavior { - private readonly IPreferencesService _preferencesService = App.Current.Services.GetService(); + private readonly IPreferencesService? _preferencesService = App.Current.Services.GetService(); public static readonly DependencyProperty PrimaryCommandsProperty = DependencyProperty.Register( "PrimaryCommands", typeof(object), typeof(BindableCommandBarBehavior), new PropertyMetadata(null, UpdateCommands)); [GeneratedDependencyProperty] - public partial ICommand ItemClickedCommand { get; set; } + public partial ICommand? ItemClickedCommand { get; set; } public object PrimaryCommands { @@ -88,7 +88,7 @@ public partial class BindableCommandBarBehavior : Behavior { if (command is MailOperationMenuItem mailOperationMenuItem) { - ICommandBarElement menuItem = null; + ICommandBarElement? menuItem = null; if (mailOperationMenuItem.Operation == Core.Domain.Enums.MailOperation.Seperator) { @@ -97,13 +97,17 @@ public partial class BindableCommandBarBehavior : Behavior else { var label = XamlHelpers.GetOperationString(mailOperationMenuItem.Operation); - var labelPosition = string.IsNullOrWhiteSpace(label) || !_preferencesService.IsShowActionLabelsEnabled ? + var labelPosition = string.IsNullOrWhiteSpace(label) || _preferencesService == null || !_preferencesService.IsShowActionLabelsEnabled ? CommandBarLabelPosition.Collapsed : CommandBarLabelPosition.Default; + + var iconGlyph = XamlHelpers.GetWinoIconGlyph(mailOperationMenuItem.Operation); + var glyphValue = ControlConstants.WinoIconFontDictionary.TryGetValue(iconGlyph, out var glyph) ? glyph : string.Empty; + menuItem = new AppBarButton { Width = double.NaN, MinWidth = 40, - Icon = new WinoFontIcon() { Glyph = ControlConstants.WinoIconFontDictionary[XamlHelpers.GetWinoIconGlyph(mailOperationMenuItem.Operation)] }, + Icon = new WinoFontIcon() { Glyph = glyphValue }, Label = label, LabelPosition = labelPosition, DataContext = mailOperationMenuItem, @@ -162,7 +166,7 @@ public partial class BindableCommandBarBehavior : Behavior UpdatePrimaryCommands(); } - private void PrimaryCommandsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void PrimaryCommandsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { UpdatePrimaryCommands(); } diff --git a/Wino.Mail.WinUI/Behaviors/CreateMailNavigationItemBehavior.cs b/Wino.Mail.WinUI/Behaviors/CreateMailNavigationItemBehavior.cs index 87daff10..35e6c9f4 100644 --- a/Wino.Mail.WinUI/Behaviors/CreateMailNavigationItemBehavior.cs +++ b/Wino.Mail.WinUI/Behaviors/CreateMailNavigationItemBehavior.cs @@ -58,7 +58,7 @@ public class CreateMailNavigationItemBehavior : Behavior } } - private void MenuCollectionUpdated(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + private void MenuCollectionUpdated(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { ManageAccounts(); } diff --git a/Wino.Mail.WinUI/Controls/AccountNavigationItem.cs b/Wino.Mail.WinUI/Controls/AccountNavigationItem.cs index 19e6c4ee..c0de6ad7 100644 --- a/Wino.Mail.WinUI/Controls/AccountNavigationItem.cs +++ b/Wino.Mail.WinUI/Controls/AccountNavigationItem.cs @@ -28,8 +28,8 @@ public partial class AccountNavigationItem : WinoNavigationViewItem private const string PART_NavigationViewItemMenuItemsHost = "NavigationViewItemMenuItemsHost"; private const string PART_SelectionIndicator = "CustomSelectionIndicator"; - private ItemsRepeater _itemsRepeater; - private Microsoft.UI.Xaml.Shapes.Rectangle _selectionIndicator; + private ItemsRepeater _itemsRepeater = null!; + private Microsoft.UI.Xaml.Shapes.Rectangle _selectionIndicator = null!; public AccountNavigationItem() { @@ -40,8 +40,8 @@ public partial class AccountNavigationItem : WinoNavigationViewItem { base.OnApplyTemplate(); - _itemsRepeater = GetTemplateChild(PART_NavigationViewItemMenuItemsHost) as ItemsRepeater; - _selectionIndicator = GetTemplateChild(PART_SelectionIndicator) as Microsoft.UI.Xaml.Shapes.Rectangle; + _itemsRepeater = (GetTemplateChild(PART_NavigationViewItemMenuItemsHost) as ItemsRepeater)!; + _selectionIndicator = (GetTemplateChild(PART_SelectionIndicator) as Microsoft.UI.Xaml.Shapes.Rectangle)!; UpdateSelectionBorder(); } diff --git a/Wino.Mail.WinUI/Controls/Advanced/WinoItemsView.cs b/Wino.Mail.WinUI/Controls/Advanced/WinoItemsView.cs index b7a64657..c801ef97 100644 --- a/Wino.Mail.WinUI/Controls/Advanced/WinoItemsView.cs +++ b/Wino.Mail.WinUI/Controls/Advanced/WinoItemsView.cs @@ -15,7 +15,7 @@ public partial class WinoItemsView : ItemsView private ScrollView? _internalScrollView; [GeneratedDependencyProperty] - public partial ICommand LoadMoreCommand { get; set; } + public partial ICommand? LoadMoreCommand { get; set; } public IEnumerable? CastedItemsSource => ItemsSource as IEnumerable; diff --git a/Wino.Mail.WinUI/Controls/ImagePreviewControl.cs b/Wino.Mail.WinUI/Controls/ImagePreviewControl.cs index 72fd737a..259eeb2f 100644 --- a/Wino.Mail.WinUI/Controls/ImagePreviewControl.cs +++ b/Wino.Mail.WinUI/Controls/ImagePreviewControl.cs @@ -60,13 +60,13 @@ public partial class ImagePreviewControl : Control #endregion - private Ellipse Ellipse; - private Grid InitialsGrid; - private TextBlock InitialsTextblock; - private Image KnownHostImage; - private Border FaviconSquircle; - private Image FaviconImage; - private CancellationTokenSource contactPictureLoadingCancellationTokenSource; + private Ellipse Ellipse = null!; + private Grid InitialsGrid = null!; + private TextBlock InitialsTextblock = null!; + private Image KnownHostImage = null!; + private Border FaviconSquircle = null!; + private Image FaviconImage = null!; + private CancellationTokenSource contactPictureLoadingCancellationTokenSource = null!; public ImagePreviewControl() { @@ -77,12 +77,12 @@ public partial class ImagePreviewControl : Control { base.OnApplyTemplate(); - InitialsGrid = GetTemplateChild(PART_EllipseInitialsGrid) as Grid; - InitialsTextblock = GetTemplateChild(PART_InitialsTextBlock) as TextBlock; - KnownHostImage = GetTemplateChild(PART_KnownHostImage) as Image; - Ellipse = GetTemplateChild(PART_Ellipse) as Ellipse; - FaviconSquircle = GetTemplateChild(PART_FaviconSquircle) as Border; - FaviconImage = GetTemplateChild(PART_FaviconImage) as Image; + InitialsGrid = (GetTemplateChild(PART_EllipseInitialsGrid) as Grid)!; + InitialsTextblock = (GetTemplateChild(PART_InitialsTextBlock) as TextBlock)!; + KnownHostImage = (GetTemplateChild(PART_KnownHostImage) as Image)!; + Ellipse = (GetTemplateChild(PART_Ellipse) as Ellipse)!; + FaviconSquircle = (GetTemplateChild(PART_FaviconSquircle) as Border)!; + FaviconImage = (GetTemplateChild(PART_FaviconImage) as Image)!; UpdateInformation(); } @@ -101,7 +101,7 @@ public partial class ImagePreviewControl : Control // Cancel active image loading if exists. if (!contactPictureLoadingCancellationTokenSource?.IsCancellationRequested ?? false) { - contactPictureLoadingCancellationTokenSource.Cancel(); + contactPictureLoadingCancellationTokenSource!.Cancel(); } string contactPicture = SenderContactPicture; @@ -120,8 +120,10 @@ public partial class ImagePreviewControl : Control { // Show favicon in squircle FaviconSquircle.Visibility = Visibility.Visible; - InitialsGrid.Visibility = Visibility.Collapsed; - KnownHostImage.Visibility = Visibility.Collapsed; + if (InitialsGrid != null) + InitialsGrid.Visibility = Visibility.Collapsed; + if (KnownHostImage != null) + KnownHostImage.Visibility = Visibility.Collapsed; var bitmapImage = await GetBitmapImageAsync(contactPicture); @@ -133,9 +135,12 @@ public partial class ImagePreviewControl : Control else { // Show normal avatar (tondo) - FaviconSquircle.Visibility = Visibility.Collapsed; - KnownHostImage.Visibility = Visibility.Collapsed; - InitialsGrid.Visibility = Visibility.Visible; + if (FaviconSquircle != null) + FaviconSquircle.Visibility = Visibility.Collapsed; + if (KnownHostImage != null) + KnownHostImage.Visibility = Visibility.Collapsed; + if (InitialsGrid != null) + InitialsGrid.Visibility = Visibility.Visible; contactPictureLoadingCancellationTokenSource = new CancellationTokenSource(); try { @@ -145,8 +150,10 @@ public partial class ImagePreviewControl : Control { if (!contactPictureLoadingCancellationTokenSource?.Token.IsCancellationRequested ?? false) { - Ellipse.Fill = brush; - InitialsTextblock.Text = string.Empty; + if (Ellipse != null) + Ellipse.Fill = brush; + if (InitialsTextblock != null) + InitialsTextblock.Text = string.Empty; } } } @@ -158,19 +165,24 @@ public partial class ImagePreviewControl : Control } else { - FaviconSquircle.Visibility = Visibility.Collapsed; - KnownHostImage.Visibility = Visibility.Collapsed; - InitialsGrid.Visibility = Visibility.Visible; + if (FaviconSquircle != null) + FaviconSquircle.Visibility = Visibility.Collapsed; + if (KnownHostImage != null) + KnownHostImage.Visibility = Visibility.Collapsed; + if (InitialsGrid != null) + InitialsGrid.Visibility = Visibility.Visible; var colorHash = new ColorHash(); var rgb = colorHash.Rgb(FromAddress); - Ellipse.Fill = new SolidColorBrush(Color.FromArgb(rgb.A, rgb.R, rgb.G, rgb.B)); - InitialsTextblock.Text = ExtractInitialsFromName(FromName); + if (Ellipse != null) + Ellipse.Fill = new SolidColorBrush(Color.FromArgb(rgb.A, rgb.R, rgb.G, rgb.B)); + if (InitialsTextblock != null) + InitialsTextblock.Text = ExtractInitialsFromName(FromName); } } - private static async Task GetContactImageBrushAsync(string base64) + private static async Task GetContactImageBrushAsync(string base64) { // Load the image from base64 string. @@ -181,7 +193,7 @@ public partial class ImagePreviewControl : Control return new ImageBrush() { ImageSource = bitmapImage }; } - private static async Task GetBitmapImageAsync(string base64) + private static async Task GetBitmapImageAsync(string base64) { try { diff --git a/Wino.Mail.WinUI/Controls/ListView/WinoMailItemContainerStyleSelector.cs b/Wino.Mail.WinUI/Controls/ListView/WinoMailItemContainerStyleSelector.cs index 5a7b46e0..5afa2f4b 100644 --- a/Wino.Mail.WinUI/Controls/ListView/WinoMailItemContainerStyleSelector.cs +++ b/Wino.Mail.WinUI/Controls/ListView/WinoMailItemContainerStyleSelector.cs @@ -15,6 +15,6 @@ public partial class WinoMailItemContainerStyleSelector : StyleSelector if (item is ThreadMailItemViewModel) return ThreadStyle ?? throw new Exception($"Missing style for {nameof(ThreadMailItemViewModel)}"); - return null; + return base.SelectStyleCore(item, container); } } diff --git a/Wino.Mail.WinUI/Controls/WebViewEditorControl.cs b/Wino.Mail.WinUI/Controls/WebViewEditorControl.cs index 55f91ade..680d9541 100644 --- a/Wino.Mail.WinUI/Controls/WebViewEditorControl.cs +++ b/Wino.Mail.WinUI/Controls/WebViewEditorControl.cs @@ -19,9 +19,9 @@ namespace Wino.Mail.Controls; public sealed partial class WebViewEditorControl : Control, IDisposable { - private readonly INativeAppService _nativeAppService = App.Current.Services.GetService(); - private readonly IFontService _fontService = App.Current.Services.GetService(); - private readonly IPreferencesService _preferencesService = App.Current.Services.GetService(); + private readonly INativeAppService _nativeAppService = App.Current.Services.GetService()!; + private readonly IFontService _fontService = App.Current.Services.GetService()!; + private readonly IPreferencesService _preferencesService = App.Current.Services.GetService()!; [GeneratedDependencyProperty] public partial bool IsEditorDarkMode { get; set; } @@ -131,7 +131,7 @@ public sealed partial class WebViewEditorControl : Control, IDisposable } private const string PART_WebView = "WebView"; - private WebView2 _chromium; + private WebView2 _chromium = null!; private bool _disposedValue; private readonly TaskCompletionSource _domLoadedTask = new(); @@ -146,7 +146,7 @@ public sealed partial class WebViewEditorControl : Control, IDisposable { base.OnApplyTemplate(); - _chromium = GetTemplateChild(PART_WebView) as WebView2; + _chromium = (GetTemplateChild(PART_WebView) as WebView2)!; await InitializeComponent(); } @@ -175,7 +175,7 @@ public sealed partial class WebViewEditorControl : Control, IDisposable IsEditorDarkMode = !IsEditorDarkMode; } - public async Task GetHtmlBodyAsync() + public async Task GetHtmlBodyAsync() { var editorContent = await _chromium.ExecuteScriptFunctionSafeAsync("GetHTMLContent"); @@ -273,6 +273,8 @@ public sealed partial class WebViewEditorControl : Control, IDisposable { var change = JsonSerializer.Deserialize(args.WebMessageAsJson, DomainModelsJsonContext.Default.WebViewMessage); + if (change == null) return; + if (change.Type == "bold") { _isEditorBoldInternal = change.Value == "true"; diff --git a/Wino.Mail.WinUI/Controls/WinoExpander.cs b/Wino.Mail.WinUI/Controls/WinoExpander.cs index d40c93be..b2f90871 100644 --- a/Wino.Mail.WinUI/Controls/WinoExpander.cs +++ b/Wino.Mail.WinUI/Controls/WinoExpander.cs @@ -13,9 +13,9 @@ public partial class WinoExpander : Control private const string PART_ContentAreaWrapper = "ContentAreaWrapper"; private const string PART_ContentArea = "ContentArea"; - private ContentControl HeaderGrid; - private ContentControl ContentArea; - private Grid ContentAreaWrapper; + private ContentControl HeaderGrid = null!; + private ContentControl ContentArea = null!; + private Grid ContentAreaWrapper = null!; public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(nameof(Header), typeof(UIElement), typeof(WinoExpander), new PropertyMetadata(null)); public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(UIElement), typeof(WinoExpander), new PropertyMetadata(null)); @@ -50,9 +50,9 @@ public partial class WinoExpander : Control { base.OnApplyTemplate(); - HeaderGrid = GetTemplateChild(PART_HeaderGrid) as ContentControl; - ContentAreaWrapper = GetTemplateChild(PART_ContentAreaWrapper) as Grid; - ContentArea = GetTemplateChild(PART_ContentArea) as ContentControl; + HeaderGrid = (GetTemplateChild(PART_HeaderGrid) as ContentControl)!; + ContentAreaWrapper = (GetTemplateChild(PART_ContentAreaWrapper) as Grid)!; + ContentArea = (GetTemplateChild(PART_ContentArea) as ContentControl)!; Guard.IsNotNull(HeaderGrid, nameof(HeaderGrid)); Guard.IsNotNull(ContentAreaWrapper, nameof(ContentAreaWrapper)); diff --git a/Wino.Mail.WinUI/Controls/WinoSwipeControlItems.cs b/Wino.Mail.WinUI/Controls/WinoSwipeControlItems.cs index c3a412af..a6b095ae 100644 --- a/Wino.Mail.WinUI/Controls/WinoSwipeControlItems.cs +++ b/Wino.Mail.WinUI/Controls/WinoSwipeControlItems.cs @@ -60,7 +60,7 @@ public partial class WinoSwipeControlItems : SwipeItems this.Add(swipeItem); } - private SwipeItem GetSwipeItem(MailOperation operation) + private SwipeItem? GetSwipeItem(MailOperation operation) { if (MailItem == null) return null; @@ -72,18 +72,18 @@ public partial class WinoSwipeControlItems : SwipeItems { var singleItem = MailItem as MailItemViewModel; - if (operation == MailOperation.MarkAsRead && singleItem.IsRead) + if (singleItem != null && operation == MailOperation.MarkAsRead && singleItem.IsRead) finalOperation = MailOperation.MarkAsUnread; - else if (operation == MailOperation.MarkAsUnread && !singleItem.IsRead) + else if (singleItem != null && operation == MailOperation.MarkAsUnread && !singleItem.IsRead) finalOperation = MailOperation.MarkAsRead; } else { var threadItem = MailItem as ThreadMailItemViewModel; - if (operation == MailOperation.MarkAsRead && threadItem.ThreadEmails.All(a => a.IsRead)) + if (threadItem != null && operation == MailOperation.MarkAsRead && threadItem.ThreadEmails.All(a => a.IsRead)) finalOperation = MailOperation.MarkAsUnread; - else if (operation == MailOperation.MarkAsUnread && threadItem.ThreadEmails.All(a => !a.IsRead)) + else if (threadItem != null && operation == MailOperation.MarkAsUnread && threadItem.ThreadEmails.All(a => !a.IsRead)) finalOperation = MailOperation.MarkAsRead; } @@ -114,18 +114,21 @@ public partial class WinoSwipeControlItems : SwipeItems { var singleItem = MailItem as MailItemViewModel; - if (SwipeOperation == MailOperation.MarkAsRead && singleItem.IsRead) - finalOperation = MailOperation.MarkAsUnread; - else if (SwipeOperation == MailOperation.MarkAsUnread && !singleItem.IsRead) - finalOperation = MailOperation.MarkAsRead; + if (singleItem != null) + { + if (SwipeOperation == MailOperation.MarkAsRead && singleItem.IsRead) + finalOperation = MailOperation.MarkAsUnread; + else if (SwipeOperation == MailOperation.MarkAsUnread && !singleItem.IsRead) + finalOperation = MailOperation.MarkAsRead; + } } else { var threadItem = MailItem as ThreadMailItemViewModel; - if (SwipeOperation == MailOperation.MarkAsRead && threadItem.ThreadEmails.All(a => a.IsRead)) + if (threadItem != null && SwipeOperation == MailOperation.MarkAsRead && threadItem.ThreadEmails.All(a => a.IsRead)) finalOperation = MailOperation.MarkAsUnread; - else if (SwipeOperation == MailOperation.MarkAsUnread && threadItem.ThreadEmails.All(a => !a.IsRead)) + else if (threadItem != null && SwipeOperation == MailOperation.MarkAsUnread && threadItem.ThreadEmails.All(a => !a.IsRead)) finalOperation = MailOperation.MarkAsRead; } diff --git a/Wino.Mail.WinUI/Dialogs/AccountReorderDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/AccountReorderDialog.xaml.cs index d9b7815a..c29dcae5 100644 --- a/Wino.Mail.WinUI/Dialogs/AccountReorderDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/AccountReorderDialog.xaml.cs @@ -1,4 +1,5 @@ -using System.Collections.ObjectModel; +using System; +using System.Collections.ObjectModel; using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.UI.Xaml.Controls; @@ -9,16 +10,16 @@ namespace Wino.Dialogs; public sealed partial class AccountReorderDialog : ContentDialog { - public ObservableCollection Accounts { get; } + public ObservableCollection Accounts { get; set; } = null!; private int count; private bool isOrdering = false; - private readonly IAccountService _accountService = App.Current.Services.GetService(); + private readonly IAccountService? _accountService = App.Current.Services.GetService(); - public AccountReorderDialog(ObservableCollection accounts) + public AccountReorderDialog(ObservableCollection? accounts) { - Accounts = accounts; + Accounts = accounts ?? throw new ArgumentNullException(nameof(accounts)); count = accounts.Count; @@ -33,7 +34,7 @@ public sealed partial class AccountReorderDialog : ContentDialog private void DialogClosed(ContentDialog sender, ContentDialogClosedEventArgs args) => Accounts.CollectionChanged -= AccountsChanged; - private async void AccountsChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + private async void AccountsChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (count - 1 == Accounts.Count) isOrdering = true; @@ -44,7 +45,8 @@ public sealed partial class AccountReorderDialog : ContentDialog var dict = Accounts.ToDictionary(a => a.StartupEntityId, a => Accounts.IndexOf(a)); - await _accountService.UpdateAccountOrdersAsync(dict); + if (_accountService != null) + await _accountService.UpdateAccountOrdersAsync(dict); isOrdering = false; } diff --git a/Wino.Mail.WinUI/Dialogs/CreateAccountAliasDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/CreateAccountAliasDialog.xaml.cs index 9b090941..ce410889 100644 --- a/Wino.Mail.WinUI/Dialogs/CreateAccountAliasDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/CreateAccountAliasDialog.xaml.cs @@ -7,7 +7,7 @@ namespace Wino.Dialogs; public sealed partial class CreateAccountAliasDialog : ContentDialog, ICreateAccountAliasDialog { - public MailAccountAlias CreatedAccountAlias { get; set; } + public MailAccountAlias CreatedAccountAlias { get; set; } = null!; public CreateAccountAliasDialog() { InitializeComponent(); diff --git a/Wino.Mail.WinUI/Dialogs/KeyboardShortcutDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/KeyboardShortcutDialog.xaml.cs index 1773ea92..e90df4c5 100644 --- a/Wino.Mail.WinUI/Dialogs/KeyboardShortcutDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/KeyboardShortcutDialog.xaml.cs @@ -25,7 +25,7 @@ public sealed partial class KeyboardShortcutDialog : ContentDialog { InitializeComponent(); AvailableMailOperations = GetAvailableMailOperations(); - SelectedMailOperation = AvailableMailOperations.FirstOrDefault(); + SelectedMailOperation = AvailableMailOperations.FirstOrDefault()!; } public KeyboardShortcutDialog(KeyboardShortcut existingShortcut) : this() @@ -33,7 +33,7 @@ public sealed partial class KeyboardShortcutDialog : ContentDialog if (existingShortcut != null) { KeyInputTextBox.Text = existingShortcut.Key; - SelectedMailOperation = AvailableMailOperations.FirstOrDefault(x => x.Operation == existingShortcut.MailOperation); + SelectedMailOperation = AvailableMailOperations.FirstOrDefault(x => x.Operation == existingShortcut.MailOperation)!; var modifiers = existingShortcut.ModifierKeys; IsControlPressed = modifiers.HasFlag(ModifierKeys.Control); diff --git a/Wino.Mail.WinUI/Dialogs/MessageSourceDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/MessageSourceDialog.xaml.cs index c93eed91..4c0b7677 100644 --- a/Wino.Mail.WinUI/Dialogs/MessageSourceDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/MessageSourceDialog.xaml.cs @@ -8,8 +8,8 @@ namespace Wino.Mail.Dialogs; public sealed partial class MessageSourceDialog : ContentDialog { - private readonly IClipboardService _clipboardService = App.Current.Services.GetService(); - public string MessageSource { get; set; } + private readonly IClipboardService? _clipboardService = App.Current.Services.GetService(); + public string MessageSource { get; set; } = string.Empty; public bool Copied { get; set; } public MessageSourceDialog() { @@ -18,7 +18,7 @@ public sealed partial class MessageSourceDialog : ContentDialog private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) { - _clipboardService.CopyClipboardAsync(MessageSource); + _clipboardService!.CopyClipboardAsync(MessageSource); Copied = true; } } diff --git a/Wino.Mail.WinUI/Dialogs/MoveMailDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/MoveMailDialog.xaml.cs index 0cb6d1f8..5aa66489 100644 --- a/Wino.Mail.WinUI/Dialogs/MoveMailDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/MoveMailDialog.xaml.cs @@ -17,7 +17,7 @@ public sealed partial class MoveMailDialog : ContentDialog public static readonly DependencyProperty SelectedFolderProperty = DependencyProperty.Register(nameof(SelectedFolder), typeof(IMailItemFolder), typeof(MoveMailDialog), new PropertyMetadata(null, OnSelectedFolderChanged)); - public List FolderList { get; set; } + public List FolderList { get; set; } = []; public MoveMailDialog(List allFolders) { @@ -58,7 +58,7 @@ public sealed partial class MoveMailDialog : ContentDialog container.IsExpanded = !container.IsExpanded; } } - SelectedFolder = null; + SelectedFolder = null!; } else { diff --git a/Wino.Mail.WinUI/Dialogs/NewImapSetupDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/NewImapSetupDialog.xaml.cs index 0772143f..ec67ef8e 100644 --- a/Wino.Mail.WinUI/Dialogs/NewImapSetupDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/NewImapSetupDialog.xaml.cs @@ -43,7 +43,7 @@ public sealed partial class NewImapSetupDialog : ContentDialog, public void Complete(bool cancel) { if (!_getServerInfoTaskCompletionSource.Task.IsCompleted) - _getServerInfoTaskCompletionSource.TrySetResult(null); + _getServerInfoTaskCompletionSource.TrySetResult(null!); isDismissRequested = true; diff --git a/Wino.Mail.WinUI/Dialogs/SignatureEditorDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/SignatureEditorDialog.xaml.cs index 310bc12e..f931312c 100644 --- a/Wino.Mail.WinUI/Dialogs/SignatureEditorDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/SignatureEditorDialog.xaml.cs @@ -8,7 +8,7 @@ namespace Wino.Dialogs; public sealed partial class SignatureEditorDialog : ContentDialog { - public AccountSignature Result; + public AccountSignature Result = null!; public SignatureEditorDialog() { @@ -51,7 +51,7 @@ public sealed partial class SignatureEditorDialog : ContentDialog private async void SaveClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args) { - var newSignature = Regex.Unescape(await WebViewEditor.GetHtmlBodyAsync()); + var newSignature = Regex.Unescape((await WebViewEditor.GetHtmlBodyAsync())!); if (Result == null) { diff --git a/Wino.Mail.WinUI/Dialogs/SystemFolderConfigurationDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/SystemFolderConfigurationDialog.xaml.cs index 75a4df16..af66754e 100644 --- a/Wino.Mail.WinUI/Dialogs/SystemFolderConfigurationDialog.xaml.cs +++ b/Wino.Mail.WinUI/Dialogs/SystemFolderConfigurationDialog.xaml.cs @@ -5,7 +5,6 @@ using Microsoft.UI.Xaml.Controls; using Wino.Core.Domain; using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Enums; -using Wino.Core.Domain.Exceptions; using Wino.Core.Domain.Models.Folders; namespace Wino.Dialogs; @@ -14,14 +13,14 @@ public sealed partial class SystemFolderConfigurationDialog : ContentDialog { private bool canDismissDialog = false; - public SystemFolderConfiguration Configuration { get; set; } + public SystemFolderConfiguration? Configuration { get; set; } public List AvailableFolders { get; } - public MailItemFolder Sent { get; set; } - public MailItemFolder Draft { get; set; } - public MailItemFolder Archive { get; set; } - public MailItemFolder Junk { get; set; } - public MailItemFolder Trash { get; set; } + public MailItemFolder? Sent { get; set; } + public MailItemFolder? Draft { get; set; } + public MailItemFolder? Archive { get; set; } + public MailItemFolder? Junk { get; set; } + public MailItemFolder? Trash { get; set; } public SystemFolderConfigurationDialog(List availableFolders) { @@ -29,11 +28,11 @@ public sealed partial class SystemFolderConfigurationDialog : ContentDialog AvailableFolders = availableFolders; - Sent = AvailableFolders.Find(a => a.SpecialFolderType == Core.Domain.Enums.SpecialFolderType.Sent); - Draft = AvailableFolders.Find(a => a.SpecialFolderType == Core.Domain.Enums.SpecialFolderType.Draft); - Archive = AvailableFolders.Find(a => a.SpecialFolderType == Core.Domain.Enums.SpecialFolderType.Archive); - Junk = AvailableFolders.Find(a => a.SpecialFolderType == Core.Domain.Enums.SpecialFolderType.Junk); - Trash = AvailableFolders.Find(a => a.SpecialFolderType == Core.Domain.Enums.SpecialFolderType.Deleted); + Sent = AvailableFolders.Find(a => a.SpecialFolderType == SpecialFolderType.Sent); + Draft = AvailableFolders.Find(a => a.SpecialFolderType == SpecialFolderType.Draft); + Archive = AvailableFolders.Find(a => a.SpecialFolderType == SpecialFolderType.Archive); + Junk = AvailableFolders.Find(a => a.SpecialFolderType == SpecialFolderType.Junk); + Trash = AvailableFolders.Find(a => a.SpecialFolderType == SpecialFolderType.Deleted); } private void DialogClosing(ContentDialog sender, ContentDialogClosingEventArgs args) @@ -46,21 +45,21 @@ public sealed partial class SystemFolderConfigurationDialog : ContentDialog private void SaveClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args) { - ValidationErrorTextBlock.Text = string.Empty; + ValidationErrorTextBlock!.Text = string.Empty; - var allSpecialFolders = new List() + var allSpecialFolders = new List() { Sent, Draft, Archive, Trash, Junk }; if (allSpecialFolders.Any(a => a != null && a.SpecialFolderType == SpecialFolderType.Inbox)) - ValidationErrorTextBlock.Text = Translator.SystemFolderConfigDialogValidation_InboxSelected; + ValidationErrorTextBlock!.Text = Translator.SystemFolderConfigDialogValidation_InboxSelected; - if (new HashSet(allSpecialFolders.Where(a => a != null).Select(x => x.Id)).Count != allSpecialFolders.Where(a => a != null).Count()) - ValidationErrorTextBlock.Text = Translator.SystemFolderConfigDialogValidation_DuplicateSystemFolders; + if (new HashSet(allSpecialFolders.Where(a => a != null).Select(x => x!.Id)).Count != allSpecialFolders.Where(a => a != null).Count()) + ValidationErrorTextBlock!.Text = Translator.SystemFolderConfigDialogValidation_DuplicateSystemFolders; // Check if we can save. - if (string.IsNullOrEmpty(ValidationErrorTextBlock.Text)) + if (string.IsNullOrEmpty(ValidationErrorTextBlock!.Text)) { var configuration = new SystemFolderConfiguration(Sent, Draft, Archive, Trash, Junk); diff --git a/Wino.Mail.WinUI/MenuFlyouts/FilterMenuFlyout.cs b/Wino.Mail.WinUI/MenuFlyouts/FilterMenuFlyout.cs index e7c8111e..8a6fe7d5 100644 --- a/Wino.Mail.WinUI/MenuFlyouts/FilterMenuFlyout.cs +++ b/Wino.Mail.WinUI/MenuFlyouts/FilterMenuFlyout.cs @@ -110,7 +110,8 @@ public partial class FilterMenuFlyout : MenuFlyout var optionModel = button.Tag as SortingOption; - SelectSortingOption(optionModel); + if (optionModel != null) + SelectSortingOption(optionModel); } } @@ -124,7 +125,8 @@ public partial class FilterMenuFlyout : MenuFlyout var optionModel = button.Tag as FilterOption; - SelectFilterOption(optionModel); + if (optionModel != null) + SelectFilterOption(optionModel); } } diff --git a/Wino.Mail.WinUI/MenuFlyouts/MoveButtonFlyout.cs b/Wino.Mail.WinUI/MenuFlyouts/MoveButtonFlyout.cs index 0352f096..e1fdbdcc 100644 --- a/Wino.Mail.WinUI/MenuFlyouts/MoveButtonFlyout.cs +++ b/Wino.Mail.WinUI/MenuFlyouts/MoveButtonFlyout.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using Windows.Foundation; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Windows.Foundation; using Wino.Core.Domain.Entities.Mail; namespace Wino.MenuFlyouts; @@ -15,7 +15,7 @@ public class MoveButtonMenuItemClickedEventArgs public partial class MoveButtonFlyout : MenuFlyout { - public event TypedEventHandler MenuItemClick; + public event TypedEventHandler MenuItemClick = delegate { }; public static readonly DependencyProperty FoldersProperty = DependencyProperty.Register(nameof(Folders), typeof(List), typeof(MoveButtonFlyout), new PropertyMetadata(null, new PropertyChangedCallback(OnFoldersChanged))); public List Folders @@ -66,7 +66,7 @@ public partial class MoveButtonFlyout : MenuFlyout private void MenuItemClicked(object sender, RoutedEventArgs e) { - var clickedFolder = (sender as MenuFlyoutItem).Tag as MailItemFolder; + var clickedFolder = ((MenuFlyoutItem)sender).Tag as MailItemFolder ?? throw new InvalidOperationException("Clicked folder is null."); MenuItemClick?.Invoke(this, new MoveButtonMenuItemClickedEventArgs() { diff --git a/Wino.Mail.WinUI/MenuFlyouts/WinoOperationFlyout.cs b/Wino.Mail.WinUI/MenuFlyouts/WinoOperationFlyout.cs index 19420781..b28c7bd5 100644 --- a/Wino.Mail.WinUI/MenuFlyouts/WinoOperationFlyout.cs +++ b/Wino.Mail.WinUI/MenuFlyouts/WinoOperationFlyout.cs @@ -7,7 +7,7 @@ namespace Wino.MenuFlyouts; public partial class WinoOperationFlyout : MenuFlyout, IDisposable where TActionType : class { - public TActionType ClickedOperation { get; set; } + public TActionType ClickedOperation { get; set; } = null!; protected readonly IEnumerable AvailableActions; diff --git a/Wino.Mail.WinUI/Selectors/AccountProviderViewModelTemplateSelector.cs b/Wino.Mail.WinUI/Selectors/AccountProviderViewModelTemplateSelector.cs index 91ede6e0..080434da 100644 --- a/Wino.Mail.WinUI/Selectors/AccountProviderViewModelTemplateSelector.cs +++ b/Wino.Mail.WinUI/Selectors/AccountProviderViewModelTemplateSelector.cs @@ -1,4 +1,5 @@ -using Microsoft.UI.Xaml; +using System; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Wino.Core.ViewModels.Data; @@ -6,14 +7,14 @@ namespace Wino.Selectors; public partial class AccountProviderViewModelTemplateSelector : DataTemplateSelector { - public DataTemplate RootAccountTemplate { get; set; } - public DataTemplate MergedAccountTemplate { get; set; } + public DataTemplate? RootAccountTemplate { get; set; } + public DataTemplate? MergedAccountTemplate { get; set; } protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { if (item is MergedAccountProviderDetailViewModel) - return MergedAccountTemplate; + return MergedAccountTemplate ?? throw new ArgumentException(nameof(MergedAccountTemplate)); else - return RootAccountTemplate; + return RootAccountTemplate ?? throw new ArgumentException(nameof(RootAccountTemplate)); } } diff --git a/Wino.Mail.WinUI/Selectors/AccountReorderTemplateSelector.cs b/Wino.Mail.WinUI/Selectors/AccountReorderTemplateSelector.cs index e4f5187e..af5e607a 100644 --- a/Wino.Mail.WinUI/Selectors/AccountReorderTemplateSelector.cs +++ b/Wino.Mail.WinUI/Selectors/AccountReorderTemplateSelector.cs @@ -1,4 +1,5 @@ -using Microsoft.UI.Xaml; +using System; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Wino.Core.ViewModels.Data; @@ -6,16 +7,16 @@ namespace Wino.Selectors; public partial class AccountReorderTemplateSelector : DataTemplateSelector { - public DataTemplate MergedAccountReorderTemplate { get; set; } - public DataTemplate RootAccountReorderTemplate { get; set; } + public DataTemplate? MergedAccountReorderTemplate { get; set; } + public DataTemplate? RootAccountReorderTemplate { get; set; } protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { if (item is MergedAccountProviderDetailViewModel) { - return MergedAccountReorderTemplate; + return MergedAccountReorderTemplate ?? throw new ArgumentException(nameof(MergedAccountReorderTemplate)); } - return RootAccountReorderTemplate; + return RootAccountReorderTemplate ?? throw new ArgumentException(nameof(RootAccountReorderTemplate)); } } diff --git a/Wino.Mail.WinUI/Selectors/MailItemDisplayModePreviewTemplateSelector.cs b/Wino.Mail.WinUI/Selectors/MailItemDisplayModePreviewTemplateSelector.cs index eef9d981..05a86d14 100644 --- a/Wino.Mail.WinUI/Selectors/MailItemDisplayModePreviewTemplateSelector.cs +++ b/Wino.Mail.WinUI/Selectors/MailItemDisplayModePreviewTemplateSelector.cs @@ -1,4 +1,5 @@ -using Microsoft.UI.Xaml; +using System; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Wino.Core.Domain.Enums; @@ -9,9 +10,9 @@ namespace Wino.Selectors; /// public partial class MailItemDisplayModePreviewTemplateSelector : DataTemplateSelector { - public DataTemplate CompactTemplate { get; set; } - public DataTemplate MediumTemplate { get; set; } - public DataTemplate SpaciousTemplate { get; set; } + public DataTemplate? CompactTemplate { get; set; } + public DataTemplate? MediumTemplate { get; set; } + public DataTemplate? SpaciousTemplate { get; set; } protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { @@ -20,11 +21,11 @@ public partial class MailItemDisplayModePreviewTemplateSelector : DataTemplateSe switch (mode) { case MailListDisplayMode.Spacious: - return SpaciousTemplate; + return SpaciousTemplate ?? throw new ArgumentException(nameof(SpaciousTemplate)); case MailListDisplayMode.Medium: - return MediumTemplate; + return MediumTemplate ?? throw new ArgumentException(nameof(MediumTemplate)); case MailListDisplayMode.Compact: - return CompactTemplate; + return CompactTemplate ?? throw new ArgumentException(nameof(CompactTemplate)); } } diff --git a/Wino.Mail.WinUI/Services/DialogService.cs b/Wino.Mail.WinUI/Services/DialogService.cs index 5a50b4b0..17458d0b 100644 --- a/Wino.Mail.WinUI/Services/DialogService.cs +++ b/Wino.Mail.WinUI/Services/DialogService.cs @@ -149,7 +149,7 @@ public class DialogService : DialogServiceBase, IMailDialogService return accountPicker.PickedAccount; } - public async Task ShowSignatureEditorDialog(AccountSignature signatureModel = null) + public async Task ShowSignatureEditorDialog(AccountSignature? signatureModel = null) { SignatureEditorDialog signatureEditorDialog; if (signatureModel != null) @@ -169,7 +169,7 @@ public class DialogService : DialogServiceBase, IMailDialogService var result = await HandleDialogPresentationAsync(signatureEditorDialog); - return result == ContentDialogResult.Primary ? signatureEditorDialog.Result : null; + return result == ContentDialogResult.Primary ? signatureEditorDialog.Result : null!; } public async Task ShowMessageSourceDialogAsync(string messageSource) diff --git a/Wino.Mail.WinUI/Services/NavigationService.cs b/Wino.Mail.WinUI/Services/NavigationService.cs index 346d98ab..f5299b1b 100644 --- a/Wino.Mail.WinUI/Services/NavigationService.cs +++ b/Wino.Mail.WinUI/Services/NavigationService.cs @@ -74,7 +74,7 @@ public class NavigationService : NavigationServiceBase, INavigationService } public bool Navigate(WinoPage page, - object parameter = null, + object? parameter = null, NavigationReferenceFrame frame = NavigationReferenceFrame.ShellFrame, NavigationTransitionType transition = NavigationTransitionType.None) { diff --git a/Wino.Mail.WinUI/Services/ProviderService.cs b/Wino.Mail.WinUI/Services/ProviderService.cs index 81083d0f..918891e9 100644 --- a/Wino.Mail.WinUI/Services/ProviderService.cs +++ b/Wino.Mail.WinUI/Services/ProviderService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Wino.Core.Domain.Enums; using Wino.Core.Domain.Interfaces; @@ -15,7 +16,7 @@ public class ProviderService : IProviderService { var details = GetAvailableProviders(); - return details.FirstOrDefault(a => a.Type == type); + return details.FirstOrDefault(a => a.Type == type) ?? throw new InvalidOperationException($"Provider detail not found for type: {type}"); } public List GetAvailableProviders() diff --git a/Wino.Mail.WinUI/ShellWindow.xaml.cs b/Wino.Mail.WinUI/ShellWindow.xaml.cs index cdda19a5..95925708 100644 --- a/Wino.Mail.WinUI/ShellWindow.xaml.cs +++ b/Wino.Mail.WinUI/ShellWindow.xaml.cs @@ -85,7 +85,11 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow, IRecipient WeakReferenceMessenger.Default.Send(new DisposeRenderingFrameRequested()); } - private void MainFrameNavigated(object sender, Microsoft.UI.Xaml.Navigation.NavigationEventArgs e) => ShellTitleBar.Content = (e.Content as BasePage).ShellContent; + private void MainFrameNavigated(object sender, Microsoft.UI.Xaml.Navigation.NavigationEventArgs e) + { + if (e.Content is BasePage basePage) + ShellTitleBar.Content = basePage.ShellContent; + } private void PaneButtonClicked(Microsoft.UI.Xaml.Controls.TitleBar sender, object args) { diff --git a/Wino.Mail.WinUI/Views/ComposePage.xaml.cs b/Wino.Mail.WinUI/Views/ComposePage.xaml.cs index eff3f555..27ba3b67 100644 --- a/Wino.Mail.WinUI/Views/ComposePage.xaml.cs +++ b/Wino.Mail.WinUI/Views/ComposePage.xaml.cs @@ -41,7 +41,7 @@ public sealed partial class ComposePage : ComposePageAbstract, InitializeComponent(); } - private async void GlobalFocusManagerGotFocus(object sender, FocusManagerGotFocusEventArgs e) + private async void GlobalFocusManagerGotFocus(object? sender, FocusManagerGotFocusEventArgs e) { // In order to delegate cursor to the inner editor for WebView2. // When the control got focus, we invoke script to focus the editor. @@ -60,7 +60,7 @@ public sealed partial class ComposePage : ComposePageAbstract, x => box.TextChanged += x, x => box.TextChanged -= x) .Throttle(TimeSpan.FromMilliseconds(120)) - .ObserveOn(SynchronizationContext.Current) + .ObserveOn(SynchronizationContext.Current!) .Subscribe(t => { if (t.EventArgs.Reason == AutoSuggestionBoxTextChangeReason.UserInput) @@ -305,10 +305,15 @@ public sealed partial class ComposePage : ComposePageAbstract, ImportanceFlyout.Hide(); ImportanceSplitButton.IsChecked = true; - if (sender is Button senderButton) + if (sender is Button senderButton && senderButton.Tag is MessageImportance importance) { - ViewModel.SelectedMessageImportance = (MessageImportance)senderButton.Tag; - ((ImportanceSplitButton.Content as Viewbox).Child as SymbolIcon).Symbol = (senderButton.Content as SymbolIcon).Symbol; + ViewModel.SelectedMessageImportance = importance; + if (ImportanceSplitButton.Content is Viewbox viewbox && + viewbox.Child is SymbolIcon symbolIcon && + senderButton.Content is SymbolIcon contentIcon) + { + symbolIcon.Symbol = contentIcon.Symbol; + } } } @@ -332,7 +337,7 @@ public sealed partial class ComposePage : ComposePageAbstract, _ => null }; - AccountContact addedItem = null; + AccountContact? addedItem = null; if (addressCollection != null) addedItem = await ViewModel.GetAddressInformationAsync(currentText, addressCollection); diff --git a/Wino.Mail.WinUI/Views/ImapSetup/AdvancedImapSetupPage.xaml.cs b/Wino.Mail.WinUI/Views/ImapSetup/AdvancedImapSetupPage.xaml.cs index 3968e8a7..2c7ded49 100644 --- a/Wino.Mail.WinUI/Views/ImapSetup/AdvancedImapSetupPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/ImapSetup/AdvancedImapSetupPage.xaml.cs @@ -200,15 +200,15 @@ public sealed partial class AdvancedImapSetupPage : Page IncomingServerPassword = PasswordBox.Password, IncomingServerType = Core.Domain.Enums.CustomIncomingServerType.IMAP4, IncomingServerUsername = UsernameBox.Text, - IncomingAuthenticationMethod = (IncomingAuthenticationMethod.SelectedItem as ImapAuthenticationMethodModel).ImapAuthenticationMethod, - IncomingServerSocketOption = (IncomingConnectionSecurity.SelectedItem as ImapConnectionSecurityModel).ImapConnectionSecurity, + IncomingAuthenticationMethod = (IncomingAuthenticationMethod.SelectedItem as ImapAuthenticationMethodModel)!.ImapAuthenticationMethod, + IncomingServerSocketOption = (IncomingConnectionSecurity.SelectedItem as ImapConnectionSecurityModel)!.ImapConnectionSecurity, IncomingServerPort = IncomingServerPortBox.Text, OutgoingServer = GetServerWithoutPort(OutgoingServerBox.Text), OutgoingServerPort = OutgoingServerPort.Text, OutgoingServerPassword = OutgoingPasswordBox.Password, - OutgoingAuthenticationMethod = (OutgoingAuthenticationMethod.SelectedItem as ImapAuthenticationMethodModel).ImapAuthenticationMethod, - OutgoingServerSocketOption = (OutgoingConnectionSecurity.SelectedItem as ImapConnectionSecurityModel).ImapConnectionSecurity, + OutgoingAuthenticationMethod = (OutgoingAuthenticationMethod.SelectedItem as ImapAuthenticationMethodModel)!.ImapAuthenticationMethod, + OutgoingServerSocketOption = (OutgoingConnectionSecurity.SelectedItem as ImapConnectionSecurityModel)!.ImapConnectionSecurity, OutgoingServerUsername = OutgoingUsernameBox.Text, ProxyServer = ProxyServerBox.Text, diff --git a/Wino.Mail.WinUI/Views/ImapSetup/ImapConnectionFailedPage.xaml.cs b/Wino.Mail.WinUI/Views/ImapSetup/ImapConnectionFailedPage.xaml.cs index ecee8537..201687a1 100644 --- a/Wino.Mail.WinUI/Views/ImapSetup/ImapConnectionFailedPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/ImapSetup/ImapConnectionFailedPage.xaml.cs @@ -13,10 +13,10 @@ namespace Wino.Views.ImapSetup; public sealed partial class ImapConnectionFailedPage : Page { - private string _protocolLog; + private string? _protocolLog; - private readonly IClipboardService _clipboardService = App.Current.Services.GetService(); - private readonly IMailDialogService _dialogService = App.Current.Services.GetService(); + private readonly IClipboardService _clipboardService = App.Current.Services.GetService()!; + private readonly IMailDialogService _dialogService = App.Current.Services.GetService()!; public ImapConnectionFailedPage() { diff --git a/Wino.Mail.WinUI/Views/ImapSetup/TestingImapConnectionPage.xaml.cs b/Wino.Mail.WinUI/Views/ImapSetup/TestingImapConnectionPage.xaml.cs index 4d99cbdf..f81cdaa3 100644 --- a/Wino.Mail.WinUI/Views/ImapSetup/TestingImapConnectionPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/ImapSetup/TestingImapConnectionPage.xaml.cs @@ -15,8 +15,8 @@ namespace Wino.Views.ImapSetup; public sealed partial class TestingImapConnectionPage : Page { - private AutoDiscoverySettings autoDiscoverySettings; - private CustomServerInformation serverInformationToTest; + private AutoDiscoverySettings autoDiscoverySettings = null!; + private CustomServerInformation serverInformationToTest = null!; public TestingImapConnectionPage() { diff --git a/Wino.Mail.WinUI/Views/ImapSetup/WelcomeImapSetupPage.xaml.cs b/Wino.Mail.WinUI/Views/ImapSetup/WelcomeImapSetupPage.xaml.cs index 375cad9c..3c7d1752 100644 --- a/Wino.Mail.WinUI/Views/ImapSetup/WelcomeImapSetupPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/ImapSetup/WelcomeImapSetupPage.xaml.cs @@ -19,7 +19,7 @@ namespace Wino.Views.ImapSetup; public sealed partial class WelcomeImapSetupPage : Page { - private readonly IAutoDiscoveryService _autoDiscoveryService = App.Current.Services.GetService(); + private readonly IAutoDiscoveryService _autoDiscoveryService = App.Current.Services.GetService()!; public WelcomeImapSetupPage() { diff --git a/Wino.Mail.WinUI/Views/MailListPage.xaml b/Wino.Mail.WinUI/Views/MailListPage.xaml index 3ef0f785..9bce541f 100644 --- a/Wino.Mail.WinUI/Views/MailListPage.xaml +++ b/Wino.Mail.WinUI/Views/MailListPage.xaml @@ -184,14 +184,9 @@ LostFocus="SearchBarUnfocused" PlaceholderText="{x:Bind domain:Translator.SearchBarPlaceholder}" QueryIcon="Find" + QuerySubmitted="SearchbarQuerySubmitted" Text="{x:Bind ViewModel.SearchQuery, Mode=TwoWay}" - TextChanged="SearchBar_TextChanged"> - - - - - - + TextChanged="SearchBar_TextChanged" /> diff --git a/Wino.Mail.WinUI/Views/MailListPage.xaml.cs b/Wino.Mail.WinUI/Views/MailListPage.xaml.cs index f41e69cb..ec037620 100644 --- a/Wino.Mail.WinUI/Views/MailListPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/MailListPage.xaml.cs @@ -188,7 +188,7 @@ public sealed partial class MailListPage : MailListPageAbstract, targetItems = ViewModel.MailCollection.SelectedItems; var availableActions = ViewModel.GetAvailableMailActions(targetItems); - if (!availableActions?.Any() ?? false) return; + if (availableActions == null || !availableActions.Any()) return; var clickedOperation = await GetMailOperationFromFlyoutAsync(availableActions, control, p.X, p.Y); @@ -738,4 +738,10 @@ public sealed partial class MailListPage : MailListPageAbstract, await WinoClickItemInternalAsync(e.ClickedItem); } + + private void SearchbarQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + { + if (ViewModel.PerformSearchCommand.CanExecute(null)) + ViewModel.PerformSearchCommand.Execute(null); + } } diff --git a/Wino.Mail.WinUI/Views/MailRenderingPage.xaml.cs b/Wino.Mail.WinUI/Views/MailRenderingPage.xaml.cs index 6fe45934..04238328 100644 --- a/Wino.Mail.WinUI/Views/MailRenderingPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/MailRenderingPage.xaml.cs @@ -28,8 +28,8 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract, IRecipient, IRecipient { - private readonly IPreferencesService _preferencesService = App.Current.Services.GetService(); - private readonly IMailDialogService _dialogService = App.Current.Services.GetService(); + private readonly IPreferencesService _preferencesService = App.Current.Services.GetService()!; + private readonly IMailDialogService _dialogService = App.Current.Services.GetService()!; private bool isRenderingInProgress = false; private TaskCompletionSource DOMLoadedTask = new TaskCompletionSource(); @@ -232,7 +232,7 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract, // TODO: Check external link navigation setting is enabled. // Open all external urls in launcher. - if (args.Cancel && Uri.TryCreate(args.Uri, UriKind.Absolute, out Uri newUri)) + if (args.Cancel && Uri.TryCreate(args.Uri, UriKind.Absolute, out Uri? newUri) && newUri != null) { await Launcher.LaunchUriAsync(newUri); } @@ -242,7 +242,7 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract, { if (e.ClickedItem is MailAttachmentViewModel attachmentViewModel) { - ViewModel.OpenAttachmentCommand.Execute(attachmentViewModel); + ViewModel?.OpenAttachmentCommand.Execute(attachmentViewModel); } } diff --git a/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj b/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj index 05a4576e..d74bef08 100644 --- a/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj +++ b/Wino.Mail.WinUI/Wino.Mail.WinUI.csproj @@ -11,8 +11,17 @@ true true enable + + + False + True + True + true + + $(DefineConstants);DISABLE_XAML_GENERATED_MAIN - + + @@ -259,11 +268,14 @@ - + False True + + False True + True False True