Calendar improvements.

This commit is contained in:
Burak Kaan Köse
2026-03-08 01:33:47 +01:00
parent 1da34080d1
commit a8f9b2d126
10 changed files with 162 additions and 20 deletions
+2 -1
View File
@@ -56,6 +56,7 @@
<PackageVersion Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" /> <PackageVersion Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
<PackageVersion Include="Google.Apis.Auth" Version="1.73.0" /> <PackageVersion Include="Google.Apis.Auth" Version="1.73.0" />
<PackageVersion Include="Google.Apis.Calendar.v3" Version="1.73.0.4063" /> <PackageVersion Include="Google.Apis.Calendar.v3" Version="1.73.0.4063" />
<PackageVersion Include="Google.Apis.Drive.v3" Version="1.73.0.4068" />
<PackageVersion Include="Google.Apis.Gmail.v1" Version="1.73.0.4029" /> <PackageVersion Include="Google.Apis.Gmail.v1" Version="1.73.0.4029" />
<PackageVersion Include="Google.Apis.PeopleService.v1" Version="1.72.0.3973" /> <PackageVersion Include="Google.Apis.PeopleService.v1" Version="1.72.0.3973" />
<PackageVersion Include="HtmlKit" Version="1.2.0" /> <PackageVersion Include="HtmlKit" Version="1.2.0" />
@@ -74,4 +75,4 @@
<PackageVersion Include="FluentAssertions" Version="8.8.0" /> <PackageVersion Include="FluentAssertions" Version="8.8.0" />
<PackageVersion Include="Moq" Version="4.20.72" /> <PackageVersion Include="Moq" Version="4.20.72" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -119,9 +119,13 @@ public partial class CalendarAppShellViewModel : CalendarBaseViewModel,
{ {
base.OnNavigatedTo(mode, parameters); base.OnNavigatedTo(mode, parameters);
// Account list may have changed while this shell was inactive. // Preserve the existing calendar shell frame state when the user switches
if (mode == NavigationMode.Back) // between Mail and Calendar modes. Back/forward restoration should not
// force a new CalendarPage navigation, otherwise pages like
// CalendarEventComposePage get dropped from the inner frame stack.
if (mode != NavigationMode.New)
{ {
UpdateDateNavigationHeaderItems();
await InitializeAccountCalendarsAsync(); await InitializeAccountCalendarsAsync();
ValidateConfiguredNewEventCalendar(); ValidateConfiguredNewEventCalendar();
return; return;
@@ -102,8 +102,15 @@ public partial class CalendarEventComposePageViewModel : CalendarBaseViewModel
public CalendarSettings CurrentSettings { get; } public CalendarSettings CurrentSettings { get; }
public string TimePickerClockIdentifier => CurrentSettings.DayHeaderDisplayType == DayHeaderDisplayType.TwentyFourHour ? "24HourClock" : "12HourClock"; public string TimePickerClockIdentifier => CurrentSettings.DayHeaderDisplayType == DayHeaderDisplayType.TwentyFourHour ? "24HourClock" : "12HourClock";
public bool HasAttachments => Attachments.Count > 0; public bool HasAttachments => Attachments.Count > 0;
public bool IsSelectedCalendarCalDav => SelectedCalendar?.Account?.ProviderType == MailProviderType.IMAP4 &&
SelectedCalendar.Account.ServerInformation?.CalendarSupportMode == ImapCalendarSupportMode.CalDav;
public bool CanAddAttachments => !IsSelectedCalendarCalDav;
public string AttachmentsDisabledTooltipText => IsSelectedCalendarCalDav
? Translator.CalendarEventCompose_AttachmentsNotSupportedForCalDav
: string.Empty;
public string SelectedCalendarDisplayText => SelectedCalendar?.Name ?? Translator.CalendarEventCompose_SelectCalendar; public string SelectedCalendarDisplayText => SelectedCalendar?.Name ?? Translator.CalendarEventCompose_SelectCalendar;
public string SelectedCalendarAccountText => SelectedCalendar?.Account?.Address ?? string.Empty; public string SelectedCalendarAccountText => SelectedCalendar?.Account?.Address ?? string.Empty;
public bool IsDailyRecurrenceSelected => SelectedRecurrenceFrequencyOption?.Frequency == CalendarItemRecurrenceFrequency.Daily;
public CalendarEventComposePageViewModel(IAccountService accountService, public CalendarEventComposePageViewModel(IAccountService accountService,
ICalendarService calendarService, ICalendarService calendarService,
@@ -183,6 +190,15 @@ public partial class CalendarEventComposePageViewModel : CalendarBaseViewModel
SelectedShowAsOption = ShowAsOptions.FirstOrDefault(option => option.ShowAs == value.DefaultShowAs) SelectedShowAsOption = ShowAsOptions.FirstOrDefault(option => option.ShowAs == value.DefaultShowAs)
?? ShowAsOptions.FirstOrDefault(); ?? ShowAsOptions.FirstOrDefault();
if (IsSelectedCalendarCalDav && Attachments.Count > 0)
{
Attachments.Clear();
}
OnPropertyChanged(nameof(IsSelectedCalendarCalDav));
OnPropertyChanged(nameof(CanAddAttachments));
OnPropertyChanged(nameof(AttachmentsDisabledTooltipText));
OnPropertyChanged(nameof(SelectedCalendarDisplayText)); OnPropertyChanged(nameof(SelectedCalendarDisplayText));
OnPropertyChanged(nameof(SelectedCalendarAccountText)); OnPropertyChanged(nameof(SelectedCalendarAccountText));
} }
@@ -228,12 +244,19 @@ public partial class CalendarEventComposePageViewModel : CalendarBaseViewModel
UpdateRecurrenceSummary(); UpdateRecurrenceSummary();
} }
partial void OnSelectedRecurrenceIntervalChanged(int value) => UpdateRecurrenceSummary(); partial void OnSelectedRecurrenceIntervalChanged(int value) => UpdateRecurrenceSummary();
partial void OnSelectedRecurrenceFrequencyOptionChanged(CalendarComposeFrequencyOption value) => UpdateRecurrenceSummary(); partial void OnSelectedRecurrenceFrequencyOptionChanged(CalendarComposeFrequencyOption value)
{
OnPropertyChanged(nameof(IsDailyRecurrenceSelected));
UpdateRecurrenceSummary();
}
partial void OnRecurrenceEndDateChanged(DateTimeOffset? value) => UpdateRecurrenceSummary(); partial void OnRecurrenceEndDateChanged(DateTimeOffset? value) => UpdateRecurrenceSummary();
[RelayCommand] [RelayCommand]
private async Task AddAttachmentsAsync() private async Task AddAttachmentsAsync()
{ {
if (!CanAddAttachments)
return;
var pickedFiles = await _dialogService.PickFilesMetadataAsync("*"); var pickedFiles = await _dialogService.PickFilesMetadataAsync("*");
if (pickedFiles.Count == 0) if (pickedFiles.Count == 0)
return; return;
@@ -471,7 +494,9 @@ public partial class CalendarEventComposePageViewModel : CalendarBaseViewModel
ShowAs = SelectedShowAsOption?.ShowAs ?? SelectedCalendar?.DefaultShowAs ?? CalendarItemShowAs.Busy, ShowAs = SelectedShowAsOption?.ShowAs ?? SelectedCalendar?.DefaultShowAs ?? CalendarItemShowAs.Busy,
SelectedReminders = BuildSelectedReminders(), SelectedReminders = BuildSelectedReminders(),
Attendees = BuildAttendees(uniqueAttendees), Attendees = BuildAttendees(uniqueAttendees),
Attachments = Attachments.Select(attachment => attachment.ToDraftModel()).ToList(), Attachments = CanAddAttachments
? Attachments.Select(attachment => attachment.ToDraftModel()).ToList()
: [],
Recurrence = BuildRecurrenceRule(), Recurrence = BuildRecurrenceRule(),
RecurrenceSummary = RecurrenceSummary RecurrenceSummary = RecurrenceSummary
}; };
@@ -527,10 +552,12 @@ public partial class CalendarEventComposePageViewModel : CalendarBaseViewModel
var effectiveStart = GetEffectiveStartDateTime(); var effectiveStart = GetEffectiveStartDateTime();
var effectiveEnd = GetEffectiveEndDateTime(); var effectiveEnd = GetEffectiveEndDateTime();
var selectedDays = WeekdayOptions var selectedDays = IsDailyRecurrenceSelected
.Where(option => option.IsSelected) ? WeekdayOptions
.Select(option => option.DayOfWeek) .Where(option => option.IsSelected)
.ToList(); .Select(option => option.DayOfWeek)
.ToList()
: [];
RecurrenceSummary = CalendarRecurrenceSummaryFormatter.BuildSummary( RecurrenceSummary = CalendarRecurrenceSummaryFormatter.BuildSummary(
IsRecurring, IsRecurring,
@@ -565,10 +592,12 @@ public partial class CalendarEventComposePageViewModel : CalendarBaseViewModel
$"INTERVAL={SelectedRecurrenceInterval}" $"INTERVAL={SelectedRecurrenceInterval}"
}; };
var selectedDays = WeekdayOptions var selectedDays = IsDailyRecurrenceSelected
.Where(option => option.IsSelected) ? WeekdayOptions
.Select(option => option.RuleValue) .Where(option => option.IsSelected)
.ToList(); .Select(option => option.RuleValue)
.ToList()
: [];
if (selectedDays.Count > 0) if (selectedDays.Count > 0)
{ {
@@ -649,7 +678,8 @@ public partial class CalendarEventComposePageViewModel : CalendarBaseViewModel
private bool TryAddAttachment(string fileName, string filePath, string fileExtension, long size) private bool TryAddAttachment(string fileName, string filePath, string fileExtension, long size)
{ {
if (string.IsNullOrWhiteSpace(filePath) || if (!CanAddAttachments ||
string.IsNullOrWhiteSpace(filePath) ||
Attachments.Any(existing => existing.FilePath.Equals(filePath, StringComparison.OrdinalIgnoreCase))) Attachments.Any(existing => existing.FilePath.Equals(filePath, StringComparison.OrdinalIgnoreCase)))
{ {
return false; return false;
@@ -126,6 +126,7 @@
"CalendarAttendeeStatus_Tentative": "Tentative", "CalendarAttendeeStatus_Tentative": "Tentative",
"CalendarEventDetails_Attachments": "Attachments", "CalendarEventDetails_Attachments": "Attachments",
"CalendarEventCompose_AddAttachment": "Add attachment", "CalendarEventCompose_AddAttachment": "Add attachment",
"CalendarEventCompose_AttachmentsNotSupportedForCalDav": "Attachments are not supported for CalDAV calendars.",
"CalendarEventCompose_AllDay": "All Day", "CalendarEventCompose_AllDay": "All Day",
"CalendarEventCompose_EndDate": "End date", "CalendarEventCompose_EndDate": "End date",
"CalendarEventCompose_EndTime": "End time", "CalendarEventCompose_EndTime": "End time",
+93 -1
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@@ -9,12 +10,14 @@ using System.Web;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Google; using Google;
using Google.Apis.Calendar.v3.Data; using Google.Apis.Calendar.v3.Data;
using Google.Apis.Drive.v3;
using Google.Apis.Gmail.v1; using Google.Apis.Gmail.v1;
using Google.Apis.Gmail.v1.Data; using Google.Apis.Gmail.v1.Data;
using Google.Apis.Http; using Google.Apis.Http;
using Google.Apis.PeopleService.v1; using Google.Apis.PeopleService.v1;
using Google.Apis.Requests; using Google.Apis.Requests;
using Google.Apis.Services; using Google.Apis.Services;
using Google.Apis.Upload;
using MailKit; using MailKit;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using MimeKit; using MimeKit;
@@ -42,12 +45,15 @@ using Wino.Core.Requests.Mail;
using Wino.Messaging.UI; using Wino.Messaging.UI;
using Wino.Services; using Wino.Services;
using CalendarService = Google.Apis.Calendar.v3.CalendarService; using CalendarService = Google.Apis.Calendar.v3.CalendarService;
using DriveFile = Google.Apis.Drive.v3.Data.File;
using DriveService = Google.Apis.Drive.v3.DriveService;
namespace Wino.Core.Synchronizers.Mail; namespace Wino.Core.Synchronizers.Mail;
[JsonSerializable(typeof(Message))] [JsonSerializable(typeof(Message))]
[JsonSerializable(typeof(Label))] [JsonSerializable(typeof(Label))]
[JsonSerializable(typeof(Draft))] [JsonSerializable(typeof(Draft))]
[JsonSerializable(typeof(Event))]
public partial class GmailSynchronizerJsonContext : JsonSerializerContext; public partial class GmailSynchronizerJsonContext : JsonSerializerContext;
/// <summary> /// <summary>
@@ -88,6 +94,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
private readonly ConfigurableHttpClient _googleHttpClient; private readonly ConfigurableHttpClient _googleHttpClient;
private readonly GmailService _gmailService; private readonly GmailService _gmailService;
private readonly CalendarService _calendarService; private readonly CalendarService _calendarService;
private readonly DriveService _driveService;
private readonly PeopleServiceService _peopleService; private readonly PeopleServiceService _peopleService;
private readonly IGmailChangeProcessor _gmailChangeProcessor; private readonly IGmailChangeProcessor _gmailChangeProcessor;
@@ -114,6 +121,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
_gmailService = new GmailService(initializer); _gmailService = new GmailService(initializer);
_peopleService = new PeopleServiceService(initializer); _peopleService = new PeopleServiceService(initializer);
_calendarService = new CalendarService(initializer); _calendarService = new CalendarService(initializer);
_driveService = new DriveService(initializer);
_gmailChangeProcessor = gmailChangeProcessor; _gmailChangeProcessor = gmailChangeProcessor;
_gmailSynchronizerErrorHandlerFactory = gmailSynchronizerErrorHandlerFactory; _gmailSynchronizerErrorHandlerFactory = gmailSynchronizerErrorHandlerFactory;
@@ -1689,6 +1697,15 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
{ {
// TODO: Handle new Gmail Label added or updated. // TODO: Handle new Gmail Label added or updated.
} }
else if (bundle is HttpRequestBundle<IClientServiceRequest, Event> eventBundle && eventBundle.Request is CreateCalendarEventRequest createCalendarEventRequest)
{
var createdEvent = await eventBundle.DeserializeBundleAsync(httpResponseMessage, GmailSynchronizerJsonContext.Default.Event, cancellationToken).ConfigureAwait(false);
if (createdEvent == null || string.IsNullOrWhiteSpace(createdEvent.Id))
return;
await UploadCalendarEventAttachmentsAsync(createCalendarEventRequest, createdEvent, cancellationToken).ConfigureAwait(false);
}
else if (bundle is HttpRequestBundle<IClientServiceRequest, Draft> draftBundle && draftBundle.Request is CreateDraftRequest createDraftRequest) else if (bundle is HttpRequestBundle<IClientServiceRequest, Draft> draftBundle && draftBundle.Request is CreateDraftRequest createDraftRequest)
{ {
// New draft mail is created. // New draft mail is created.
@@ -2355,7 +2372,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
? Google.Apis.Calendar.v3.EventsResource.InsertRequest.SendUpdatesEnum.All ? Google.Apis.Calendar.v3.EventsResource.InsertRequest.SendUpdatesEnum.All
: Google.Apis.Calendar.v3.EventsResource.InsertRequest.SendUpdatesEnum.None; : Google.Apis.Calendar.v3.EventsResource.InsertRequest.SendUpdatesEnum.None;
return [new HttpRequestBundle<IClientServiceRequest>(insertRequest, request)]; return [new HttpRequestBundle<IClientServiceRequest, Event>(insertRequest, request)];
} }
public override List<IRequestBundle<IClientServiceRequest>> AcceptEvent(AcceptEventRequest request) public override List<IRequestBundle<IClientServiceRequest>> AcceptEvent(AcceptEventRequest request)
@@ -2596,9 +2613,84 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
_gmailService.Dispose(); _gmailService.Dispose();
_peopleService.Dispose(); _peopleService.Dispose();
_calendarService.Dispose(); _calendarService.Dispose();
_driveService.Dispose();
_googleHttpClient.Dispose(); _googleHttpClient.Dispose();
} }
private async Task UploadCalendarEventAttachmentsAsync(CreateCalendarEventRequest request, Event createdEvent, CancellationToken cancellationToken)
{
var composeAttachments = request.ComposeResult.Attachments ?? [];
if (composeAttachments.Count == 0)
return;
if (composeAttachments.Count > 25)
throw new InvalidOperationException("Google Calendar supports at most 25 attachments per event.");
var eventAttachments = createdEvent.Attachments?
.Where(attachment => attachment != null && !string.IsNullOrWhiteSpace(attachment.FileUrl))
.ToList() ?? [];
foreach (var attachment in composeAttachments.Where(a => !string.IsNullOrWhiteSpace(a.FilePath) && File.Exists(a.FilePath)))
{
cancellationToken.ThrowIfCancellationRequested();
eventAttachments.Add(await UploadAttachmentToDriveAsync(attachment, cancellationToken).ConfigureAwait(false));
}
if (eventAttachments.Count == 0)
return;
var patchRequest = _calendarService.Events.Patch(new Event
{
Attachments = eventAttachments
}, request.AssignedCalendar.RemoteCalendarId, createdEvent.Id);
patchRequest.SupportsAttachments = true;
patchRequest.SendUpdates = Google.Apis.Calendar.v3.EventsResource.PatchRequest.SendUpdatesEnum.None;
await patchRequest.ExecuteAsync(cancellationToken).ConfigureAwait(false);
}
private async Task<EventAttachment> UploadAttachmentToDriveAsync(
Wino.Core.Domain.Models.Calendar.CalendarEventComposeAttachmentDraft attachment,
CancellationToken cancellationToken)
{
var fileName = string.IsNullOrWhiteSpace(attachment.FileName)
? Path.GetFileName(attachment.FilePath)
: attachment.FileName;
var contentType = MimeTypes.GetMimeType(fileName);
await using var fileStream = File.OpenRead(attachment.FilePath);
var uploadRequest = _driveService.Files.Create(new DriveFile
{
Name = fileName,
MimeType = contentType
}, fileStream, contentType);
uploadRequest.Fields = "id,name,mimeType,webViewLink";
var uploadProgress = await uploadRequest.UploadAsync(cancellationToken).ConfigureAwait(false);
if (uploadProgress.Status != UploadStatus.Completed)
{
throw new InvalidOperationException(
$"Failed to upload '{fileName}' to Google Drive. Upload status: {uploadProgress.Status}.");
}
var uploadedFile = uploadRequest.ResponseBody;
if (uploadedFile == null || string.IsNullOrWhiteSpace(uploadedFile.Id) || string.IsNullOrWhiteSpace(uploadedFile.WebViewLink))
{
throw new InvalidOperationException($"Google Drive did not return a valid attachment link for '{fileName}'.");
}
return new EventAttachment
{
FileId = uploadedFile.Id,
FileUrl = uploadedFile.WebViewLink,
MimeType = uploadedFile.MimeType ?? contentType,
Title = uploadedFile.Name ?? fileName
};
}
private static TimeSpan ResolveOffset(DateTime dateTime, string timeZoneId) private static TimeSpan ResolveOffset(DateTime dateTime, string timeZoneId)
{ {
if (string.IsNullOrWhiteSpace(timeZoneId)) if (string.IsNullOrWhiteSpace(timeZoneId))
+2 -1
View File
@@ -15,6 +15,7 @@
<PackageReference Include="CommunityToolkit.Diagnostics" /> <PackageReference Include="CommunityToolkit.Diagnostics" />
<PackageReference Include="CommunityToolkit.Mvvm" /> <PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="Google.Apis.Calendar.v3" /> <PackageReference Include="Google.Apis.Calendar.v3" />
<PackageReference Include="Google.Apis.Drive.v3" />
<PackageReference Include="Google.Apis.Gmail.v1" /> <PackageReference Include="Google.Apis.Gmail.v1" />
<PackageReference Include="Google.Apis.PeopleService.v1" /> <PackageReference Include="Google.Apis.PeopleService.v1" />
<PackageReference Include="HtmlAgilityPack" /> <PackageReference Include="HtmlAgilityPack" />
@@ -43,4 +44,4 @@
<ItemGroup> <ItemGroup>
<Folder Include="Domain\Models\Errors\" /> <Folder Include="Domain\Models\Errors\" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -327,8 +327,13 @@
<TextBlock <TextBlock
Grid.Column="4" Grid.Column="4"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{x:Bind domain:Translator.CalendarEventCompose_ForWeekdays}" /> Text="{x:Bind domain:Translator.CalendarEventCompose_ForWeekdays}"
<ItemsControl Grid.Column="5" ItemsSource="{x:Bind ViewModel.WeekdayOptions}"> Visibility="{x:Bind ViewModel.IsDailyRecurrenceSelected, Mode=OneWay}" />
<ItemsControl
Grid.Column="5"
IsEnabled="{x:Bind ViewModel.IsDailyRecurrenceSelected, Mode=OneWay}"
ItemsSource="{x:Bind ViewModel.WeekdayOptions}"
Visibility="{x:Bind ViewModel.IsDailyRecurrenceSelected, Mode=OneWay}">
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" /> <StackPanel Orientation="Horizontal" Spacing="4" />
@@ -472,11 +477,13 @@
DragLeave="AttachmentsPane_DragLeave" DragLeave="AttachmentsPane_DragLeave"
DragOver="AttachmentsPane_DragOver" DragOver="AttachmentsPane_DragOver"
Drop="AttachmentsPane_Drop" Drop="AttachmentsPane_Drop"
ToolTipService.ToolTip="{x:Bind ViewModel.AttachmentsDisabledTooltipText, Mode=OneWay}"
Visibility="{x:Bind AttachmentsToggle.IsChecked, Mode=OneWay}"> Visibility="{x:Bind AttachmentsToggle.IsChecked, Mode=OneWay}">
<StackPanel Spacing="8"> <StackPanel Spacing="8">
<Button <Button
HorizontalAlignment="Left" HorizontalAlignment="Left"
Command="{x:Bind ViewModel.AddAttachmentsCommand}" Command="{x:Bind ViewModel.AddAttachmentsCommand}"
IsEnabled="{x:Bind ViewModel.CanAddAttachments, Mode=OneWay}"
Style="{StaticResource TransparentActionButtonStyle}"> Style="{StaticResource TransparentActionButtonStyle}">
<StackPanel Orientation="Horizontal" Spacing="8"> <StackPanel Orientation="Horizontal" Spacing="8">
<coreControls:WinoFontIcon FontSize="14" Icon="AttachmentNew" /> <coreControls:WinoFontIcon FontSize="14" Icon="AttachmentNew" />
@@ -150,6 +150,12 @@ public sealed partial class CalendarEventComposePage : CalendarEventComposePageA
private void AttachmentsPane_DragOver(object sender, DragEventArgs e) private void AttachmentsPane_DragOver(object sender, DragEventArgs e)
{ {
if (!ViewModel.CanAddAttachments)
{
e.AcceptedOperation = DataPackageOperation.None;
return;
}
e.AcceptedOperation = e.DataView.Contains(StandardDataFormats.StorageItems) e.AcceptedOperation = e.DataView.Contains(StandardDataFormats.StorageItems)
? DataPackageOperation.Copy ? DataPackageOperation.Copy
: DataPackageOperation.None; : DataPackageOperation.None;
@@ -169,7 +175,7 @@ public sealed partial class CalendarEventComposePage : CalendarEventComposePageA
private async void AttachmentsPane_Drop(object sender, DragEventArgs e) private async void AttachmentsPane_Drop(object sender, DragEventArgs e)
{ {
if (!e.DataView.Contains(StandardDataFormats.StorageItems)) if (!ViewModel.CanAddAttachments || !e.DataView.Contains(StandardDataFormats.StorageItems))
{ {
return; return;
} }
@@ -148,7 +148,6 @@
<AppBarToggleButton <AppBarToggleButton
x:Name="EditorThemeToggleButton" x:Name="EditorThemeToggleButton"
IsChecked="{x:Bind WebViewEditor.IsEditorDarkMode, Mode=TwoWay}" IsChecked="{x:Bind WebViewEditor.IsEditorDarkMode, Mode=TwoWay}"
Label=""
ToolTipService.ToolTip="Toggle editor dark mode"> ToolTipService.ToolTip="Toggle editor dark mode">
<AppBarToggleButton.Icon> <AppBarToggleButton.Icon>
<coreControls:WinoFontIcon Icon="DarkEditor" /> <coreControls:WinoFontIcon Icon="DarkEditor" />
+1
View File
@@ -33,6 +33,7 @@
<ItemGroup> <ItemGroup>
<TrimmerRootAssembly Include="Google.Apis.Auth" /> <TrimmerRootAssembly Include="Google.Apis.Auth" />
<TrimmerRootAssembly Include="Google.Apis.Drive.v3" />
<TrimmerRootAssembly Include="Google.Apis.Gmail.v1" /> <TrimmerRootAssembly Include="Google.Apis.Gmail.v1" />
</ItemGroup> </ItemGroup>