Calendar account management page basics.

This commit is contained in:
Burak Kaan Köse
2024-11-11 01:09:05 +01:00
parent 5b0fcd77e5
commit 418eeb7317
34 changed files with 515 additions and 184 deletions

View File

@@ -1,13 +1,22 @@
using System.Threading.Tasks; using System;
using System.Threading;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Input;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Navigation; using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Domain.Models.Store;
using Wino.Core.ViewModels; using Wino.Core.ViewModels;
using Wino.Messaging.Server;
namespace Wino.Calendar.ViewModels namespace Wino.Calendar.ViewModels
{ {
public partial class AccountManagementViewModel : AccountManagementPageViewModelBase public partial class AccountManagementViewModel : AccountManagementPageViewModelBase
{ {
private readonly IProviderService _providerService;
public AccountManagementViewModel(ICalendarDialogService dialogService, public AccountManagementViewModel(ICalendarDialogService dialogService,
IWinoServerConnectionManager winoServerConnectionManager, IWinoServerConnectionManager winoServerConnectionManager,
INavigationService navigationService, INavigationService navigationService,
@@ -18,20 +27,116 @@ namespace Wino.Calendar.ViewModels
IPreferencesService preferencesService) : base(dialogService, winoServerConnectionManager, navigationService, accountService, providerService, storeManagementService, authenticationProvider, preferencesService) IPreferencesService preferencesService) : base(dialogService, winoServerConnectionManager, navigationService, accountService, providerService, storeManagementService, authenticationProvider, preferencesService)
{ {
CalendarDialogService = dialogService; CalendarDialogService = dialogService;
_providerService = providerService;
} }
public ICalendarDialogService CalendarDialogService { get; } public ICalendarDialogService CalendarDialogService { get; }
public override Task InitializeAccountsAsync() public override async Task InitializeAccountsAsync()
{ {
return Task.CompletedTask; Accounts.Clear();
var accounts = await AccountService.GetAccountsAsync().ConfigureAwait(false);
await ExecuteUIThread(() =>
{
foreach (var account in accounts)
{
var accountDetails = GetAccountProviderDetails(account);
Accounts.Add(accountDetails);
}
});
await ManageStorePurchasesAsync().ConfigureAwait(false);
} }
public override async void OnNavigatedTo(NavigationMode mode, object parameters) [RelayCommand]
private async Task AddNewAccountAsync()
{ {
base.OnNavigatedTo(mode, parameters); if (IsAccountCreationBlocked)
{
var isPurchaseClicked = await DialogService.ShowConfirmationDialogAsync(Translator.DialogMessage_AccountLimitMessage, Translator.DialogMessage_AccountLimitTitle, Translator.Buttons_Purchase);
var t = await StoreManagementService.HasProductAsync(StoreProductType.UnlimitedAccounts); if (!isPurchaseClicked) return;
await PurchaseUnlimitedAccountAsync();
return;
}
var availableProviders = _providerService.GetAvailableProviders();
var accountCreationDialogResult = await DialogService.ShowAccountProviderSelectionDialogAsync(availableProviders);
if (accountCreationDialogResult == null) return;
var accountCreationCancellationTokenSource = new CancellationTokenSource();
var accountCreationDialog = CalendarDialogService.GetAccountCreationDialog(accountCreationDialogResult.ProviderType);
accountCreationDialog.ShowDialog(accountCreationCancellationTokenSource);
accountCreationDialog.State = AccountCreationDialogState.SigningIn;
// For OAuth authentications, we just generate token and assign it to the MailAccount.
var createdAccount = new MailAccount()
{
ProviderType = accountCreationDialogResult.ProviderType,
Name = accountCreationDialogResult.AccountName,
AccountColorHex = accountCreationDialogResult.AccountColorHex,
Id = Guid.NewGuid()
};
var tokenInformationResponse = await WinoServerConnectionManager
.GetResponseAsync<TokenInformation, AuthorizationRequested>(new AuthorizationRequested(accountCreationDialogResult.ProviderType,
createdAccount,
createdAccount.ProviderType == MailProviderType.Gmail), accountCreationCancellationTokenSource.Token);
if (accountCreationDialog.State == AccountCreationDialogState.Canceled)
throw new AccountSetupCanceledException();
tokenInformationResponse.ThrowIfFailed();
var tokenInformation = tokenInformationResponse.Data;
createdAccount.Address = tokenInformation.Address;
tokenInformation.AccountId = createdAccount.Id;
await AccountService.CreateAccountAsync(createdAccount, tokenInformation, null);
// Sync profile information if supported.
if (createdAccount.IsProfileInfoSyncSupported)
{
// Start profile information synchronization.
// It's only available for Outlook and Gmail synchronizers.
var profileSyncOptions = new SynchronizationOptions()
{
AccountId = createdAccount.Id,
Type = SynchronizationType.UpdateProfile
};
var profileSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync<SynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(profileSyncOptions, SynchronizationSource.Client));
var profileSynchronizationResult = profileSynchronizationResponse.Data;
if (profileSynchronizationResult.CompletedState != SynchronizationCompletedState.Success)
throw new Exception(Translator.Exception_FailedToSynchronizeProfileInformation);
createdAccount.SenderName = profileSynchronizationResult.ProfileInformation.SenderName;
createdAccount.Base64ProfilePictureData = profileSynchronizationResult.ProfileInformation.Base64ProfilePictureData;
await AccountService.UpdateProfileInformationAsync(createdAccount.Id, profileSynchronizationResult.ProfileInformation);
}
accountCreationDialog.State = AccountCreationDialogState.FetchingEvents;
// Start synchronizing events.
var eventsSyncOptions = new SynchronizationOptions()
{
AccountId = createdAccount.Id,
Type = SynchronizationType.Events
};
} }
} }
} }

