Main app aot compatibility.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>;
|
||||
|
||||
|
||||
@@ -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,7 +120,9 @@ public partial class ImagePreviewControl : Control
|
||||
{
|
||||
// Show favicon in squircle
|
||||
FaviconSquircle.Visibility = Visibility.Visible;
|
||||
if (InitialsGrid != null)
|
||||
InitialsGrid.Visibility = Visibility.Collapsed;
|
||||
if (KnownHostImage != null)
|
||||
KnownHostImage.Visibility = Visibility.Collapsed;
|
||||
|
||||
var bitmapImage = await GetBitmapImageAsync(contactPicture);
|
||||
@@ -133,8 +135,11 @@ public partial class ImagePreviewControl : Control
|
||||
else
|
||||
{
|
||||
// Show normal avatar (tondo)
|
||||
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,7 +150,9 @@ public partial class ImagePreviewControl : Control
|
||||
{
|
||||
if (!contactPictureLoadingCancellationTokenSource?.Token.IsCancellationRequested ?? false)
|
||||
{
|
||||
if (Ellipse != null)
|
||||
Ellipse.Fill = brush;
|
||||
if (InitialsTextblock != null)
|
||||
InitialsTextblock.Text = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -158,19 +165,24 @@ public partial class ImagePreviewControl : Control
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
|
||||
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";
|
||||
|
||||
@@ -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 (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,6 +45,7 @@ public sealed partial class AccountReorderDialog : ContentDialog
|
||||
|
||||
var dict = Accounts.ToDictionary(a => a.StartupEntityId, a => Accounts.IndexOf(a));
|
||||
|
||||
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,6 +110,7 @@ public partial class FilterMenuFlyout : MenuFlyout
|
||||
|
||||
var optionModel = button.Tag as SortingOption;
|
||||
|
||||
if (optionModel != null)
|
||||
SelectSortingOption(optionModel);
|
||||
}
|
||||
}
|
||||
@@ -124,6 +125,7 @@ public partial class FilterMenuFlyout : MenuFlyout
|
||||
|
||||
var optionModel = button.Tag as FilterOption;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user