Initial event composing.
This commit is contained in:
@@ -171,6 +171,7 @@ public partial class App : WinoApplication,
|
||||
services.AddTransient(typeof(CalendarSettingsPageViewModel));
|
||||
services.AddTransient(typeof(CalendarAccountSettingsPageViewModel));
|
||||
services.AddTransient(typeof(EventDetailsPageViewModel));
|
||||
services.AddTransient(typeof(CalendarEventComposePageViewModel));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -14,7 +14,6 @@ using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Helpers;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Mail.WinUI;
|
||||
|
||||
@@ -176,7 +175,7 @@ public sealed partial class CalendarMailItemDisplayInformationControl : UserCont
|
||||
}
|
||||
|
||||
using var stream = new MemoryStream();
|
||||
calendarMimePart.Content.DecodeTo(stream);
|
||||
calendarMimePart.Content?.DecodeTo(stream);
|
||||
var contentBytes = stream.ToArray();
|
||||
|
||||
if (contentBytes.Length == 0)
|
||||
|
||||
@@ -9,6 +9,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Mail.WinUI;
|
||||
|
||||
@@ -30,6 +31,15 @@ public sealed partial class ImagePreviewControl : PersonPicture
|
||||
[GeneratedDependencyProperty]
|
||||
public partial IMailItemDisplayInformation? MailItemInformation { get; set; }
|
||||
|
||||
[GeneratedDependencyProperty]
|
||||
public partial AccountContact? PreviewContact { get; set; }
|
||||
|
||||
[GeneratedDependencyProperty]
|
||||
public partial string? Address { get; set; }
|
||||
|
||||
[GeneratedDependencyProperty]
|
||||
public partial string? DisplayNameOverride { get; set; }
|
||||
|
||||
private readonly IThumbnailService? _thumbnailService;
|
||||
private readonly IPreferencesService? _preferencesService;
|
||||
private readonly IContactPictureFileService? _contactPictureFileService;
|
||||
@@ -73,6 +83,11 @@ public sealed partial class ImagePreviewControl : PersonPicture
|
||||
|
||||
RequestRefresh();
|
||||
}
|
||||
|
||||
partial void OnPreviewContactPropertyChanged(DependencyPropertyChangedEventArgs e) => RequestRefresh();
|
||||
partial void OnAddressPropertyChanged(DependencyPropertyChangedEventArgs e) => RequestRefresh();
|
||||
partial void OnDisplayNameOverridePropertyChanged(DependencyPropertyChangedEventArgs e) => RequestRefresh();
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RequestRefresh();
|
||||
@@ -262,7 +277,7 @@ public sealed partial class ImagePreviewControl : PersonPicture
|
||||
var address = ResolveAddress();
|
||||
var displayName = ResolveDisplayName(address);
|
||||
var base64Picture = ResolveBase64Picture();
|
||||
var contactPictureFileId = MailItemInformation?.SenderContact?.ContactPictureFileId;
|
||||
var contactPictureFileId = PreviewContact?.ContactPictureFileId ?? MailItemInformation?.SenderContact?.ContactPictureFileId;
|
||||
|
||||
return new RefreshSnapshot(displayName, address, contactPictureFileId, base64Picture);
|
||||
}).ConfigureAwait(false);
|
||||
@@ -270,6 +285,12 @@ public sealed partial class ImagePreviewControl : PersonPicture
|
||||
|
||||
private string ResolveAddress()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(PreviewContact?.Address))
|
||||
return PreviewContact.Address.Trim();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Address))
|
||||
return Address.Trim();
|
||||
|
||||
if (MailItemInformation == null)
|
||||
return string.Empty;
|
||||
|
||||
@@ -285,6 +306,12 @@ public sealed partial class ImagePreviewControl : PersonPicture
|
||||
|
||||
private string ResolveDisplayName(string resolvedAddress)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(PreviewContact?.Name))
|
||||
return PreviewContact.Name.Trim();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(DisplayNameOverride))
|
||||
return DisplayNameOverride.Trim();
|
||||
|
||||
var contactName = MailItemInformation?.SenderContact?.Name;
|
||||
if (!string.IsNullOrWhiteSpace(contactName))
|
||||
return contactName.Trim();
|
||||
@@ -297,6 +324,9 @@ public sealed partial class ImagePreviewControl : PersonPicture
|
||||
|
||||
private string ResolveBase64Picture()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(PreviewContact?.Base64ContactPicture))
|
||||
return PreviewContact.Base64ContactPicture;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(MailItemInformation?.SenderContact?.Base64ContactPicture))
|
||||
return MailItemInformation.SenderContact.Base64ContactPicture;
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.SingleCalendarPickerDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:calendar="using:Wino.Core.Domain.Models.Calendar"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:helpers="using:Wino.Helpers"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:sharedCalendar="using:Wino.Core.Domain.Entities.Calendar"
|
||||
Title="{x:Bind domain:Translator.CalendarEventCompose_PickCalendarTitle}"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.Buttons_Cancel}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMinWidth">420</x:Double>
|
||||
<Style
|
||||
x:Key="CalendarPickerListItemStyle"
|
||||
BasedOn="{StaticResource DefaultListViewItemStyle}"
|
||||
TargetType="ListViewItem">
|
||||
<Setter Property="Padding" Value="12,10" />
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
<Setter Property="Margin" Value="0,2" />
|
||||
</Style>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<ScrollViewer Margin="0,8,0,0">
|
||||
<ItemsControl ItemsSource="{x:Bind AvailableGroups}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Margin="0,0,0,12" Spacing="6">
|
||||
<TextBlock FontWeight="SemiBold">
|
||||
<Run Text="{Binding Account.Name}" />
|
||||
<Run Text=" (" />
|
||||
<Run Text="{Binding Account.Address}" />
|
||||
<Run Text=")" />
|
||||
</TextBlock>
|
||||
|
||||
<ListView
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="CalendarClicked"
|
||||
ItemContainerStyle="{StaticResource CalendarPickerListItemStyle}"
|
||||
ItemsSource="{Binding Calendars}"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid ColumnSpacing="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Ellipse
|
||||
Width="14"
|
||||
Height="14"
|
||||
VerticalAlignment="Center"
|
||||
Fill="{ThemeResource AccentFillColorDefaultBrush}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Name}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</ContentDialog>
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Entities.Calendar;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class SingleCalendarPickerDialog : ContentDialog
|
||||
{
|
||||
public AccountCalendar? PickedCalendar { get; private set; }
|
||||
|
||||
public List<CalendarPickerAccountGroup> AvailableGroups { get; } = [];
|
||||
|
||||
public SingleCalendarPickerDialog(List<CalendarPickerAccountGroup> availableGroups)
|
||||
{
|
||||
AvailableGroups = availableGroups;
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void CalendarClicked(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
PickedCalendar = e.ClickedItem as AccountCalendar;
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,14 @@ using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities.Calendar;
|
||||
using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
using Wino.Core.Domain.Models.Folders;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Mail.WinUI.Extensions;
|
||||
@@ -122,6 +124,18 @@ public class DialogService : DialogServiceBase, IMailDialogService
|
||||
return accountPicker.PickedAccount ?? null!;
|
||||
}
|
||||
|
||||
public async Task<AccountCalendar> ShowSingleCalendarPickerDialogAsync(List<CalendarPickerAccountGroup> availableCalendarGroups)
|
||||
{
|
||||
var calendarPicker = new SingleCalendarPickerDialog(availableCalendarGroups)
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
await HandleDialogPresentationAsync(calendarPicker);
|
||||
|
||||
return calendarPicker.PickedCalendar ?? null!;
|
||||
}
|
||||
|
||||
public async Task<AccountSignature> ShowSignatureEditorDialog(AccountSignature? signatureModel = null)
|
||||
{
|
||||
SignatureEditorDialog signatureEditorDialog;
|
||||
|
||||
@@ -120,6 +120,40 @@ public class DialogServiceBase : IDialogServiceBase
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public async Task<List<PickedFileMetadata>> PickFilesMetadataAsync(params object[] typeFilters)
|
||||
{
|
||||
var returnList = new List<PickedFileMetadata>();
|
||||
var picker = new FileOpenPicker
|
||||
{
|
||||
ViewMode = PickerViewMode.Thumbnail,
|
||||
SuggestedStartLocation = PickerLocationId.Desktop
|
||||
};
|
||||
|
||||
foreach (var filter in typeFilters)
|
||||
{
|
||||
picker.FileTypeFilter.Add(filter.ToString());
|
||||
}
|
||||
|
||||
var mainWindow = WinoApplication.MainWindow;
|
||||
if (mainWindow == null) return returnList;
|
||||
|
||||
nint windowHandle = WindowNative.GetWindowHandle(mainWindow);
|
||||
InitializeWithWindow.Initialize(picker, windowHandle);
|
||||
|
||||
var files = await picker.PickMultipleFilesAsync();
|
||||
if (files == null) return returnList;
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
StorageApplicationPermissions.FutureAccessList.Add(file);
|
||||
|
||||
var basicProperties = await file.GetBasicPropertiesAsync();
|
||||
returnList.Add(new PickedFileMetadata(file.Path, (long)basicProperties.Size));
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private async Task<StorageFile?> PickFileAsync(params object[] typeFilters)
|
||||
{
|
||||
var picker = new FileOpenPicker
|
||||
|
||||
@@ -55,7 +55,8 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
||||
private static readonly WinoPage[] CalendarOnlyPages =
|
||||
[
|
||||
WinoPage.CalendarPage,
|
||||
WinoPage.EventDetailsPage
|
||||
WinoPage.EventDetailsPage,
|
||||
WinoPage.CalendarEventComposePage
|
||||
];
|
||||
|
||||
public NavigationService(IStatePersistanceService statePersistanceService, IDispatcher dispatcher, IWinoWindowManager windowManager)
|
||||
@@ -126,6 +127,7 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
||||
WinoPage.SpecialImapCredentialsPage => typeof(SpecialImapCredentialsPage),
|
||||
WinoPage.CalendarPage => typeof(CalendarPage),
|
||||
WinoPage.EventDetailsPage => typeof(EventDetailsPage),
|
||||
WinoPage.CalendarEventComposePage => typeof(CalendarEventComposePage),
|
||||
WinoPage.CalendarSettingsPage => typeof(CalendarSettingsPage),
|
||||
WinoPage.CalendarAccountSettingsPage => typeof(CalendarAccountSettingsPage),
|
||||
_ => null,
|
||||
@@ -248,7 +250,7 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
||||
}
|
||||
|
||||
_statePersistanceService.IsReadingMail = _renderingPageTypes.Contains(page);
|
||||
_statePersistanceService.IsEventDetailsVisible = page == WinoPage.EventDetailsPage;
|
||||
_statePersistanceService.IsEventDetailsVisible = page == WinoPage.EventDetailsPage || page == WinoPage.CalendarEventComposePage;
|
||||
|
||||
Frame? innerShellFrame = GetCoreFrameInternal(NavigationReferenceFrame.InnerShellFrame);
|
||||
if (innerShellFrame == null && frame == NavigationReferenceFrame.ShellFrame)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
using Wino.Calendar.ViewModels;
|
||||
|
||||
namespace Wino.Mail.WinUI.Views.Abstract;
|
||||
|
||||
public abstract class CalendarEventComposePageAbstract : BasePage<CalendarEventComposePageViewModel> { }
|
||||
@@ -149,14 +149,26 @@
|
||||
<SplitView.Pane>
|
||||
<Grid Padding="0,0,0,6">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Button
|
||||
Margin="14,12,14,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{x:Bind ViewModel.NewEventCommand}"
|
||||
Style="{StaticResource AccentButtonStyle}">
|
||||
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Spacing="8">
|
||||
<coreControls:WinoFontIcon FontSize="16" Icon="NewMail" />
|
||||
<TextBlock Text="{x:Bind domain:Translator.CalendarEventCompose_NewEventButton}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<calendarControls:WinoCalendarView
|
||||
x:Name="CalendarView"
|
||||
Grid.Row="0"
|
||||
Grid.Row="1"
|
||||
Margin="0,12,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
DateClickedCommand="{x:Bind ViewModel.DateClickedCommand}"
|
||||
@@ -167,7 +179,7 @@
|
||||
<!-- Account Calendars Host -->
|
||||
<ListView
|
||||
x:Name="CalendarHostListView"
|
||||
Grid.Row="1"
|
||||
Grid.Row="2"
|
||||
ItemsSource="{x:Bind ViewModel.AccountCalendarStateService.GroupedAccountCalendars}"
|
||||
SelectionMode="None">
|
||||
<ListView.Header>
|
||||
@@ -261,7 +273,7 @@
|
||||
|
||||
<!-- Menu Items -->
|
||||
<ListView
|
||||
Grid.Row="2"
|
||||
Grid.Row="3"
|
||||
ItemTemplateSelector="{StaticResource NavigationMenuTemplateSelector}"
|
||||
SelectedIndex="{x:Bind ViewModel.SelectedMenuItemIndex, Mode=TwoWay}">
|
||||
<ListView.Items>
|
||||
|
||||
@@ -0,0 +1,533 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<abstract:CalendarEventComposePageAbstract
|
||||
x:Class="Wino.Calendar.Views.CalendarEventComposePage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:abstract="using:Wino.Mail.WinUI.Views.Abstract"
|
||||
xmlns:calendarViewModels="using:Wino.Calendar.ViewModels"
|
||||
xmlns:controls="using:Wino.Controls"
|
||||
xmlns:coreControls="using:Wino.Mail.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:data="using:Wino.Calendar.ViewModels.Data"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:mailControls="using:Wino.Mail.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:shared="using:Wino.Core.Domain.Entities.Shared"
|
||||
xmlns:toolkit="using:CommunityToolkit.WinUI.Controls"
|
||||
Style="{StaticResource PageStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Page.Resources>
|
||||
<Style
|
||||
x:Key="TransparentActionButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="12,8" />
|
||||
<Setter Property="MinWidth" Value="0" />
|
||||
<Setter Property="MinHeight" Value="0" />
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="ComposeCreateButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Background" Value="{ThemeResource AccentFillColorDefaultBrush}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextOnAccentFillColorPrimaryBrush}" />
|
||||
<Setter Property="Padding" Value="16,8" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="EventDetailsPanelGridStyle" TargetType="Grid">
|
||||
<Setter Property="Padding" Value="12,6" />
|
||||
<Setter Property="Margin" Value="0,12" />
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorSecondaryBrush}" />
|
||||
<Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" />
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="EventDetailsPanelTitleStyle"
|
||||
BasedOn="{StaticResource SubtitleTextBlockStyle}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="Margin" Value="0,0,0,20" />
|
||||
</Style>
|
||||
|
||||
<DataTemplate x:Key="AttendeeSuggestionTemplate">
|
||||
<StackPanel Padding="8,4" Orientation="Vertical">
|
||||
<TextBlock FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
<TextBlock FontSize="12" Text="{Binding Address}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="AttendeeTokenTemplate">
|
||||
<TextBlock Text="{Binding DisplayName}" />
|
||||
</DataTemplate>
|
||||
</Page.Resources>
|
||||
|
||||
<Grid Padding="20">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border
|
||||
VerticalAlignment="Top"
|
||||
Background="{ThemeResource WinoContentZoneBackgroud}"
|
||||
BorderBrush="{StaticResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="7">
|
||||
<ScrollViewer
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
HorizontalScrollMode="Enabled"
|
||||
VerticalScrollBarVisibility="Disabled"
|
||||
VerticalScrollMode="Disabled">
|
||||
<StackPanel
|
||||
Padding="8"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<Button Command="{x:Bind ViewModel.CreateCommand}" Style="{StaticResource ComposeCreateButtonStyle}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<coreControls:WinoFontIcon FontSize="16" Icon="Save" />
|
||||
<TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.Buttons_Create}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<StackPanel
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<coreControls:WinoFontIcon FontSize="16" Icon="CalendarShowAs" />
|
||||
<ComboBox
|
||||
Width="190"
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{x:Bind ViewModel.AvailableCalendars}"
|
||||
PlaceholderText="{x:Bind domain:Translator.CalendarEventCompose_SelectCalendar}"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedCalendar, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Vertical" Spacing="2">
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Account.Address}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<coreControls:WinoFontIcon FontSize="16" Icon="CalendarShowAs" />
|
||||
<ComboBox
|
||||
Width="150"
|
||||
DisplayMemberPath="DisplayText"
|
||||
ItemsSource="{x:Bind ViewModel.ShowAsOptions}"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedShowAsOption, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<coreControls:WinoFontIcon FontSize="16" Icon="Reminder" />
|
||||
<ComboBox
|
||||
Width="150"
|
||||
DisplayMemberPath="DisplayText"
|
||||
ItemsSource="{x:Bind ViewModel.ReminderOptions}"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedReminderOption, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid x:Name="DetailsGrid" Style="{StaticResource EventDetailsPanelGridStyle}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Style="{StaticResource EventDetailsPanelTitleStyle}" Text="{x:Bind domain:Translator.CalendarEventDetails_Details}" />
|
||||
|
||||
<TextBox
|
||||
Grid.Row="1"
|
||||
Header="{x:Bind domain:Translator.CalendarEventCompose_Title}"
|
||||
PlaceholderText="{x:Bind domain:Translator.CalendarEventCompose_TitlePlaceholder}"
|
||||
Text="{x:Bind ViewModel.Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
|
||||
<Grid
|
||||
Grid.Row="2"
|
||||
Margin="0,12,0,0"
|
||||
ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<DatePicker
|
||||
Grid.Column="0"
|
||||
Date="{x:Bind ViewModel.StartDate, Mode=TwoWay}"
|
||||
Header="{x:Bind domain:Translator.CalendarEventCompose_StartDate}" />
|
||||
|
||||
<ToggleButton
|
||||
Grid.Column="1"
|
||||
Margin="0,30,0,0"
|
||||
IsChecked="{x:Bind ViewModel.IsAllDay, Mode=TwoWay}">
|
||||
<TextBlock Text="{x:Bind domain:Translator.CalendarEventCompose_AllDay}" />
|
||||
</ToggleButton>
|
||||
|
||||
<TimePicker
|
||||
Grid.Column="2"
|
||||
ClockIdentifier="{x:Bind ViewModel.TimePickerClockIdentifier, Mode=OneWay}"
|
||||
Header="{x:Bind domain:Translator.CalendarEventCompose_StartTime}"
|
||||
IsEnabled="{x:Bind ViewModel.IsAllDay, Mode=OneWay}"
|
||||
SelectedTime="{x:Bind ViewModel.StartTime, Mode=TwoWay}" />
|
||||
|
||||
<TimePicker
|
||||
Grid.Column="3"
|
||||
ClockIdentifier="{x:Bind ViewModel.TimePickerClockIdentifier, Mode=OneWay}"
|
||||
Header="{x:Bind domain:Translator.CalendarEventCompose_EndTime}"
|
||||
IsEnabled="{x:Bind ViewModel.IsAllDay, Mode=OneWay}"
|
||||
SelectedTime="{x:Bind ViewModel.EndTime, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
|
||||
<DatePicker
|
||||
Grid.Row="3"
|
||||
Margin="0,12,0,0"
|
||||
Date="{x:Bind ViewModel.AllDayEndDate, Mode=TwoWay}"
|
||||
Header="{x:Bind domain:Translator.CalendarEventCompose_EndDate}"
|
||||
Visibility="{x:Bind ViewModel.IsAllDay, Mode=OneWay}" />
|
||||
|
||||
<Grid
|
||||
Grid.Row="4"
|
||||
Margin="0,12,0,0"
|
||||
ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox
|
||||
Grid.Column="0"
|
||||
Header="{x:Bind domain:Translator.CalendarEventCompose_Location}"
|
||||
PlaceholderText="{x:Bind domain:Translator.CalendarEventCompose_LocationPlaceholder}"
|
||||
Text="{x:Bind ViewModel.Location, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
|
||||
<ToggleButton
|
||||
Grid.Column="1"
|
||||
Margin="0,30,0,0"
|
||||
IsChecked="{x:Bind ViewModel.IsRecurring, Mode=TwoWay}">
|
||||
<TextBlock Text="{x:Bind domain:Translator.CalendarEventCompose_Recurring}" />
|
||||
</ToggleButton>
|
||||
</Grid>
|
||||
|
||||
<Border
|
||||
Grid.Row="5"
|
||||
Margin="0,12,0,0"
|
||||
Padding="12"
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
CornerRadius="6"
|
||||
Visibility="{x:Bind ViewModel.IsRecurring, Mode=OneWay}">
|
||||
<StackPanel Spacing="12">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="80" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="140" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="170" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock VerticalAlignment="Center" Text="{x:Bind domain:Translator.CalendarEventCompose_RepeatEvery}" />
|
||||
<ComboBox
|
||||
Grid.Column="1"
|
||||
ItemsSource="{x:Bind ViewModel.RecurrenceIntervalOptions}"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedRecurrenceInterval, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind domain:Translator.CalendarEventCompose_Every}" />
|
||||
<ComboBox
|
||||
Grid.Column="3"
|
||||
DisplayMemberPath="DisplayText"
|
||||
ItemsSource="{x:Bind ViewModel.RecurrenceFrequencyOptions}"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedRecurrenceFrequencyOption, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Grid.Column="4"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind domain:Translator.CalendarEventCompose_ForWeekdays}" />
|
||||
<ItemsControl Grid.Column="5" ItemsSource="{x:Bind ViewModel.WeekdayOptions}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ToggleButton
|
||||
Width="32"
|
||||
Height="32"
|
||||
Padding="0"
|
||||
IsChecked="{Binding IsSelected, Mode=TwoWay}">
|
||||
<TextBlock HorizontalAlignment="Center" Text="{Binding Label}" />
|
||||
</ToggleButton>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
Grid.Column="6"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind domain:Translator.CalendarEventCompose_Until}" />
|
||||
<CalendarDatePicker
|
||||
Grid.Column="7"
|
||||
Date="{x:Bind ViewModel.RecurrenceEndDate, Mode=TwoWay}"
|
||||
PlaceholderText="{x:Bind domain:Translator.CalendarEventCompose_NoEndDate}" />
|
||||
<Button
|
||||
Grid.Column="8"
|
||||
Command="{x:Bind ViewModel.ClearRecurrenceEndDateCommand}"
|
||||
Style="{StaticResource TransparentActionButtonStyle}">
|
||||
<coreControls:WinoFontIcon FontSize="14" Icon="Dismiss" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Margin="0,12,0,0"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{x:Bind ViewModel.RecurrenceSummary, Mode=OneWay}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<Grid Grid.Row="7" Margin="0,12,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Margin="0,0,0,8"
|
||||
FontWeight="SemiBold"
|
||||
Text="{x:Bind domain:Translator.CalendarEventCompose_Notes}" />
|
||||
|
||||
<mailControls:WebViewEditorControl
|
||||
x:Name="NotesEditor"
|
||||
Grid.Row="1"
|
||||
Height="340"
|
||||
IsEditorDarkMode="{x:Bind ViewModel.IsDarkWebviewRenderer, Mode=OneWay}"
|
||||
IsEditorWebViewEditor="True" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
x:Name="PeopleGrid"
|
||||
Grid.Column="1"
|
||||
Style="{StaticResource EventDetailsPanelGridStyle}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Style="{StaticResource EventDetailsPanelTitleStyle}" Text="{x:Bind domain:Translator.CalendarEventDetails_People}" />
|
||||
|
||||
<toolkit:TokenizingTextBox
|
||||
x:Name="AttendeeBox"
|
||||
Grid.Row="1"
|
||||
BorderThickness="0"
|
||||
ItemsSource="{x:Bind ViewModel.Attendees, Mode=OneWay}"
|
||||
LostFocus="AddressBoxLostFocus"
|
||||
PlaceholderText="{x:Bind domain:Translator.CalendarEventDetails_InviteSomeone}"
|
||||
SuggestedItemTemplate="{StaticResource AttendeeSuggestionTemplate}"
|
||||
TokenDelimiter=";"
|
||||
TokenItemAdding="TokenItemAdding"
|
||||
TokenItemTemplate="{StaticResource AttendeeTokenTemplate}" />
|
||||
|
||||
<ListView
|
||||
Grid.Row="2"
|
||||
Margin="-12,12,0,0"
|
||||
ItemsSource="{x:Bind ViewModel.Attendees, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="0,6" ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:ImagePreviewControl
|
||||
Width="40"
|
||||
Height="40"
|
||||
Address="{Binding Email}"
|
||||
DisplayNameOverride="{Binding DisplayName}"
|
||||
PreviewContact="{Binding ResolvedContact}" />
|
||||
|
||||
<StackPanel Grid.Column="1" Spacing="4">
|
||||
<TextBlock
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding DisplayName}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
FontSize="13"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Email}"
|
||||
Visibility="{Binding HasDistinctDisplayName}" />
|
||||
</StackPanel>
|
||||
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Click="RemoveAttendeeClicked"
|
||||
Style="{StaticResource TransparentActionButtonStyle}"
|
||||
Tag="{Binding}">
|
||||
<coreControls:WinoFontIcon FontSize="14" Icon="Delete" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
x:Name="AttachmentsGrid"
|
||||
Grid.Column="2"
|
||||
Style="{StaticResource EventDetailsPanelGridStyle}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Style="{StaticResource EventDetailsPanelTitleStyle}" Text="{x:Bind domain:Translator.CalendarEventDetails_Attachments}" />
|
||||
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Left"
|
||||
Command="{x:Bind ViewModel.AddAttachmentsCommand}"
|
||||
Style="{StaticResource TransparentActionButtonStyle}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<coreControls:WinoFontIcon FontSize="14" Icon="EventAccept" />
|
||||
<TextBlock Text="{x:Bind domain:Translator.CalendarEventCompose_AddAttachment}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<ListView
|
||||
Grid.Row="2"
|
||||
Margin="-12,12,0,0"
|
||||
ItemsSource="{x:Bind ViewModel.Attachments, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Height="56" ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="40" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ContentControl
|
||||
VerticalAlignment="Center"
|
||||
Content="{Binding AttachmentType}"
|
||||
ContentTemplateSelector="{StaticResource FileTypeIconSelector}" />
|
||||
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="2">
|
||||
<TextBlock Text="{Binding FileName}" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding ReadableSize}" />
|
||||
</StackPanel>
|
||||
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Click="RemoveAttachmentClicked"
|
||||
Style="{StaticResource TransparentActionButtonStyle}"
|
||||
Tag="{Binding}">
|
||||
<coreControls:WinoFontIcon FontSize="14" Icon="Delete" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="WindowWidthStates">
|
||||
<VisualState x:Name="WideState">
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger MinWindowWidth="1200" />
|
||||
</VisualState.StateTriggers>
|
||||
</VisualState>
|
||||
<VisualState x:Name="MediumState">
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger MinWindowWidth="800" />
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="DetailsGrid.(Grid.Row)" Value="0" />
|
||||
<Setter Target="DetailsGrid.(Grid.Column)" Value="0" />
|
||||
<Setter Target="DetailsGrid.(Grid.RowSpan)" Value="2" />
|
||||
<Setter Target="PeopleGrid.(Grid.Row)" Value="0" />
|
||||
<Setter Target="PeopleGrid.(Grid.Column)" Value="1" />
|
||||
<Setter Target="PeopleGrid.(Grid.ColumnSpan)" Value="2" />
|
||||
<Setter Target="PeopleGrid.(Grid.RowSpan)" Value="1" />
|
||||
<Setter Target="AttachmentsGrid.(Grid.Row)" Value="1" />
|
||||
<Setter Target="AttachmentsGrid.(Grid.Column)" Value="1" />
|
||||
<Setter Target="AttachmentsGrid.(Grid.ColumnSpan)" Value="2" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="NarrowState">
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger MinWindowWidth="0" />
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="DetailsGrid.(Grid.Row)" Value="0" />
|
||||
<Setter Target="DetailsGrid.(Grid.Column)" Value="0" />
|
||||
<Setter Target="DetailsGrid.(Grid.ColumnSpan)" Value="3" />
|
||||
<Setter Target="PeopleGrid.(Grid.Row)" Value="1" />
|
||||
<Setter Target="PeopleGrid.(Grid.Column)" Value="0" />
|
||||
<Setter Target="PeopleGrid.(Grid.ColumnSpan)" Value="3" />
|
||||
<Setter Target="AttachmentsGrid.(Grid.Row)" Value="2" />
|
||||
<Setter Target="AttachmentsGrid.(Grid.Column)" Value="0" />
|
||||
<Setter Target="AttachmentsGrid.(Grid.ColumnSpan)" Value="3" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</abstract:CalendarEventComposePageAbstract>
|
||||
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.WinUI.Controls;
|
||||
using EmailValidation;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Windows.Foundation;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
using Wino.Calendar.ViewModels.Data;
|
||||
using Wino.Mail.WinUI.Views.Abstract;
|
||||
|
||||
namespace Wino.Calendar.Views;
|
||||
|
||||
public sealed partial class CalendarEventComposePage : CalendarEventComposePageAbstract,
|
||||
IRecipient<ApplicationThemeChanged>
|
||||
{
|
||||
private readonly List<IDisposable> _disposables = [];
|
||||
|
||||
public CalendarEventComposePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override async void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
_disposables.Add(GetSuggestionBoxDisposable(AttendeeBox));
|
||||
_disposables.Add(NotesEditor);
|
||||
|
||||
ViewModel.GetHtmlNotesAsync = async () => await NotesEditor.GetHtmlBodyAsync() ?? string.Empty;
|
||||
await NotesEditor.RenderHtmlAsync(" ");
|
||||
}
|
||||
|
||||
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
|
||||
{
|
||||
base.OnNavigatingFrom(e);
|
||||
|
||||
foreach (var disposable in _disposables)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
|
||||
_disposables.Clear();
|
||||
}
|
||||
|
||||
private IDisposable GetSuggestionBoxDisposable(TokenizingTextBox box)
|
||||
{
|
||||
return Observable.FromEventPattern<TypedEventHandler<AutoSuggestBox, AutoSuggestBoxTextChangedEventArgs>, AutoSuggestBoxTextChangedEventArgs>(
|
||||
handler => box.TextChanged += handler,
|
||||
handler => box.TextChanged -= handler)
|
||||
.Throttle(TimeSpan.FromMilliseconds(120))
|
||||
.ObserveOn(SynchronizationContext.Current!)
|
||||
.Subscribe(async eventPattern =>
|
||||
{
|
||||
if (eventPattern.EventArgs.Reason != AutoSuggestionBoxTextChangeReason.UserInput)
|
||||
return;
|
||||
|
||||
if (eventPattern.Sender is not AutoSuggestBox senderBox || senderBox.Text.Length < 2)
|
||||
return;
|
||||
|
||||
var addresses = await ViewModel.SearchContactsAsync(senderBox.Text).ConfigureAwait(false);
|
||||
await ViewModel.ExecuteUIThread(() => senderBox.ItemsSource = addresses);
|
||||
});
|
||||
}
|
||||
|
||||
private async void TokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args)
|
||||
{
|
||||
if (!EmailValidator.Validate(args.TokenText))
|
||||
{
|
||||
args.Cancel = true;
|
||||
ViewModel.NotifyInvalidEmail(args.TokenText);
|
||||
return;
|
||||
}
|
||||
|
||||
var deferral = args.GetDeferral();
|
||||
|
||||
try
|
||||
{
|
||||
var attendee = await ViewModel.GetAttendeeAsync(args.TokenText);
|
||||
if (attendee == null)
|
||||
{
|
||||
args.Cancel = true;
|
||||
ViewModel.NotifyAddressExists();
|
||||
return;
|
||||
}
|
||||
|
||||
args.Item = attendee;
|
||||
}
|
||||
finally
|
||||
{
|
||||
deferral.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
private async void AddressBoxLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not TokenizingTextBox tokenizingTextBox)
|
||||
return;
|
||||
|
||||
if (tokenizingTextBox.Items.LastOrDefault() is not ITokenStringContainer info)
|
||||
return;
|
||||
|
||||
var currentText = info.Text;
|
||||
if (string.IsNullOrWhiteSpace(currentText) || !EmailValidator.Validate(currentText))
|
||||
return;
|
||||
|
||||
var attendee = await ViewModel.GetAttendeeAsync(currentText);
|
||||
if (attendee == null)
|
||||
{
|
||||
tokenizingTextBox.Text = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
ViewModel.AddAttendee(attendee);
|
||||
tokenizingTextBox.Text = string.Empty;
|
||||
}
|
||||
|
||||
private void RemoveAttendeeClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button { Tag: CalendarComposeAttendeeViewModel attendee })
|
||||
{
|
||||
ViewModel.RemoveAttendeeCommand.Execute(attendee);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveAttachmentClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button { Tag: CalendarComposeAttachmentViewModel attachment })
|
||||
{
|
||||
ViewModel.RemoveAttachmentCommand.Execute(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(ApplicationThemeChanged message)
|
||||
{
|
||||
ViewModel.IsDarkWebviewRenderer = message.IsUnderlyingThemeDark;
|
||||
NotesEditor.IsEditorDarkMode = message.IsUnderlyingThemeDark;
|
||||
}
|
||||
|
||||
protected override void RegisterRecipients()
|
||||
{
|
||||
base.RegisterRecipients();
|
||||
WeakReferenceMessenger.Default.Register<ApplicationThemeChanged>(this);
|
||||
}
|
||||
|
||||
protected override void UnregisterRecipients()
|
||||
{
|
||||
base.UnregisterRecipients();
|
||||
WeakReferenceMessenger.Default.Unregister<ApplicationThemeChanged>(this);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user