View File

@@ -51,6 +51,7 @@ namespace Wino.Calendar
services.AddSingleton<INavigationService, NavigationService>(); services.AddSingleton<INavigationService, NavigationService>();
services.AddSingleton<ICalendarDialogService, DialogService>(); services.AddSingleton<ICalendarDialogService, DialogService>();
services.AddTransient<ISettingsBuilderService, SettingsBuilderService>(); services.AddTransient<ISettingsBuilderService, SettingsBuilderService>();
services.AddTransient<IProviderService, ProviderService>();
} }
private void RegisterViewModels(IServiceCollection services) private void RegisterViewModels(IServiceCollection services)

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Wino.Calendar.Services
{
internal class ApplicationResourceManager
{
}
}

View File

@@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Linq;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
namespace Wino.Calendar.Services
{
public class ProviderService : IProviderService
{
public IProviderDetail GetProviderDetail(MailProviderType type)
{
var details = GetAvailableProviders();
return details.FirstOrDefault(a => a.Type == type);
}
public List<IProviderDetail> GetAvailableProviders()
{
var providerList = new List<IProviderDetail>();
var providers = new MailProviderType[]
{
MailProviderType.Outlook,
MailProviderType.Gmail
};
foreach (var type in providers)
{
providerList.Add(new ProviderDetail(type));
}
return providerList;
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -152,9 +152,9 @@
</Compile> </Compile>
<Compile Include="Models\CalendarItemMeasurement.cs" /> <Compile Include="Models\CalendarItemMeasurement.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\ApplicationResourceManager.cs" />
<Compile Include="Services\DialogService.cs" /> <Compile Include="Services\DialogService.cs" />
<Compile Include="Services\NavigationService.cs" /> <Compile Include="Services\NavigationService.cs" />
<Compile Include="Services\ProviderService.cs" />
<Compile Include="Services\SettingsBuilderService.cs" /> <Compile Include="Services\SettingsBuilderService.cs" />
<Compile Include="Styles\CalendarItemControlResources.xaml.cs" /> <Compile Include="Styles\CalendarItemControlResources.xaml.cs" />
<Compile Include="Styles\WinoCalendarResources.xaml.cs" /> <Compile Include="Styles\WinoCalendarResources.xaml.cs" />

View File

@@ -11,6 +11,7 @@
AutoDiscoverySetup, AutoDiscoverySetup,
AutoDiscoveryInProgress, AutoDiscoveryInProgress,
FetchingProfileInformation, FetchingProfileInformation,
Canceled Canceled,
FetchingEvents
} }
} }

View File

@@ -2,12 +2,16 @@
{ {
public enum SynchronizationType public enum SynchronizationType
{ {
FoldersOnly, // Only synchronize folder metadata. // Shared
ExecuteRequests, // Run the queued requests, and then synchronize if needed.
Inbox, // Only Inbox, Sent and Draft folders.
Custom, // Only sync folders that are specified in the options.
Full, // Synchronize all folders. This won't update profile or alias information.
UpdateProfile, // Only update profile information UpdateProfile, // Only update profile information
ExecuteRequests, // Run the queued requests, and then synchronize if needed.
// Wino Mail
FoldersOnly, // Only synchronize folder metadata.
InboxOnly, // Only Inbox, Sent and Draft folders.
CustomFolders, // Only sync folders that are specified in the options.
FullFolders, // Synchronize all folders. This won't update profile or alias information.
Alias, // Only update alias information Alias, // Only update alias information
// Calendar
Events
} }
} }

