Main app aot compatibility.

This commit is contained in:
Burak Kaan Köse
2025-11-14 18:51:48 +01:00
parent ae64094feb
commit b356af8eb4
41 changed files with 220 additions and 327 deletions
+3
View File
@@ -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
@@ -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<IActivatedEventArgs>
{
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;
}
@@ -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<FileActivatedEventArgs>
{
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();
}
@@ -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;
/// <summary>
/// This handler will only handle the toasts that runs on foreground.
/// Background executions are not handled here like mark as read or delete.
/// </summary>
internal class ToastNotificationActivationHandler : ActivationHandler<ToastNotificationActivatedEventArgs>
{
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<ILaunchProtocolService>();
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;
}
}
+7 -2
View File
@@ -75,6 +75,9 @@ public sealed partial class AppShell : AppShellAbstract,
var mailCopies = new List<MailCopy>();
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)
{
@@ -17,13 +17,13 @@ namespace Wino.Behaviors;
public partial class BindableCommandBarBehavior : Behavior<CommandBar>
{
private readonly IPreferencesService _preferencesService = App.Current.Services.GetService<IPreferencesService>();
private readonly IPreferencesService? _preferencesService = App.Current.Services.GetService<IPreferencesService>();
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<CommandBar>
{
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<CommandBar>
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<CommandBar>
UpdatePrimaryCommands();
}
private void PrimaryCommandsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void PrimaryCommandsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
UpdatePrimaryCommands();
}
@@ -58,7 +58,7 @@ public class CreateMailNavigationItemBehavior : Behavior<WinoNavigationViewItem>
}
}
private void MenuCollectionUpdated(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
private void MenuCollectionUpdated(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
ManageAccounts();
}
@@ -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();
}
@@ -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<object>? CastedItemsSource => ItemsSource as IEnumerable<object>;
+40 -28
View File
@@ -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<ImageBrush> GetContactImageBrushAsync(string base64)
private static async Task<ImageBrush?> 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<BitmapImage> GetBitmapImageAsync(string base64)
private static async Task<BitmapImage?> GetBitmapImageAsync(string base64)
{
try
{
@@ -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);
}
}
@@ -19,9 +19,9 @@ namespace Wino.Mail.Controls;
public sealed partial class WebViewEditorControl : Control, IDisposable
{
private readonly INativeAppService _nativeAppService = App.Current.Services.GetService<INativeAppService>();
private readonly IFontService _fontService = App.Current.Services.GetService<IFontService>();
private readonly IPreferencesService _preferencesService = App.Current.Services.GetService<IPreferencesService>();
private readonly INativeAppService _nativeAppService = App.Current.Services.GetService<INativeAppService>()!;
private readonly IFontService _fontService = App.Current.Services.GetService<IFontService>()!;
private readonly IPreferencesService _preferencesService = App.Current.Services.GetService<IPreferencesService>()!;
[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<bool> _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<string> GetHtmlBodyAsync()
public async Task<string?> 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";
+6 -6
View File
@@ -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));
@@ -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;
}
@@ -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<IAccountProviderDetailViewModel> Accounts { get; }
public ObservableCollection<IAccountProviderDetailViewModel> Accounts { get; set; } = null!;
private int count;
private bool isOrdering = false;
private readonly IAccountService _accountService = App.Current.Services.GetService<IAccountService>();
private readonly IAccountService? _accountService = App.Current.Services.GetService<IAccountService>();
public AccountReorderDialog(ObservableCollection<IAccountProviderDetailViewModel> accounts)
public AccountReorderDialog(ObservableCollection<IAccountProviderDetailViewModel>? 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;
}
@@ -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();
@@ -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);
@@ -8,8 +8,8 @@ namespace Wino.Mail.Dialogs;
public sealed partial class MessageSourceDialog : ContentDialog
{
private readonly IClipboardService _clipboardService = App.Current.Services.GetService<IClipboardService>();
public string MessageSource { get; set; }
private readonly IClipboardService? _clipboardService = App.Current.Services.GetService<IClipboardService>();
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;
}
}
@@ -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<IMailItemFolder> FolderList { get; set; }
public List<IMailItemFolder> FolderList { get; set; } = [];
public MoveMailDialog(List<IMailItemFolder> allFolders)
{
@@ -58,7 +58,7 @@ public sealed partial class MoveMailDialog : ContentDialog
container.IsExpanded = !container.IsExpanded;
}
}
SelectedFolder = null;
SelectedFolder = null!;
}
else
{
@@ -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;
@@ -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)
{
@@ -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<MailItemFolder> 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<MailItemFolder> 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<MailItemFolder>()
var allSpecialFolders = new List<MailItemFolder?>()
{
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<Guid>(allSpecialFolders.Where(a => a != null).Select(x => x.Id)).Count != allSpecialFolders.Where(a => a != null).Count())
ValidationErrorTextBlock.Text = Translator.SystemFolderConfigDialogValidation_DuplicateSystemFolders;
if (new HashSet<Guid>(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);
@@ -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);
}
}
@@ -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<MoveButtonFlyout, MoveButtonMenuItemClickedEventArgs> MenuItemClick;
public event TypedEventHandler<MoveButtonFlyout, MoveButtonMenuItemClickedEventArgs> MenuItemClick = delegate { };
public static readonly DependencyProperty FoldersProperty = DependencyProperty.Register(nameof(Folders), typeof(List<MailItemFolder>), typeof(MoveButtonFlyout), new PropertyMetadata(null, new PropertyChangedCallback(OnFoldersChanged)));
public List<MailItemFolder> 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()
{
@@ -7,7 +7,7 @@ namespace Wino.MenuFlyouts;
public partial class WinoOperationFlyout<TActionType> : MenuFlyout, IDisposable where TActionType : class
{
public TActionType ClickedOperation { get; set; }
public TActionType ClickedOperation { get; set; } = null!;
protected readonly IEnumerable<TActionType> AvailableActions;
@@ -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));
}
}
@@ -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));
}
}
@@ -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;
/// </summary>
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));
}
}
+2 -2
View File
@@ -149,7 +149,7 @@ public class DialogService : DialogServiceBase, IMailDialogService
return accountPicker.PickedAccount;
}
public async Task<AccountSignature> ShowSignatureEditorDialog(AccountSignature signatureModel = null)
public async Task<AccountSignature> 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)
@@ -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)
{
+3 -2
View File
@@ -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<IProviderDetail> GetAvailableProviders()
+5 -1
View File
@@ -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)
{
+11 -6
View File
@@ -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);
@@ -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,
@@ -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<IClipboardService>();
private readonly IMailDialogService _dialogService = App.Current.Services.GetService<IMailDialogService>();
private readonly IClipboardService _clipboardService = App.Current.Services.GetService<IClipboardService>()!;
private readonly IMailDialogService _dialogService = App.Current.Services.GetService<IMailDialogService>()!;
public ImapConnectionFailedPage()
{
@@ -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()
{
@@ -19,7 +19,7 @@ namespace Wino.Views.ImapSetup;
public sealed partial class WelcomeImapSetupPage : Page
{
private readonly IAutoDiscoveryService _autoDiscoveryService = App.Current.Services.GetService<IAutoDiscoveryService>();
private readonly IAutoDiscoveryService _autoDiscoveryService = App.Current.Services.GetService<IAutoDiscoveryService>()!;
public WelcomeImapSetupPage()
{
+2 -7
View File
@@ -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">
<i:Interaction.Behaviors>
<i:EventTriggerBehavior EventName="QuerySubmitted">
<i:InvokeCommandAction Command="{x:Bind ViewModel.PerformSearchCommand}" />
</i:EventTriggerBehavior>
</i:Interaction.Behaviors>
</AutoSuggestBox>
TextChanged="SearchBar_TextChanged" />
</Grid>
</wino:BasePage.ShellContent>
+7 -1
View File
@@ -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);
}
}
@@ -28,8 +28,8 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
IRecipient<CancelRenderingContentRequested>,
IRecipient<ApplicationThemeChanged>
{
private readonly IPreferencesService _preferencesService = App.Current.Services.GetService<IPreferencesService>();
private readonly IMailDialogService _dialogService = App.Current.Services.GetService<IMailDialogService>();
private readonly IPreferencesService _preferencesService = App.Current.Services.GetService<IPreferencesService>()!;
private readonly IMailDialogService _dialogService = App.Current.Services.GetService<IMailDialogService>()!;
private bool isRenderingInProgress = false;
private TaskCompletionSource<bool> DOMLoadedTask = new TaskCompletionSource<bool>();
@@ -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);
}
}
+13 -1
View File
@@ -11,8 +11,17 @@
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<Nullable>enable</Nullable>
<!-- AOT / Trimming -->
<PublishAot Condition="'$(Configuration)' == 'Debug'">False</PublishAot>
<PublishAot Condition="'$(Configuration)' != 'Debug'">True</PublishAot>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<!-- Single instancing -->
<DefineConstants>$(DefineConstants);DISABLE_XAML_GENERATED_MAIN</DefineConstants>
</PropertyGroup>
</PropertyGroup>
<ItemGroup>
<Content Remove="Assets\BadgeLogo.scale-100.png" />
<Content Remove="Assets\BadgeLogo.scale-125.png" />
@@ -262,8 +271,11 @@
<PropertyGroup>
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
<!-- Trimming -->
<PublishTrimmed Condition="'$(Configuration)' == 'Debug'">False</PublishTrimmed>
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>
<GenerateTemporaryStoreCertificate>True</GenerateTemporaryStoreCertificate>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>