27
Wino.Core.UWP/Services/ApplicationResourceManager.cs
Normal file
27
Wino.Core.UWP/Services/ApplicationResourceManager.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Linq;
|
||||
using Windows.UI.Xaml;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.UWP;
|
||||
|
||||
namespace Wino.Services
|
||||
{
|
||||
public class ApplicationResourceManager : IApplicationResourceManager<ResourceDictionary>
|
||||
{
|
||||
public void AddResource(ResourceDictionary resource)
|
||||
=> WinoApplication.Current.Resources.MergedDictionaries.Add(resource);
|
||||
public void RemoveResource(ResourceDictionary resource)
|
||||
=> WinoApplication.Current.Resources.MergedDictionaries.Remove(resource);
|
||||
|
||||
public bool ContainsResourceKey(string resourceKey)
|
||||
=> WinoApplication.Current.Resources.ContainsKey(resourceKey);
|
||||
|
||||
public ResourceDictionary GetLastResource()
|
||||
=> WinoApplication.Current.Resources.MergedDictionaries.LastOrDefault();
|
||||
|
||||
public void ReplaceResource(string resourceKey, object resource)
|
||||
=> WinoApplication.Current.Resources[resourceKey] = resource;
|
||||
|
||||
public TReturnType GetResource<TReturnType>(string resourceKey)
|
||||
=> (TReturnType)WinoApplication.Current.Resources[resourceKey];
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,11 @@ namespace Wino.Core.UWP.Services
|
||||
return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(value);
|
||||
}
|
||||
|
||||
if (typeof(T) == typeof(TimeSpan))
|
||||
{
|
||||
return (T)(object)TimeSpan.Parse(value);
|
||||
}
|
||||
|
||||
return (T)Convert.ChangeType(value, typeof(T));
|
||||
}
|
||||
|
||||
|
||||
205
Wino.Core.UWP/Services/DialogServiceBase.cs
Normal file
205
Wino.Core.UWP/Services/DialogServiceBase.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Toolkit.Uwp.Helpers;
|
||||
using Serilog;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.UWP.Extensions;
|
||||
using Wino.Dialogs;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
|
||||
namespace Wino.Core.UWP.Services
|
||||
{
|
||||
public class DialogServiceBase : IDialogServiceBase
|
||||
{
|
||||
private SemaphoreSlim _presentationSemaphore = new SemaphoreSlim(1);
|
||||
|
||||
protected IThemeService ThemeService { get; }
|
||||
protected IConfigurationService ConfigurationService { get; }
|
||||
|
||||
protected IApplicationResourceManager<ResourceDictionary> ApplicationResourceManager { get; }
|
||||
|
||||
public DialogServiceBase(IThemeService themeService, IConfigurationService configurationService, IApplicationResourceManager<ResourceDictionary> applicationResourceManager)
|
||||
{
|
||||
ThemeService = themeService;
|
||||
ConfigurationService = configurationService;
|
||||
ApplicationResourceManager = applicationResourceManager;
|
||||
}
|
||||
|
||||
private async Task<StorageFile> PickFileAsync(params object[] typeFilters)
|
||||
{
|
||||
var picker = new FileOpenPicker
|
||||
{
|
||||
ViewMode = PickerViewMode.Thumbnail
|
||||
};
|
||||
|
||||
foreach (var filter in typeFilters)
|
||||
{
|
||||
picker.FileTypeFilter.Add(filter.ToString());
|
||||
}
|
||||
|
||||
var file = await picker.PickSingleFileAsync();
|
||||
|
||||
if (file == null) return null;
|
||||
|
||||
Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.AddOrReplace("FilePickerPath", file);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public async Task<byte[]> PickWindowsFileContentAsync(params object[] typeFilters)
|
||||
{
|
||||
var file = await PickFileAsync(typeFilters);
|
||||
|
||||
if (file == null) return [];
|
||||
|
||||
return await file.ReadBytesAsync();
|
||||
}
|
||||
|
||||
public Task ShowMessageAsync(string message, string title, WinoCustomMessageDialogIcon icon = WinoCustomMessageDialogIcon.Information)
|
||||
=> ShowWinoCustomMessageDialogAsync(title, message, Translator.Buttons_Close, icon);
|
||||
|
||||
public Task<bool> ShowConfirmationDialogAsync(string question, string title, string confirmationButtonTitle)
|
||||
=> ShowWinoCustomMessageDialogAsync(title, question, confirmationButtonTitle, WinoCustomMessageDialogIcon.Question, Translator.Buttons_Cancel, string.Empty);
|
||||
|
||||
public async Task<bool> ShowWinoCustomMessageDialogAsync(string title,
|
||||
string description,
|
||||
string approveButtonText,
|
||||
WinoCustomMessageDialogIcon? icon,
|
||||
string cancelButtonText = "",
|
||||
string dontAskAgainConfigurationKey = "")
|
||||
|
||||
{
|
||||
// This config key has been marked as don't ask again already.
|
||||
// Return immidiate result without presenting the dialog.
|
||||
|
||||
bool isDontAskEnabled = !string.IsNullOrEmpty(dontAskAgainConfigurationKey);
|
||||
|
||||
if (isDontAskEnabled && ConfigurationService.Get(dontAskAgainConfigurationKey, false)) return false;
|
||||
|
||||
var informationContainer = new CustomMessageDialogInformationContainer(title, description, icon.Value, isDontAskEnabled);
|
||||
|
||||
var dialog = new ContentDialog
|
||||
{
|
||||
Style = ApplicationResourceManager.GetResource<Style>("WinoDialogStyle"),
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme(),
|
||||
DefaultButton = ContentDialogButton.Primary,
|
||||
PrimaryButtonText = approveButtonText,
|
||||
ContentTemplate = ApplicationResourceManager.GetResource<DataTemplate>("CustomWinoContentDialogContentTemplate"),
|
||||
Content = informationContainer
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(cancelButtonText))
|
||||
{
|
||||
dialog.SecondaryButtonText = cancelButtonText;
|
||||
}
|
||||
|
||||
var dialogResult = await HandleDialogPresentationAsync(dialog);
|
||||
|
||||
// Mark this key to not ask again if user checked the checkbox.
|
||||
if (informationContainer.IsDontAskChecked)
|
||||
{
|
||||
ConfigurationService.Set(dontAskAgainConfigurationKey, true);
|
||||
}
|
||||
|
||||
return dialogResult == ContentDialogResult.Primary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for PopupRoot to be available before presenting the dialog and returns the result after presentation.
|
||||
/// </summary>
|
||||
/// <param name="dialog">Dialog to present and wait for closing.</param>
|
||||
/// <returns>Dialog result from WinRT.</returns>
|
||||
public async Task<ContentDialogResult> HandleDialogPresentationAsync(ContentDialog dialog)
|
||||
{
|
||||
await _presentationSemaphore.WaitAsync();
|
||||
|
||||
try
|
||||
{
|
||||
return await dialog.ShowAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, $"Handling dialog service failed. Dialog was {dialog.GetType().Name}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_presentationSemaphore.Release();
|
||||
}
|
||||
|
||||
return ContentDialogResult.None;
|
||||
}
|
||||
|
||||
|
||||
public void InfoBarMessage(string title, string message, InfoBarMessageType messageType)
|
||||
=> WeakReferenceMessenger.Default.Send(new InfoBarMessageRequested(messageType, title, message));
|
||||
|
||||
public void InfoBarMessage(string title, string message, InfoBarMessageType messageType, string actionButtonText, Action action)
|
||||
=> WeakReferenceMessenger.Default.Send(new InfoBarMessageRequested(messageType, title, message, actionButtonText, action));
|
||||
|
||||
public void ShowNotSupportedMessage()
|
||||
=> InfoBarMessage(Translator.Info_UnsupportedFunctionalityTitle,
|
||||
Translator.Info_UnsupportedFunctionalityDescription,
|
||||
InfoBarMessageType.Error);
|
||||
|
||||
public async Task<string> ShowTextInputDialogAsync(string currentInput, string dialogTitle, string dialogDescription, string primaryButtonText)
|
||||
{
|
||||
var inputDialog = new TextInputDialog()
|
||||
{
|
||||
CurrentInput = currentInput,
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme(),
|
||||
Title = dialogTitle
|
||||
};
|
||||
|
||||
inputDialog.SetDescription(dialogDescription);
|
||||
inputDialog.SetPrimaryButtonText(primaryButtonText);
|
||||
|
||||
await HandleDialogPresentationAsync(inputDialog);
|
||||
|
||||
if (inputDialog.HasInput.GetValueOrDefault() && !currentInput.Equals(inputDialog.CurrentInput))
|
||||
return inputDialog.CurrentInput;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public async Task<string> PickWindowsFolderAsync()
|
||||
{
|
||||
var picker = new FolderPicker
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
|
||||
};
|
||||
|
||||
picker.FileTypeFilter.Add("*");
|
||||
|
||||
var pickedFolder = await picker.PickSingleFolderAsync();
|
||||
|
||||
if (pickedFolder != null)
|
||||
{
|
||||
Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.AddOrReplace("FolderPickerToken", pickedFolder);
|
||||
|
||||
return pickedFolder.Path;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public async Task<bool> ShowCustomThemeBuilderDialogAsync()
|
||||
{
|
||||
var themeBuilderDialog = new CustomThemeBuilderDialog()
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
var dialogResult = await HandleDialogPresentationAsync(themeBuilderDialog);
|
||||
|
||||
return dialogResult == ContentDialogResult.Primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Wino.Core.UWP/Services/NavigationServiceBase.cs
Normal file
28
Wino.Core.UWP/Services/NavigationServiceBase.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
|
||||
namespace Wino.Core.UWP.Services
|
||||
{
|
||||
public class NavigationServiceBase
|
||||
{
|
||||
public NavigationTransitionInfo GetNavigationTransitionInfo(NavigationTransitionType transition)
|
||||
{
|
||||
return transition switch
|
||||
{
|
||||
NavigationTransitionType.DrillIn => new DrillInNavigationTransitionInfo(),
|
||||
NavigationTransitionType.Entrance => new EntranceNavigationTransitionInfo(),
|
||||
_ => new SuppressNavigationTransitionInfo(),
|
||||
};
|
||||
}
|
||||
|
||||
public Type GetCurrentFrameType(ref Frame _frame)
|
||||
{
|
||||
if (_frame != null && _frame.Content != null)
|
||||
return _frame.Content.GetType();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using Serilog;
|
||||
using Windows.Data.Xml.Dom;
|
||||
using Windows.UI.Notifications;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
using Wino.Core.Domain.Models.Reader;
|
||||
using Wino.Core.Domain.Translations;
|
||||
using Wino.Core.Services;
|
||||
|
||||
namespace Wino.Core.UWP.Services
|
||||
@@ -213,5 +217,77 @@ namespace Wino.Core.UWP.Services
|
||||
get => _configurationService.Get(nameof(ServerTerminationBehavior), ServerBackgroundMode.MinimizedTray);
|
||||
set => SaveProperty(propertyName: nameof(ServerTerminationBehavior), value);
|
||||
}
|
||||
|
||||
public DayOfWeek FirstDayOfWeek
|
||||
{
|
||||
get => _configurationService.Get(nameof(FirstDayOfWeek), DayOfWeek.Monday);
|
||||
set => SaveProperty(propertyName: nameof(FirstDayOfWeek), value);
|
||||
}
|
||||
|
||||
public double HourHeight
|
||||
{
|
||||
get => _configurationService.Get(nameof(HourHeight), 60.0);
|
||||
set => SaveProperty(propertyName: nameof(HourHeight), value);
|
||||
}
|
||||
|
||||
public TimeSpan WorkingHourStart
|
||||
{
|
||||
get => _configurationService.Get(nameof(WorkingHourStart), new TimeSpan(8, 0, 0));
|
||||
set => SaveProperty(propertyName: nameof(WorkingHourStart), value);
|
||||
}
|
||||
|
||||
public TimeSpan WorkingHourEnd
|
||||
{
|
||||
get => _configurationService.Get(nameof(WorkingHourEnd), new TimeSpan(17, 0, 0));
|
||||
set => SaveProperty(propertyName: nameof(WorkingHourEnd), value);
|
||||
}
|
||||
|
||||
public DayOfWeek WorkingDayStart
|
||||
{
|
||||
get => _configurationService.Get(nameof(WorkingDayStart), DayOfWeek.Monday);
|
||||
set => SaveProperty(propertyName: nameof(WorkingDayStart), value);
|
||||
}
|
||||
|
||||
public DayOfWeek WorkingDayEnd
|
||||
{
|
||||
get => _configurationService.Get(nameof(WorkingDayEnd), DayOfWeek.Friday);
|
||||
set => SaveProperty(propertyName: nameof(WorkingDayEnd), value);
|
||||
}
|
||||
|
||||
public CalendarSettings GetCurrentCalendarSettings()
|
||||
{
|
||||
var workingDays = GetDaysBetween(WorkingDayStart, WorkingDayEnd);
|
||||
|
||||
return new CalendarSettings(FirstDayOfWeek,
|
||||
workingDays,
|
||||
WorkingHourStart,
|
||||
WorkingHourEnd,
|
||||
HourHeight,
|
||||
Prefer24HourTimeFormat ? DayHeaderDisplayType.TwentyFourHour : DayHeaderDisplayType.TwelveHour,
|
||||
new CultureInfo(WinoTranslationDictionary.GetLanguageFileNameRelativePath(CurrentLanguage)));
|
||||
}
|
||||
|
||||
private List<DayOfWeek> GetDaysBetween(DayOfWeek startDay, DayOfWeek endDay)
|
||||
{
|
||||
var daysOfWeek = new List<DayOfWeek>();
|
||||
|
||||
int currentDay = (int)startDay;
|
||||
int endDayInt = (int)endDay;
|
||||
|
||||
// If endDay is before startDay in the week, wrap around
|
||||
if (endDayInt < currentDay)
|
||||
{
|
||||
endDayInt += 7;
|
||||
}
|
||||
|
||||
// Collect days from startDay to endDay
|
||||
while (currentDay <= endDayInt)
|
||||
{
|
||||
daysOfWeek.Add((DayOfWeek)(currentDay % 7));
|
||||
currentDay++;
|
||||
}
|
||||
|
||||
return daysOfWeek;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
|
||||
namespace Wino.Services
|
||||
{
|
||||
@@ -20,8 +19,10 @@ namespace Wino.Services
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
|
||||
openPaneLength = _configurationService.Get(OpenPaneLengthKey, 320d);
|
||||
_openPaneLength = _configurationService.Get(OpenPaneLengthKey, 320d);
|
||||
_mailListPaneLength = _configurationService.Get(MailListPaneLengthKey, 420d);
|
||||
_calendarDisplayType = _configurationService.Get(nameof(CalendarDisplayType), CalendarDisplayType.Week);
|
||||
_dayDisplayCount = _configurationService.Get(nameof(DayDisplayCount), 1);
|
||||
|
||||
PropertyChanged += ServicePropertyChanged;
|
||||
}
|
||||
@@ -80,15 +81,13 @@ namespace Wino.Services
|
||||
}
|
||||
}
|
||||
|
||||
#region Settings
|
||||
|
||||
private double openPaneLength;
|
||||
private double _openPaneLength;
|
||||
public double OpenPaneLength
|
||||
{
|
||||
get => openPaneLength;
|
||||
get => _openPaneLength;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref openPaneLength, value))
|
||||
if (SetProperty(ref _openPaneLength, value))
|
||||
{
|
||||
_configurationService.Set(OpenPaneLengthKey, value);
|
||||
}
|
||||
@@ -106,10 +105,33 @@ namespace Wino.Services
|
||||
_configurationService.Set(MailListPaneLengthKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
private CalendarDisplayType _calendarDisplayType;
|
||||
public CalendarDisplayType CalendarDisplayType
|
||||
{
|
||||
get => _calendarDisplayType;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _calendarDisplayType, value))
|
||||
{
|
||||
_configurationService.Set(nameof(CalendarDisplayType), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int _dayDisplayCount;
|
||||
public int DayDisplayCount
|
||||
{
|
||||
get => _dayDisplayCount;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _dayDisplayCount, value))
|
||||
{
|
||||
_configurationService.Set(nameof(DayDisplayCount), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAppCoreWindowTitle()
|
||||
{
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace Wino.Core.UWP.Services
|
||||
private const string LatestAskedKey = nameof(LatestAskedKey);
|
||||
|
||||
private readonly IConfigurationService _configurationService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IMailDialogService _dialogService;
|
||||
|
||||
public StoreRatingService(IConfigurationService configurationService, IDialogService dialogService)
|
||||
public StoreRatingService(IConfigurationService configurationService, IMailDialogService dialogService)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
_dialogService = dialogService;
|
||||
|
||||
Reference in New Issue
Block a user