View File

@@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Accounts;
namespace Wino.Core.Domain.Interfaces namespace Wino.Core.Domain.Interfaces
{ {
@@ -21,5 +23,7 @@ namespace Wino.Core.Domain.Interfaces
string cancelButtonText = "", string cancelButtonText = "",
string dontAskAgainConfigurationKey = ""); string dontAskAgainConfigurationKey = "");
Task<bool> ShowCustomThemeBuilderDialogAsync(); Task<bool> ShowCustomThemeBuilderDialogAsync();
Task<AccountCreationDialogResult> ShowAccountProviderSelectionDialogAsync(List<IProviderDetail> availableProviders);
IAccountCreationDialog GetAccountCreationDialog(MailProviderType type);
} }
} }

View File

@@ -5,7 +5,6 @@ using System.Threading.Tasks;
using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.Folders; using Wino.Core.Domain.Models.Folders;
namespace Wino.Core.Domain.Interfaces namespace Wino.Core.Domain.Interfaces
@@ -17,9 +16,6 @@ namespace Wino.Core.Domain.Interfaces
// Custom dialogs // Custom dialogs
Task<IMailItemFolder> ShowMoveMailFolderDialogAsync(List<IMailItemFolder> availableFolders); Task<IMailItemFolder> ShowMoveMailFolderDialogAsync(List<IMailItemFolder> availableFolders);
Task<AccountCreationDialogResult> ShowNewAccountMailProviderDialogAsync(List<IProviderDetail> availableProviders);
IAccountCreationDialog GetAccountCreationDialog(MailProviderType type);
Task<MailAccount> ShowEditAccountDialogAsync(MailAccount account); Task<MailAccount> ShowEditAccountDialogAsync(MailAccount account);
Task<MailAccount> ShowAccountPickerDialogAsync(List<MailAccount> availableAccounts); Task<MailAccount> ShowAccountPickerDialogAsync(List<MailAccount> availableAccounts);

View File

@@ -5,7 +5,7 @@ namespace Wino.Core.Domain.Interfaces
{ {
public interface IProviderService public interface IProviderService
{ {
List<IProviderDetail> GetProviderDetails(); List<IProviderDetail> GetAvailableProviders();
IProviderDetail GetProviderDetail(MailProviderType type); IProviderDetail GetProviderDetail(MailProviderType type);
} }
} }

View File

@@ -4,6 +4,7 @@
"AccountCreationDialog_PreparingFolders": "We are getting folder information at the moment.", "AccountCreationDialog_PreparingFolders": "We are getting folder information at the moment.",
"AccountCreationDialog_SigninIn": "Account information is being saved.", "AccountCreationDialog_SigninIn": "Account information is being saved.",
"AccountCreationDialog_FetchingProfileInformation": "Fetching profile details.", "AccountCreationDialog_FetchingProfileInformation": "Fetching profile details.",
"AccountCreationDialog_FetchingEvents": "Fetching calendar events.",
"AccountCreationDialog_GoogleAuthHelpClipboardText_Row0": "If your browser did not launch automatically to complete authentication:", "AccountCreationDialog_GoogleAuthHelpClipboardText_Row0": "If your browser did not launch automatically to complete authentication:",
"AccountCreationDialog_GoogleAuthHelpClipboardText_Row1": "1) Click the button below to copy the authentication address", "AccountCreationDialog_GoogleAuthHelpClipboardText_Row1": "1) Click the button below to copy the authentication address",
"AccountCreationDialog_GoogleAuthHelpClipboardText_Row2": "2) Launch your web browser (Edge, Chrome, Firefox etc...)", "AccountCreationDialog_GoogleAuthHelpClipboardText_Row2": "2) Launch your web browser (Edge, Chrome, Firefox etc...)",

View File

@@ -14,6 +14,7 @@
<ResourceDictionary Source="Styles/Converters.xaml" /> <ResourceDictionary Source="Styles/Converters.xaml" />
<ResourceDictionary Source="Styles/FontIcons.xaml" /> <ResourceDictionary Source="Styles/FontIcons.xaml" />
<ResourceDictionary Source="Styles/WinoInfoBar.xaml" /> <ResourceDictionary Source="Styles/WinoInfoBar.xaml" />
<ResourceDictionary Source="Styles/SharedStyles.xaml" />
<styles:CustomMessageDialogStyles /> <styles:CustomMessageDialogStyles />
<styles:DataTemplates /> <styles:DataTemplates />

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
<ContentDialog <ContentDialog
x:Class="Wino.Dialogs.NewAccountDialog" x:Class="Wino.Core.UWP.Dialogs.NewAccountDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:accounts="using:Wino.Core.Domain.Models.Accounts" xmlns:accounts="using:Wino.Core.Domain.Models.Accounts"

View File

@@ -4,7 +4,7 @@ using Windows.UI.Xaml.Controls;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts; using Wino.Core.Domain.Models.Accounts;
namespace Wino.Dialogs namespace Wino.Core.UWP.Dialogs
{ {
public sealed partial class NewAccountDialog : ContentDialog public sealed partial class NewAccountDialog : ContentDialog
{ {

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
@@ -11,6 +12,8 @@ using Windows.UI.Xaml.Controls;
using Wino.Core.Domain; using Wino.Core.Domain;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.UWP.Dialogs;
using Wino.Core.UWP.Extensions; using Wino.Core.UWP.Extensions;
using Wino.Dialogs; using Wino.Dialogs;
using Wino.Messaging.Client.Shell; using Wino.Messaging.Client.Shell;
@@ -54,6 +57,14 @@ namespace Wino.Core.UWP.Services
return file; return file;
} }
public virtual IAccountCreationDialog GetAccountCreationDialog(MailProviderType type)
{
return new AccountCreationDialog
{
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
};
}
public async Task<byte[]> PickWindowsFileContentAsync(params object[] typeFilters) public async Task<byte[]> PickWindowsFileContentAsync(params object[] typeFilters)
{ {
var file = await PickFileAsync(typeFilters); var file = await PickFileAsync(typeFilters);
@@ -201,5 +212,18 @@ namespace Wino.Core.UWP.Services
return dialogResult == ContentDialogResult.Primary; return dialogResult == ContentDialogResult.Primary;
} }
public async Task<AccountCreationDialogResult> ShowAccountProviderSelectionDialogAsync(List<IProviderDetail> availableProviders)
{
var dialog = new NewAccountDialog
{
Providers = availableProviders,
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
};
await HandleDialogPresentationAsync(dialog);
return dialog.Result;
}
} }
} }

View File

@@ -288,6 +288,8 @@ namespace Wino.Core.UWP.Services
if (Status != WinoServerConnectionStatus.Connected) if (Status != WinoServerConnectionStatus.Connected)
await ConnectAsync(); await ConnectAsync();
if (Connection == null) return WinoServerResponse<TResponse>.CreateErrorResponse("Server connection is not established.");
string serializedMessage = string.Empty; string serializedMessage = string.Empty;
try try

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Wino.Core.UWP.Styles">
<!-- Horizontally Stretched List View Item Container Style -->
<Style x:Key="StretchedItemContainerStyle" TargetType="ListViewItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="Background" Value="{ThemeResource ListViewItemBackground}" />
<Setter Property="Foreground" Value="{ThemeResource ListViewItemForeground}" />
<Setter Property="TabNavigation" Value="Local" />
<Setter Property="IsHoldingEnabled" Value="True" />
<Setter Property="Padding" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}" />
<Setter Property="AllowDrop" Value="False" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter
x:Name="Root"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
CheckBoxBrush="{ThemeResource ListViewItemCheckBoxBrush}"
CheckBrush="{ThemeResource ListViewItemCheckBrush}"
CheckMode="{ThemeResource ListViewItemCheckMode}"
ContentMargin="{TemplateBinding Padding}"
ContentTransitions="{TemplateBinding ContentTransitions}"
Control.IsTemplateFocusTarget="True"
DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
DragBackground="{ThemeResource ListViewItemDragBackground}"
DragForeground="{ThemeResource ListViewItemDragForeground}"
DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
FocusBorderBrush="{ThemeResource ListViewItemFocusBorderBrush}"
FocusSecondaryBorderBrush="{ThemeResource ListViewItemFocusSecondaryBorderBrush}"
FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackground}"
PointerOverBackground="{ThemeResource ListViewItemBackgroundPointerOver}"
PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}"
PressedBackground="{ThemeResource ListViewItemBackgroundPressed}"
ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
RevealBackground="{ThemeResource ListViewItemRevealBackground}"
RevealBorderBrush="{ThemeResource ListViewItemRevealBorderBrush}"
RevealBorderThickness="{ThemeResource ListViewItemRevealBorderThemeThickness}"
SelectedBackground="{ThemeResource ListViewItemBackgroundSelected}"
SelectedForeground="{ThemeResource ListViewItemForegroundSelected}"
SelectedPointerOverBackground="{ThemeResource ListViewItemBackgroundSelectedPointerOver}"
SelectedPressedBackground="{ThemeResource ListViewItemBackgroundSelectedPressed}"
SelectionCheckMarkVisualEnabled="{ThemeResource ListViewItemSelectionCheckMarkVisualEnabled}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected" />
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="PointerOver" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPointerOver}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOverSelected">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="PointerOver" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPointerOver}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOverPressed">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="Pressed" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPressed}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="Pressed" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPressed}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PressedSelected">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="Pressed" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPressed}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DisabledStates">
<VisualState x:Name="Enabled" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="Root.RevealBorderThickness" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ListViewItemPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -96,6 +96,9 @@
<Compile Include="Converters\ReverseBooleanConverter.cs" /> <Compile Include="Converters\ReverseBooleanConverter.cs" />
<Compile Include="Converters\ReverseBooleanToVisibilityConverter.cs" /> <Compile Include="Converters\ReverseBooleanToVisibilityConverter.cs" />
<Compile Include="CoreUWPContainerSetup.cs" /> <Compile Include="CoreUWPContainerSetup.cs" />
<Compile Include="Dialogs\NewAccountDialog.xaml.cs">
<DependentUpon>NewAccountDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Selectors\NavigationMenuTemplateSelector.cs" /> <Compile Include="Selectors\NavigationMenuTemplateSelector.cs" />
<Compile Include="Services\ApplicationResourceManager.cs" /> <Compile Include="Services\ApplicationResourceManager.cs" />
<Compile Include="Services\DialogServiceBase.cs" /> <Compile Include="Services\DialogServiceBase.cs" />
@@ -194,7 +197,6 @@
<PackageReference Include="CommunityToolkit.Uwp.Controls.SettingsControls"> <PackageReference Include="CommunityToolkit.Uwp.Controls.SettingsControls">
<Version>8.1.240916</Version> <Version>8.1.240916</Version>
</PackageReference> </PackageReference>
<PackageReference Include="CommunityToolkit.Uwp.Controls.Sizers"> <PackageReference Include="CommunityToolkit.Uwp.Controls.Sizers">
<Version>8.1.240916</Version> <Version>8.1.240916</Version>
</PackageReference> </PackageReference>
@@ -338,6 +340,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Dialogs\NewAccountDialog.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Dialogs\TextInputDialog.xaml"> <Page Include="Dialogs\TextInputDialog.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
@@ -374,6 +380,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Styles\SharedStyles.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Styles\WinoInfoBar.xaml"> <Page Include="Styles\WinoInfoBar.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>

View File

@@ -29,7 +29,6 @@ namespace Wino.Core
services.AddTransient<IOutlookChangeProcessor, OutlookChangeProcessor>(); services.AddTransient<IOutlookChangeProcessor, OutlookChangeProcessor>();
services.AddTransient<ITokenService, TokenService>(); services.AddTransient<ITokenService, TokenService>();
services.AddTransient<IProviderService, ProviderService>();
services.AddTransient<IFolderService, FolderService>(); services.AddTransient<IFolderService, FolderService>();
services.AddTransient<IMailService, MailService>(); services.AddTransient<IMailService, MailService>();
services.AddTransient<IAccountService, AccountService>(); services.AddTransient<IAccountService, AccountService>();

View File

@@ -550,7 +550,7 @@ namespace Wino.Core.Services
{ {
var folders = new List<MailItemFolder>(); var folders = new List<MailItemFolder>();
if (options.Type == SynchronizationType.Full) if (options.Type == SynchronizationType.FullFolders)
{ {
// Only get sync enabled folders. // Only get sync enabled folders.
@@ -568,11 +568,11 @@ namespace Wino.Core.Services
var mustHaveFolders = await GetInboxSynchronizationFoldersAsync(options.AccountId); var mustHaveFolders = await GetInboxSynchronizationFoldersAsync(options.AccountId);
if (options.Type == SynchronizationType.Inbox) if (options.Type == SynchronizationType.InboxOnly)
{ {
return mustHaveFolders; return mustHaveFolders;
} }
else if (options.Type == SynchronizationType.Custom) else if (options.Type == SynchronizationType.CustomFolders)
{ {
// Only get the specified and enabled folders. // Only get the specified and enabled folders.

View File

@@ -397,13 +397,13 @@ namespace Wino.Core.Synchronizers
{ {
// Gather FolderIds to synchronize. // Gather FolderIds to synchronize.
options.Type = SynchronizationType.Custom; options.Type = SynchronizationType.CustomFolders;
options.SynchronizationFolderIds = synchronizationFolderIds; options.SynchronizationFolderIds = synchronizationFolderIds;
} }
else else
{ {
// At this point it's a mix of everything. Do full sync. // At this point it's a mix of everything. Do full sync.
options.Type = SynchronizationType.Full; options.Type = SynchronizationType.FullFolders;
} }
return options; return options;

View File

@@ -956,7 +956,7 @@ namespace Wino.Core.Synchronizers.Mail
var options = new SynchronizationOptions() var options = new SynchronizationOptions()
{ {
AccountId = Account.Id, AccountId = Account.Id,
Type = SynchronizationType.Full Type = SynchronizationType.FullFolders
}; };
await SynchronizeInternalAsync(options, cancellationToken); await SynchronizeInternalAsync(options, cancellationToken);

View File

@@ -437,7 +437,7 @@ namespace Wino.Core.Synchronizers.Mail
PublishSynchronizationProgress(1); PublishSynchronizationProgress(1);
bool shouldDoFolderSync = options.Type == SynchronizationType.Full || options.Type == SynchronizationType.FoldersOnly; bool shouldDoFolderSync = options.Type == SynchronizationType.FullFolders || options.Type == SynchronizationType.FoldersOnly;
if (shouldDoFolderSync) if (shouldDoFolderSync)
{ {

View File

@@ -83,10 +83,10 @@ namespace Wino.Mail.ViewModels
try try
{ {
var providers = ProviderService.GetProviderDetails(); var providers = ProviderService.GetAvailableProviders();
// Select provider. // Select provider.
var accountCreationDialogResult = await MailDialogService.ShowNewAccountMailProviderDialogAsync(providers); var accountCreationDialogResult = await MailDialogService.ShowAccountProviderSelectionDialogAsync(providers);
var accountCreationCancellationTokenSource = new CancellationTokenSource(); var accountCreationCancellationTokenSource = new CancellationTokenSource();

View File

@@ -316,7 +316,7 @@ namespace Wino.Mail.ViewModels
var options = new SynchronizationOptions() var options = new SynchronizationOptions()
{ {
AccountId = account.Id, AccountId = account.Id,
Type = SynchronizationType.Full Type = SynchronizationType.FullFolders
}; };
Messenger.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client)); Messenger.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));
@@ -889,7 +889,7 @@ namespace Wino.Mail.ViewModels
var options = new SynchronizationOptions() var options = new SynchronizationOptions()
{ {
AccountId = createdAccount.Id, AccountId = createdAccount.Id,
Type = SynchronizationType.Full, Type = SynchronizationType.FullFolders,
}; };
Messenger.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client)); Messenger.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));

View File

@@ -470,7 +470,7 @@ namespace Wino.Mail.ViewModels
var options = new SynchronizationOptions() var options = new SynchronizationOptions()
{ {
AccountId = folder.MailAccountId, AccountId = folder.MailAccountId,
Type = SynchronizationType.Custom, Type = SynchronizationType.CustomFolders,
SynchronizationFolderIds = [folder.Id], SynchronizationFolderIds = [folder.Id],
GroupedSynchronizationTrackingId = trackingSynchronizationId GroupedSynchronizationTrackingId = trackingSynchronizationId
}; };

View File

@@ -21,6 +21,7 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization; using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.UWP; using Wino.Core.UWP;
using Wino.Mail.Services;
using Wino.Mail.ViewModels; using Wino.Mail.ViewModels;
using Wino.Messaging.Client.Connection; using Wino.Messaging.Client.Connection;
using Wino.Messaging.Client.Navigation; using Wino.Messaging.Client.Navigation;
@@ -94,6 +95,8 @@ namespace Wino
services.AddSingleton<INavigationService, NavigationService>(); services.AddSingleton<INavigationService, NavigationService>();
services.AddSingleton<IMailDialogService, DialogService>(); services.AddSingleton<IMailDialogService, DialogService>();
services.AddTransient<ISettingsBuilderService, SettingsBuilderService>(); services.AddTransient<ISettingsBuilderService, SettingsBuilderService>();
services.AddTransient<IProviderService, ProviderService>();
} }
private void RegisterViewModels(IServiceCollection services) private void RegisterViewModels(IServiceCollection services)

View File

@@ -10,7 +10,6 @@ using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.Folders; using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.Synchronization; using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.UWP.Extensions; using Wino.Core.UWP.Extensions;
@@ -27,41 +26,22 @@ namespace Wino.Services
IConfigurationService configurationService, IConfigurationService configurationService,
IApplicationResourceManager<ResourceDictionary> applicationResourceManager) : base(themeService, configurationService, applicationResourceManager) IApplicationResourceManager<ResourceDictionary> applicationResourceManager) : base(themeService, configurationService, applicationResourceManager)
{ {
} }
public async Task<AccountCreationDialogResult> ShowNewAccountMailProviderDialogAsync(List<IProviderDetail> availableProviders) public override IAccountCreationDialog GetAccountCreationDialog(MailProviderType type)
{ {
var dialog = new NewAccountDialog
{
Providers = availableProviders,
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
};
await HandleDialogPresentationAsync(dialog);
return dialog.Result;
}
public IAccountCreationDialog GetAccountCreationDialog(MailProviderType type)
{
IAccountCreationDialog dialog = null;
if (type == MailProviderType.IMAP4) if (type == MailProviderType.IMAP4)
{ {
dialog = new NewImapSetupDialog return new NewImapSetupDialog
{ {
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme() RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
}; };
} }
else else
{ {
dialog = new AccountCreationDialog return base.GetAccountCreationDialog(type);
{
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
};
} }
return dialog;
} }
public async Task<MailAccount> ShowEditAccountDialogAsync(MailAccount account) public async Task<MailAccount> ShowEditAccountDialogAsync(MailAccount account)
@@ -114,7 +94,7 @@ namespace Wino.Services
var options = new SynchronizationOptions() var options = new SynchronizationOptions()
{ {
AccountId = accountId, AccountId = accountId,
Type = SynchronizationType.Full, Type = SynchronizationType.FullFolders,
}; };
WeakReferenceMessenger.Default.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client)); WeakReferenceMessenger.Default.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));

View File

@@ -4,7 +4,7 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts; using Wino.Core.Domain.Models.Accounts;
namespace Wino.Core.Services namespace Wino.Mail.Services
{ {
/// <summary> /// <summary>
/// Service that is returning available provider details. /// Service that is returning available provider details.
@@ -13,12 +13,12 @@ namespace Wino.Core.Services
{ {
public IProviderDetail GetProviderDetail(MailProviderType type) public IProviderDetail GetProviderDetail(MailProviderType type)
{ {
var details = GetProviderDetails(); var details = GetAvailableProviders();
return details.FirstOrDefault(a => a.Type == type); return details.FirstOrDefault(a => a.Type == type);
} }
public List<IProviderDetail> GetProviderDetails() public List<IProviderDetail> GetAvailableProviders()
{ {
var providerList = new List<IProviderDetail>(); var providerList = new List<IProviderDetail>();

View File

@@ -5,104 +5,6 @@
xmlns:primitives="using:Microsoft.UI.Xaml.Controls.Primitives" xmlns:primitives="using:Microsoft.UI.Xaml.Controls.Primitives"
xmlns:winoControls="using:Wino.Controls"> xmlns:winoControls="using:Wino.Controls">
<!-- Horizontally Stretched List View Item Container Style -->
<Style x:Key="StretchedItemContainerStyle" TargetType="ListViewItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="Background" Value="{ThemeResource ListViewItemBackground}" />
<Setter Property="Foreground" Value="{ThemeResource ListViewItemForeground}" />
<Setter Property="TabNavigation" Value="Local" />
<Setter Property="IsHoldingEnabled" Value="True" />
<Setter Property="Padding" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}" />
<Setter Property="AllowDrop" Value="False" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter
x:Name="Root"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
CheckBoxBrush="{ThemeResource ListViewItemCheckBoxBrush}"
CheckBrush="{ThemeResource ListViewItemCheckBrush}"
CheckMode="{ThemeResource ListViewItemCheckMode}"
ContentMargin="{TemplateBinding Padding}"
ContentTransitions="{TemplateBinding ContentTransitions}"
Control.IsTemplateFocusTarget="True"
DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}"
DragBackground="{ThemeResource ListViewItemDragBackground}"
DragForeground="{ThemeResource ListViewItemDragForeground}"
DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}"
FocusBorderBrush="{ThemeResource ListViewItemFocusBorderBrush}"
FocusSecondaryBorderBrush="{ThemeResource ListViewItemFocusSecondaryBorderBrush}"
FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackground}"
PointerOverBackground="{ThemeResource ListViewItemBackgroundPointerOver}"
PointerOverForeground="{ThemeResource ListViewItemForegroundPointerOver}"
PressedBackground="{ThemeResource ListViewItemBackgroundPressed}"
ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}"
RevealBackground="{ThemeResource ListViewItemRevealBackground}"
RevealBorderBrush="{ThemeResource ListViewItemRevealBorderBrush}"
RevealBorderThickness="{ThemeResource ListViewItemRevealBorderThemeThickness}"
SelectedBackground="{ThemeResource ListViewItemBackgroundSelected}"
SelectedForeground="{ThemeResource ListViewItemForegroundSelected}"
SelectedPointerOverBackground="{ThemeResource ListViewItemBackgroundSelectedPointerOver}"
SelectedPressedBackground="{ThemeResource ListViewItemBackgroundSelectedPressed}"
SelectionCheckMarkVisualEnabled="{ThemeResource ListViewItemSelectionCheckMarkVisualEnabled}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected" />
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="PointerOver" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPointerOver}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOverSelected">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="PointerOver" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPointerOver}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PointerOverPressed">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="Pressed" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPressed}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="Pressed" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPressed}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="PressedSelected">
<VisualState.Setters>
<Setter Target="Root.(RevealBrush.State)" Value="Pressed" />
<Setter Target="Root.RevealBorderBrush" Value="{ThemeResource ListViewItemRevealBorderBrushPressed}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DisabledStates">
<VisualState x:Name="Enabled" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="Root.RevealBorderThickness" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ListViewItemPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Mail List Header Item Style --> <!-- Mail List Header Item Style -->
<Style x:Key="MailListHeaderStyle" TargetType="ListViewHeaderItem"> <Style x:Key="MailListHeaderStyle" TargetType="ListViewHeaderItem">

View File

@@ -253,9 +253,6 @@
<DependentUpon>MailItemDisplayInformationControl.xaml</DependentUpon> <DependentUpon>MailItemDisplayInformationControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="MenuFlyouts\MoveButtonFlyout.cs" /> <Compile Include="MenuFlyouts\MoveButtonFlyout.cs" />
<Compile Include="Dialogs\NewAccountDialog.xaml.cs">
<DependentUpon>NewAccountDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Selectors\AccountProviderViewModelTemplateSelector.cs" /> <Compile Include="Selectors\AccountProviderViewModelTemplateSelector.cs" />
<Compile Include="Selectors\AccountReorderTemplateSelector.cs" /> <Compile Include="Selectors\AccountReorderTemplateSelector.cs" />
<Compile Include="Selectors\MailItemContainerStyleSelector.cs" /> <Compile Include="Selectors\MailItemContainerStyleSelector.cs" />
@@ -263,6 +260,7 @@
<Compile Include="Selectors\MailItemDisplaySelector.cs" /> <Compile Include="Selectors\MailItemDisplaySelector.cs" />
<Compile Include="Services\DialogService.cs" /> <Compile Include="Services\DialogService.cs" />
<Compile Include="Services\NavigationService.cs" /> <Compile Include="Services\NavigationService.cs" />
<Compile Include="Services\ProviderService.cs" />
<Compile Include="Services\SettingsBuilderService.cs" /> <Compile Include="Services\SettingsBuilderService.cs" />
<Compile Include="Styles\WinoExpanderStyle.xaml.cs"> <Compile Include="Styles\WinoExpanderStyle.xaml.cs">
<DependentUpon>WinoExpanderStyle.xaml</DependentUpon> <DependentUpon>WinoExpanderStyle.xaml</DependentUpon>
@@ -390,10 +388,6 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Dialogs\NewAccountDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Styles\ImagePreviewControl.xaml"> <Page Include="Styles\ImagePreviewControl.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>

View File

@@ -93,7 +93,7 @@ namespace Wino.Server
var options = new SynchronizationOptions var options = new SynchronizationOptions
{ {
AccountId = account.Id, AccountId = account.Id,
Type = SynchronizationType.Inbox, Type = SynchronizationType.InboxOnly,
}; };
var request = new NewSynchronizationRequested(options, SynchronizationSource.Server); var request = new NewSynchronizationRequested(options, SynchronizationSource.Server);