Settings refactoring.

This commit is contained in:
Burak Kaan Köse
2026-03-24 01:18:06 +01:00
parent 5c7f6aa734
commit ff84d62196
35 changed files with 990 additions and 999 deletions
@@ -402,7 +402,7 @@ public partial class CalendarAppShellViewModel : CalendarBaseViewModel,
var pickingResult = await _dialogService.ShowSingleCalendarPickerDialogAsync(availableGroups);
if (pickingResult.ShouldNavigateToCalendarSettings)
{
NavigationService.Navigate(WinoPage.CalendarSettingsPage);
NavigationService.Navigate(WinoPage.CalendarPreferenceSettingsPage);
return;
}
@@ -0,0 +1,44 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain.Interfaces;
namespace Wino.Calendar.ViewModels;
public partial class CalendarNotificationSettingsPageViewModel : CalendarSettingsSectionViewModelBase
{
[ObservableProperty]
public partial int SelectedDefaultReminderIndex { get; set; }
[ObservableProperty]
public partial int SelectedDefaultSnoozeIndex { get; set; }
public CalendarNotificationSettingsPageViewModel(
IPreferencesService preferencesService,
ICalendarService calendarService,
IAccountService accountService)
: base(preferencesService, calendarService, accountService)
{
LoadReminderOptions();
LoadSnoozeOptions();
SelectedDefaultReminderIndex = GetSelectedReminderIndex();
SelectedDefaultSnoozeIndex = GetSelectedSnoozeIndex();
IsLoaded = true;
}
partial void OnSelectedDefaultReminderIndexChanged(int value)
{
if (!IsLoaded)
return;
SaveReminderIndex(value);
}
partial void OnSelectedDefaultSnoozeIndexChanged(int value)
{
if (!IsLoaded)
return;
SaveSnoozeIndex(value);
}
}
@@ -0,0 +1,62 @@
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Calendar.ViewModels.Data;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
namespace Wino.Calendar.ViewModels;
public partial class CalendarPreferenceSettingsPageViewModel : CalendarSettingsSectionViewModelBase
{
[ObservableProperty]
public partial CalendarNewEventBehaviorOption SelectedNewEventBehaviorOption { get; set; }
[ObservableProperty]
public partial AccountCalendarViewModel SelectedNewEventCalendar { get; set; }
public bool ShouldShowSpecificNewEventCalendar
=> SelectedNewEventBehaviorOption?.Behavior == NewEventButtonBehavior.AlwaysUseSpecificCalendar;
public CalendarPreferenceSettingsPageViewModel(
IPreferencesService preferencesService,
ICalendarService calendarService,
IAccountService accountService)
: base(preferencesService, calendarService, accountService)
{
LoadNewEventBehaviorOptions();
SelectedNewEventBehaviorOption = GetSelectedNewEventBehaviorOption();
IsLoaded = true;
LoadCalendarsAsync(ApplyStoredNewEventCalendarPreference);
}
partial void OnSelectedNewEventBehaviorOptionChanged(CalendarNewEventBehaviorOption value)
{
if (!IsLoaded)
return;
OnPropertyChanged(nameof(ShouldShowSpecificNewEventCalendar));
SaveNewEventBehavior(SelectedNewEventBehaviorOption, SelectedNewEventCalendar);
}
partial void OnSelectedNewEventCalendarChanged(AccountCalendarViewModel value)
{
if (!IsLoaded)
return;
SaveNewEventBehavior(SelectedNewEventBehaviorOption, value);
}
private void ApplyStoredNewEventCalendarPreference()
{
var configuredCalendar = ResolveSelectedNewEventCalendar();
if (PreferencesService.NewEventButtonBehavior == NewEventButtonBehavior.AlwaysUseSpecificCalendar && configuredCalendar == null)
{
SelectedNewEventBehaviorOption = NewEventBehaviorOptions.First(option => option.Behavior == NewEventButtonBehavior.AskEachTime);
SelectedNewEventCalendar = null;
return;
}
SelectedNewEventCalendar = configuredCalendar ?? ResolveFallbackNewEventCalendar();
}
}
@@ -0,0 +1,191 @@
using System;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain.Interfaces;
namespace Wino.Calendar.ViewModels;
public partial class CalendarRenderingSettingsPageViewModel : CalendarSettingsSectionViewModelBase
{
[ObservableProperty]
public partial double CellHourHeight { get; set; }
[ObservableProperty]
public partial int SelectedFirstDayOfWeekIndex { get; set; }
[ObservableProperty]
public partial bool Is24HourHeaders { get; set; }
[ObservableProperty]
public partial bool IsWorkingHoursEnabled { get; set; }
[ObservableProperty]
public partial TimeSpan WorkingHourStart { get; set; }
[ObservableProperty]
public partial TimeSpan WorkingHourEnd { get; set; }
[ObservableProperty]
public partial int WorkingDayStartIndex { get; set; }
[ObservableProperty]
public partial int WorkingDayEndIndex { get; set; }
[ObservableProperty]
public partial string TimedDayHeaderDateFormat { get; set; } = "ddd dd";
[ObservableProperty]
public partial int SelectedTimedDayHeaderFormatPresetIndex { get; set; } = -1;
public CalendarRenderingSettingsPageViewModel(
IPreferencesService preferencesService,
ICalendarService calendarService,
IAccountService accountService)
: base(preferencesService, calendarService, accountService)
{
SelectedFirstDayOfWeekIndex = DayNames.IndexOf(CalendarCulture.DateTimeFormat.GetDayName(preferencesService.FirstDayOfWeek));
Is24HourHeaders = preferencesService.Prefer24HourTimeFormat;
IsWorkingHoursEnabled = preferencesService.IsWorkingHoursEnabled;
WorkingHourStart = preferencesService.WorkingHourStart;
WorkingHourEnd = preferencesService.WorkingHourEnd;
CellHourHeight = preferencesService.HourHeight;
WorkingDayStartIndex = DayNames.IndexOf(CalendarCulture.DateTimeFormat.GetDayName(preferencesService.WorkingDayStart));
WorkingDayEndIndex = DayNames.IndexOf(CalendarCulture.DateTimeFormat.GetDayName(preferencesService.WorkingDayEnd));
TimedDayHeaderDateFormat = preferencesService.CalendarTimedDayHeaderDateFormat;
SelectedTimedDayHeaderFormatPresetIndex = TimedDayHeaderFormatPresets.IndexOf(TimedDayHeaderDateFormat);
IsLoaded = true;
}
partial void OnCellHourHeightChanged(double oldValue, double newValue) => SaveSettings();
partial void OnIs24HourHeadersChanged(bool value)
{
OnPropertyChanged(nameof(TimedHourLabelPreview));
SaveSettings();
}
partial void OnSelectedFirstDayOfWeekIndexChanged(int value) => SaveSettings();
partial void OnIsWorkingHoursEnabledChanged(bool value) => SaveSettings();
partial void OnWorkingHourStartChanged(TimeSpan value) => SaveSettings();
partial void OnWorkingHourEndChanged(TimeSpan value) => SaveSettings();
partial void OnWorkingDayStartIndexChanged(int value) => SaveSettings();
partial void OnWorkingDayEndIndexChanged(int value) => SaveSettings();
partial void OnTimedDayHeaderDateFormatChanged(string value)
{
OnPropertyChanged(nameof(TimedDayHeaderFormatPreview));
OnPropertyChanged(nameof(TimedHourLabelPreview));
var normalizedFormat = string.IsNullOrWhiteSpace(value) ? "ddd dd" : value.Trim();
var matchingPresetIndex = TimedDayHeaderFormatPresets
.Select((format, index) => new { format, index })
.Where(item => string.Equals(item.format, normalizedFormat, StringComparison.Ordinal))
.Select(item => item.index)
.DefaultIfEmpty(-1)
.First();
if (SelectedTimedDayHeaderFormatPresetIndex != matchingPresetIndex)
{
SelectedTimedDayHeaderFormatPresetIndex = matchingPresetIndex;
}
SaveSettings();
}
partial void OnSelectedTimedDayHeaderFormatPresetIndexChanged(int value)
{
if (value < 0 || value >= TimedDayHeaderFormatPresets.Count)
return;
var selectedPreset = TimedDayHeaderFormatPresets[value];
if (string.Equals(TimedDayHeaderDateFormat, selectedPreset, StringComparison.Ordinal))
return;
TimedDayHeaderDateFormat = selectedPreset;
}
public string TimedDayHeaderFormatPreview
{
get
{
var format = string.IsNullOrWhiteSpace(TimedDayHeaderDateFormat) ? "ddd dd" : TimedDayHeaderDateFormat.Trim();
var previewDates = new[]
{
new DateTime(2026, 3, 23),
new DateTime(2026, 3, 24),
new DateTime(2026, 3, 25)
};
try
{
return string.Join(" · ", previewDates.Select(date => date.ToString(format, CalendarCulture)));
}
catch (FormatException)
{
return string.Join(" · ", previewDates.Select(date => date.ToString("ddd dd", CalendarCulture)));
}
}
}
public string TimedHourLabelPreview
=> string.Join(" · ", new[] { 0, 9, 14, 24 }.Select(CurrentSettingsPreviewLabel));
private string CurrentSettingsPreviewLabel(int hour)
{
if (Is24HourHeaders)
return hour.ToString(CalendarCulture);
var displayHour = hour % 24;
return DateTime.Today.AddHours(displayHour).ToString("h tt", CalendarCulture);
}
private void SaveSettings()
{
if (!IsLoaded)
return;
PreferencesService.FirstDayOfWeek = SelectedFirstDayOfWeekIndex switch
{
0 => DayOfWeek.Sunday,
1 => DayOfWeek.Monday,
2 => DayOfWeek.Tuesday,
3 => DayOfWeek.Wednesday,
4 => DayOfWeek.Thursday,
5 => DayOfWeek.Friday,
6 => DayOfWeek.Saturday,
_ => throw new ArgumentOutOfRangeException()
};
PreferencesService.WorkingDayStart = WorkingDayStartIndex switch
{
0 => DayOfWeek.Sunday,
1 => DayOfWeek.Monday,
2 => DayOfWeek.Tuesday,
3 => DayOfWeek.Wednesday,
4 => DayOfWeek.Thursday,
5 => DayOfWeek.Friday,
6 => DayOfWeek.Saturday,
_ => throw new ArgumentOutOfRangeException()
};
PreferencesService.WorkingDayEnd = WorkingDayEndIndex switch
{
0 => DayOfWeek.Sunday,
1 => DayOfWeek.Monday,
2 => DayOfWeek.Tuesday,
3 => DayOfWeek.Wednesday,
4 => DayOfWeek.Thursday,
5 => DayOfWeek.Friday,
6 => DayOfWeek.Saturday,
_ => throw new ArgumentOutOfRangeException()
};
PreferencesService.Prefer24HourTimeFormat = Is24HourHeaders;
PreferencesService.IsWorkingHoursEnabled = IsWorkingHoursEnabled;
PreferencesService.WorkingHourStart = WorkingHourStart;
PreferencesService.WorkingHourEnd = WorkingHourEnd;
PreferencesService.HourHeight = CellHourHeight;
PreferencesService.CalendarTimedDayHeaderDateFormat = TimedDayHeaderDateFormat;
}
}
@@ -1,402 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Calendar.ViewModels.Data;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Translations;
using Wino.Core.ViewModels;
namespace Wino.Calendar.ViewModels;
public partial class CalendarSettingsPageViewModel : CalendarBaseViewModel
{
[ObservableProperty]
public partial double CellHourHeight { get; set; }
[ObservableProperty]
public partial int SelectedFirstDayOfWeekIndex { get; set; }
[ObservableProperty]
public partial bool Is24HourHeaders { get; set; }
[ObservableProperty]
public partial bool IsWorkingHoursEnabled { get; set; }
[ObservableProperty]
public partial TimeSpan WorkingHourStart { get; set; }
[ObservableProperty]
public partial TimeSpan WorkingHourEnd { get; set; }
[ObservableProperty]
public partial List<string> DayNames { get; set; } = [];
[ObservableProperty]
public partial int WorkingDayStartIndex { get; set; }
[ObservableProperty]
public partial int WorkingDayEndIndex { get; set; }
[ObservableProperty]
public partial string TimedDayHeaderDateFormat { get; set; } = "ddd dd";
[ObservableProperty]
public partial int SelectedTimedDayHeaderFormatPresetIndex { get; set; } = -1;
[ObservableProperty]
public partial List<string> ReminderOptions { get; set; } = [];
[ObservableProperty]
public partial int SelectedDefaultReminderIndex { get; set; }
[ObservableProperty]
public partial List<string> SnoozeOptions { get; set; } = [];
[ObservableProperty]
public partial int SelectedDefaultSnoozeIndex { get; set; }
public ObservableCollection<MailAccount> Accounts { get; } = [];
public ObservableCollection<CalendarNewEventBehaviorOption> NewEventBehaviorOptions { get; } = [];
public ObservableCollection<AccountCalendarViewModel> AvailableNewEventCalendars { get; } = [];
public ObservableCollection<string> TimedDayHeaderFormatPresets { get; } =
[
"ddd dd",
"dddd dd",
"ddd d MMM",
"dd MMM ddd",
"M/d ddd"
];
[ObservableProperty]
public partial CalendarNewEventBehaviorOption SelectedNewEventBehaviorOption { get; set; }
[ObservableProperty]
public partial AccountCalendarViewModel SelectedNewEventCalendar { get; set; }
public bool ShouldShowSpecificNewEventCalendar => SelectedNewEventBehaviorOption?.Behavior == NewEventButtonBehavior.AlwaysUseSpecificCalendar;
public IPreferencesService PreferencesService { get; }
private readonly ICalendarService _calendarService;
private readonly IAccountService _accountService;
private readonly CultureInfo _calendarCulture;
private readonly bool _isLoaded = false;
public CalendarSettingsPageViewModel(IPreferencesService preferencesService, ICalendarService calendarService, IAccountService accountService)
{
PreferencesService = preferencesService;
_calendarService = calendarService;
_accountService = accountService;
var currentLanguageLanguageCode = WinoTranslationDictionary.GetLanguageFileNameRelativePath(preferencesService.CurrentLanguage);
var cultureInfo = new CultureInfo(currentLanguageLanguageCode);
_calendarCulture = cultureInfo;
for (var i = 0; i < 7; i++)
{
DayNames.Add(cultureInfo.DateTimeFormat.DayNames[i]);
}
var cultureFirstDayName = cultureInfo.DateTimeFormat.GetDayName(preferencesService.FirstDayOfWeek);
SelectedFirstDayOfWeekIndex = DayNames.IndexOf(cultureFirstDayName);
Is24HourHeaders = preferencesService.Prefer24HourTimeFormat;
IsWorkingHoursEnabled = preferencesService.IsWorkingHoursEnabled;
WorkingHourStart = preferencesService.WorkingHourStart;
WorkingHourEnd = preferencesService.WorkingHourEnd;
CellHourHeight = preferencesService.HourHeight;
WorkingDayStartIndex = DayNames.IndexOf(cultureInfo.DateTimeFormat.GetDayName(preferencesService.WorkingDayStart));
WorkingDayEndIndex = DayNames.IndexOf(cultureInfo.DateTimeFormat.GetDayName(preferencesService.WorkingDayEnd));
TimedDayHeaderDateFormat = preferencesService.CalendarTimedDayHeaderDateFormat;
SelectedTimedDayHeaderFormatPresetIndex = TimedDayHeaderFormatPresets.IndexOf(TimedDayHeaderDateFormat);
var predefinedMinutes = _calendarService.GetPredefinedReminderMinutes();
ReminderOptions.Add("None");
foreach (var minutes in predefinedMinutes)
{
var displayText = minutes switch
{
>= 60 => $"{minutes / 60} Hour{(minutes / 60 > 1 ? "s" : "")}",
_ => $"{minutes} Minute{(minutes > 1 ? "s" : "")}"
};
ReminderOptions.Add(displayText);
}
if (preferencesService.DefaultReminderDurationInSeconds == 0)
{
SelectedDefaultReminderIndex = 0;
}
else
{
var minutes = (int)(preferencesService.DefaultReminderDurationInSeconds / 60);
var index = Array.IndexOf(predefinedMinutes, minutes);
SelectedDefaultReminderIndex = index >= 0 ? index + 1 : 0;
}
var supportedSnoozeMinutes = CalendarReminderSnoozeOptions.GetSupportedSnoozeMinutes().ToArray();
foreach (var snoozeMinutes in supportedSnoozeMinutes)
{
SnoozeOptions.Add(string.Format(Translator.CalendarReminder_SnoozeMinutesOption, snoozeMinutes));
}
var selectedSnoozeIndex = Array.IndexOf(supportedSnoozeMinutes, preferencesService.DefaultSnoozeDurationInMinutes);
SelectedDefaultSnoozeIndex = selectedSnoozeIndex >= 0 ? selectedSnoozeIndex : 0;
NewEventBehaviorOptions.Add(new CalendarNewEventBehaviorOption(NewEventButtonBehavior.AskEachTime, Translator.CalendarSettings_NewEventBehavior_AskEachTime));
NewEventBehaviorOptions.Add(new CalendarNewEventBehaviorOption(NewEventButtonBehavior.AlwaysUseSpecificCalendar, Translator.CalendarSettings_NewEventBehavior_AlwaysUseSpecificCalendar));
SelectedNewEventBehaviorOption = NewEventBehaviorOptions.FirstOrDefault(option => option.Behavior == preferencesService.NewEventButtonBehavior)
?? NewEventBehaviorOptions.First();
_isLoaded = true;
LoadAccountsAsync();
}
private async void LoadAccountsAsync()
{
var accounts = await _accountService.GetAccountsAsync().ConfigureAwait(false);
var calendarsByAccount = new List<(MailAccount Account, List<AccountCalendarViewModel> Calendars)>();
foreach (var account in accounts)
{
var calendars = await _calendarService.GetAccountCalendarsAsync(account.Id).ConfigureAwait(false);
calendarsByAccount.Add((account, calendars.Select(calendar => new AccountCalendarViewModel(account, calendar)).ToList()));
}
await Dispatcher.ExecuteOnUIThread(() =>
{
Accounts.Clear();
AvailableNewEventCalendars.Clear();
foreach (var account in accounts)
{
Accounts.Add(account);
}
foreach (var accountCalendars in calendarsByAccount)
{
foreach (var calendar in accountCalendars.Calendars)
{
AvailableNewEventCalendars.Add(calendar);
}
}
ApplyStoredNewEventCalendarPreference();
});
}
partial void OnCellHourHeightChanged(double oldValue, double newValue) => SaveSettings();
partial void OnIs24HourHeadersChanged(bool value)
{
OnPropertyChanged(nameof(TimedHourLabelPreview));
SaveSettings();
}
partial void OnSelectedFirstDayOfWeekIndexChanged(int value) => SaveSettings();
partial void OnIsWorkingHoursEnabledChanged(bool value) => SaveSettings();
partial void OnWorkingHourStartChanged(TimeSpan value) => SaveSettings();
partial void OnWorkingHourEndChanged(TimeSpan value) => SaveSettings();
partial void OnWorkingDayStartIndexChanged(int value) => SaveSettings();
partial void OnWorkingDayEndIndexChanged(int value) => SaveSettings();
partial void OnTimedDayHeaderDateFormatChanged(string value)
{
OnPropertyChanged(nameof(TimedDayHeaderFormatPreview));
OnPropertyChanged(nameof(TimedHourLabelPreview));
var normalizedFormat = string.IsNullOrWhiteSpace(value) ? "ddd dd" : value.Trim();
var matchingPresetIndex = TimedDayHeaderFormatPresets
.Select((format, index) => new { format, index })
.Where(item => string.Equals(item.format, normalizedFormat, StringComparison.Ordinal))
.Select(item => item.index)
.DefaultIfEmpty(-1)
.First();
if (SelectedTimedDayHeaderFormatPresetIndex != matchingPresetIndex)
{
SelectedTimedDayHeaderFormatPresetIndex = matchingPresetIndex;
}
SaveSettings();
}
partial void OnSelectedTimedDayHeaderFormatPresetIndexChanged(int value)
{
if (value < 0 || value >= TimedDayHeaderFormatPresets.Count)
{
return;
}
var selectedPreset = TimedDayHeaderFormatPresets[value];
if (string.Equals(TimedDayHeaderDateFormat, selectedPreset, StringComparison.Ordinal))
{
return;
}
TimedDayHeaderDateFormat = selectedPreset;
}
partial void OnSelectedDefaultReminderIndexChanged(int value) => SaveSettings();
partial void OnSelectedDefaultSnoozeIndexChanged(int value) => SaveSettings();
partial void OnSelectedNewEventBehaviorOptionChanged(CalendarNewEventBehaviorOption value)
{
OnPropertyChanged(nameof(ShouldShowSpecificNewEventCalendar));
SaveSettings();
}
partial void OnSelectedNewEventCalendarChanged(AccountCalendarViewModel value) => SaveSettings();
public string TimedDayHeaderFormatPreview
{
get
{
var format = string.IsNullOrWhiteSpace(TimedDayHeaderDateFormat) ? "ddd dd" : TimedDayHeaderDateFormat.Trim();
var previewDates = new[]
{
new DateTime(2026, 3, 23),
new DateTime(2026, 3, 24),
new DateTime(2026, 3, 25)
};
try
{
return string.Join(" · ", previewDates.Select(date => date.ToString(format, _calendarCulture)));
}
catch (FormatException)
{
return string.Join(" · ", previewDates.Select(date => date.ToString("ddd dd", _calendarCulture)));
}
}
}
public string TimedHourLabelPreview
{
get
{
var previewHours = new[] { 0, 9, 14, 24 };
return string.Join(" · ", previewHours.Select(CurrentSettingsPreviewLabel));
}
}
private string CurrentSettingsPreviewLabel(int hour)
{
if (Is24HourHeaders)
{
return hour.ToString(_calendarCulture);
}
var displayHour = hour % 24;
return DateTime.Today.AddHours(displayHour).ToString("h tt", _calendarCulture);
}
public void SaveSettings()
{
if (!_isLoaded)
return;
PreferencesService.FirstDayOfWeek = SelectedFirstDayOfWeekIndex switch
{
0 => DayOfWeek.Sunday,
1 => DayOfWeek.Monday,
2 => DayOfWeek.Tuesday,
3 => DayOfWeek.Wednesday,
4 => DayOfWeek.Thursday,
5 => DayOfWeek.Friday,
6 => DayOfWeek.Saturday,
_ => throw new ArgumentOutOfRangeException()
};
PreferencesService.WorkingDayStart = WorkingDayStartIndex switch
{
0 => DayOfWeek.Sunday,
1 => DayOfWeek.Monday,
2 => DayOfWeek.Tuesday,
3 => DayOfWeek.Wednesday,
4 => DayOfWeek.Thursday,
5 => DayOfWeek.Friday,
6 => DayOfWeek.Saturday,
_ => throw new ArgumentOutOfRangeException()
};
PreferencesService.WorkingDayEnd = WorkingDayEndIndex switch
{
0 => DayOfWeek.Sunday,
1 => DayOfWeek.Monday,
2 => DayOfWeek.Tuesday,
3 => DayOfWeek.Wednesday,
4 => DayOfWeek.Thursday,
5 => DayOfWeek.Friday,
6 => DayOfWeek.Saturday,
_ => throw new ArgumentOutOfRangeException()
};
PreferencesService.Prefer24HourTimeFormat = Is24HourHeaders;
PreferencesService.IsWorkingHoursEnabled = IsWorkingHoursEnabled;
PreferencesService.WorkingHourStart = WorkingHourStart;
PreferencesService.WorkingHourEnd = WorkingHourEnd;
PreferencesService.HourHeight = CellHourHeight;
PreferencesService.CalendarTimedDayHeaderDateFormat = TimedDayHeaderDateFormat;
if (SelectedDefaultReminderIndex == 0)
{
PreferencesService.DefaultReminderDurationInSeconds = 0;
}
else
{
var predefinedMinutes = _calendarService.GetPredefinedReminderMinutes();
var minutes = predefinedMinutes[SelectedDefaultReminderIndex - 1];
PreferencesService.DefaultReminderDurationInSeconds = minutes * 60;
}
var supportedSnoozeMinutes = CalendarReminderSnoozeOptions.GetSupportedSnoozeMinutes();
if (supportedSnoozeMinutes.Count > 0)
{
var selectedIndex = Math.Clamp(SelectedDefaultSnoozeIndex, 0, supportedSnoozeMinutes.Count - 1);
PreferencesService.DefaultSnoozeDurationInMinutes = supportedSnoozeMinutes[selectedIndex];
}
var newEventBehavior = SelectedNewEventBehaviorOption?.Behavior ?? NewEventButtonBehavior.AskEachTime;
if (newEventBehavior == NewEventButtonBehavior.AlwaysUseSpecificCalendar && SelectedNewEventCalendar != null)
{
PreferencesService.NewEventButtonBehavior = NewEventButtonBehavior.AlwaysUseSpecificCalendar;
PreferencesService.DefaultNewEventCalendarId = SelectedNewEventCalendar.Id;
}
else
{
PreferencesService.NewEventButtonBehavior = NewEventButtonBehavior.AskEachTime;
PreferencesService.DefaultNewEventCalendarId = null;
}
}
private void ApplyStoredNewEventCalendarPreference()
{
var configuredCalendarId = PreferencesService.DefaultNewEventCalendarId;
var configuredCalendar = configuredCalendarId.HasValue
? AvailableNewEventCalendars.FirstOrDefault(calendar => calendar.Id == configuredCalendarId.Value)
: null;
if (PreferencesService.NewEventButtonBehavior == NewEventButtonBehavior.AlwaysUseSpecificCalendar && configuredCalendar == null)
{
SelectedNewEventBehaviorOption = NewEventBehaviorOptions.First(option => option.Behavior == NewEventButtonBehavior.AskEachTime);
SelectedNewEventCalendar = null;
return;
}
SelectedNewEventCalendar = configuredCalendar
?? AvailableNewEventCalendars.FirstOrDefault(calendar => calendar.IsPrimary)
?? AvailableNewEventCalendars.FirstOrDefault();
}
}
public sealed class CalendarNewEventBehaviorOption
{
public NewEventButtonBehavior Behavior { get; }
public string DisplayText { get; }
public CalendarNewEventBehaviorOption(NewEventButtonBehavior behavior, string displayText)
{
Behavior = behavior;
DisplayText = displayText;
}
}
@@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using Wino.Calendar.ViewModels.Data;
using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Translations;
using Wino.Core.ViewModels;
namespace Wino.Calendar.ViewModels;
public abstract class CalendarSettingsSectionViewModelBase : CalendarBaseViewModel
{
protected CalendarSettingsSectionViewModelBase(
IPreferencesService preferencesService,
ICalendarService calendarService,
IAccountService accountService)
{
PreferencesService = preferencesService;
CalendarService = calendarService;
AccountService = accountService;
var languageCode = WinoTranslationDictionary.GetLanguageFileNameRelativePath(preferencesService.CurrentLanguage);
CalendarCulture = new CultureInfo(languageCode);
for (var index = 0; index < 7; index++)
{
DayNames.Add(CalendarCulture.DateTimeFormat.DayNames[index]);
}
}
protected IPreferencesService PreferencesService { get; }
protected ICalendarService CalendarService { get; }
protected IAccountService AccountService { get; }
protected CultureInfo CalendarCulture { get; }
protected bool IsLoaded { get; set; }
public ObservableCollection<string> DayNames { get; } = [];
public ObservableCollection<string> ReminderOptions { get; } = [];
public ObservableCollection<string> SnoozeOptions { get; } = [];
public ObservableCollection<CalendarNewEventBehaviorOption> NewEventBehaviorOptions { get; } = [];
public ObservableCollection<AccountCalendarViewModel> AvailableNewEventCalendars { get; } = [];
public ObservableCollection<string> TimedDayHeaderFormatPresets { get; } =
[
"ddd dd",
"dddd dd",
"ddd d MMM",
"dd MMM ddd",
"M/d ddd"
];
protected void LoadReminderOptions()
{
ReminderOptions.Clear();
var predefinedMinutes = CalendarService.GetPredefinedReminderMinutes();
ReminderOptions.Add("None");
foreach (var minutes in predefinedMinutes)
{
var displayText = minutes switch
{
>= 60 => $"{minutes / 60} Hour{(minutes / 60 > 1 ? "s" : "")}",
_ => $"{minutes} Minute{(minutes > 1 ? "s" : "")}"
};
ReminderOptions.Add(displayText);
}
}
protected int GetSelectedReminderIndex()
{
if (PreferencesService.DefaultReminderDurationInSeconds == 0)
return 0;
var minutes = (int)(PreferencesService.DefaultReminderDurationInSeconds / 60);
var predefinedMinutes = CalendarService.GetPredefinedReminderMinutes();
var index = Array.IndexOf(predefinedMinutes, minutes);
return index >= 0 ? index + 1 : 0;
}
protected void SaveReminderIndex(int selectedDefaultReminderIndex)
{
if (selectedDefaultReminderIndex == 0)
{
PreferencesService.DefaultReminderDurationInSeconds = 0;
return;
}
var predefinedMinutes = CalendarService.GetPredefinedReminderMinutes();
var minutes = predefinedMinutes[selectedDefaultReminderIndex - 1];
PreferencesService.DefaultReminderDurationInSeconds = minutes * 60;
}
protected void LoadSnoozeOptions()
{
SnoozeOptions.Clear();
foreach (var snoozeMinutes in CalendarReminderSnoozeOptions.GetSupportedSnoozeMinutes())
{
SnoozeOptions.Add(string.Format(Translator.CalendarReminder_SnoozeMinutesOption, snoozeMinutes));
}
}
protected int GetSelectedSnoozeIndex()
{
var supportedSnoozeMinutes = CalendarReminderSnoozeOptions.GetSupportedSnoozeMinutes().ToArray();
var selectedIndex = Array.IndexOf(supportedSnoozeMinutes, PreferencesService.DefaultSnoozeDurationInMinutes);
return selectedIndex >= 0 ? selectedIndex : 0;
}
protected void SaveSnoozeIndex(int selectedDefaultSnoozeIndex)
{
var supportedSnoozeMinutes = CalendarReminderSnoozeOptions.GetSupportedSnoozeMinutes();
if (supportedSnoozeMinutes.Count == 0)
return;
var selectedIndex = Math.Clamp(selectedDefaultSnoozeIndex, 0, supportedSnoozeMinutes.Count - 1);
PreferencesService.DefaultSnoozeDurationInMinutes = supportedSnoozeMinutes[selectedIndex];
}
protected void LoadNewEventBehaviorOptions()
{
NewEventBehaviorOptions.Clear();
NewEventBehaviorOptions.Add(new CalendarNewEventBehaviorOption(NewEventButtonBehavior.AskEachTime, Translator.CalendarSettings_NewEventBehavior_AskEachTime));
NewEventBehaviorOptions.Add(new CalendarNewEventBehaviorOption(NewEventButtonBehavior.AlwaysUseSpecificCalendar, Translator.CalendarSettings_NewEventBehavior_AlwaysUseSpecificCalendar));
}
protected CalendarNewEventBehaviorOption GetSelectedNewEventBehaviorOption()
=> NewEventBehaviorOptions.FirstOrDefault(option => option.Behavior == PreferencesService.NewEventButtonBehavior)
?? NewEventBehaviorOptions.First();
protected async void LoadCalendarsAsync(Action applySelection)
{
var accounts = await AccountService.GetAccountsAsync().ConfigureAwait(false);
var calendarsByAccount = new List<AccountCalendarViewModel>();
foreach (var account in accounts)
{
var calendars = await CalendarService.GetAccountCalendarsAsync(account.Id).ConfigureAwait(false);
calendarsByAccount.AddRange(calendars.Select(calendar => new AccountCalendarViewModel(account, calendar)));
}
await ExecuteUIThread(() =>
{
AvailableNewEventCalendars.Clear();
foreach (var calendar in calendarsByAccount)
{
AvailableNewEventCalendars.Add(calendar);
}
applySelection();
});
}
protected AccountCalendarViewModel ResolveSelectedNewEventCalendar()
{
var configuredCalendarId = PreferencesService.DefaultNewEventCalendarId;
return configuredCalendarId.HasValue
? AvailableNewEventCalendars.FirstOrDefault(calendar => calendar.Id == configuredCalendarId.Value)
: null;
}
protected AccountCalendarViewModel ResolveFallbackNewEventCalendar()
=> AvailableNewEventCalendars.FirstOrDefault(calendar => calendar.IsPrimary)
?? AvailableNewEventCalendars.FirstOrDefault();
protected void SaveNewEventBehavior(CalendarNewEventBehaviorOption selectedBehaviorOption, AccountCalendarViewModel selectedCalendar)
{
var newEventBehavior = selectedBehaviorOption?.Behavior ?? NewEventButtonBehavior.AskEachTime;
if (newEventBehavior == NewEventButtonBehavior.AlwaysUseSpecificCalendar && selectedCalendar != null)
{
PreferencesService.NewEventButtonBehavior = NewEventButtonBehavior.AlwaysUseSpecificCalendar;
PreferencesService.DefaultNewEventCalendarId = selectedCalendar.Id;
return;
}
PreferencesService.NewEventButtonBehavior = NewEventButtonBehavior.AskEachTime;
PreferencesService.DefaultNewEventCalendarId = null;
}
}
public sealed class CalendarNewEventBehaviorOption
{
public CalendarNewEventBehaviorOption(NewEventButtonBehavior behavior, string displayText)
{
Behavior = behavior;
DisplayText = displayText;
}
public NewEventButtonBehavior Behavior { get; }
public string DisplayText { get; }
}
+3 -1
View File
@@ -21,7 +21,6 @@ public enum WinoPage
MessageListPage,
MailListPage,
ReadComposePanePage,
LanguageTimePage,
AppPreferencesPage,
SettingOptionsPage,
AliasManagementPage,
@@ -29,6 +28,9 @@ public enum WinoPage
KeyboardShortcutsPage,
CalendarPage,
CalendarSettingsPage,
CalendarRenderingSettingsPage,
CalendarNotificationSettingsPage,
CalendarPreferenceSettingsPage,
CalendarAccountSettingsPage,
EventDetailsPage,
CalendarEventComposePage,
@@ -47,11 +47,11 @@ public static class SettingsNavigationInfoProvider
Translator.SettingsAppPreferences_Description,
"\uE770",
searchKeywords: Translator.SettingsSearch_AppPreferences_Keywords),
new(WinoPage.LanguageTimePage,
Translator.SettingsLanguageTime_Title,
Translator.SettingsLanguageTime_Description,
"\uE775",
searchKeywords: Translator.SettingsSearch_LanguageTime_Keywords),
new(WinoPage.KeyboardShortcutsPage,
Translator.Settings_KeyboardShortcuts_Title,
Translator.Settings_KeyboardShortcuts_Description,
"\uE765",
searchKeywords: Translator.SettingsSearch_KeyboardShortcuts_Keywords),
new(WinoPage.PersonalizationPage,
Translator.SettingsPersonalization_Title,
Translator.SettingsPersonalization_Description,
@@ -63,11 +63,6 @@ public static class SettingsNavigationInfoProvider
"\uE946",
searchKeywords: Translator.SettingsSearch_About_Keywords),
new(null, Translator.SettingsOptions_MailSection, string.Empty, "\uE715", isSeparator: true),
new(WinoPage.KeyboardShortcutsPage,
Translator.Settings_KeyboardShortcuts_Title,
Translator.Settings_KeyboardShortcuts_Description,
"\uE765",
searchKeywords: Translator.SettingsSearch_KeyboardShortcuts_Keywords),
new(WinoPage.MessageListPage,
Translator.SettingsMessageList_Title,
Translator.SettingsMessageList_Description,
@@ -89,11 +84,22 @@ public static class SettingsNavigationInfoProvider
"\uE81C",
searchKeywords: Translator.SettingsSearch_Storage_Keywords),
new(null, Translator.SettingsOptions_CalendarSection, string.Empty, "\uE787", isSeparator: true),
new(WinoPage.CalendarSettingsPage,
Translator.SettingsCalendarSettings_Title,
Translator.SettingsCalendarSettings_Description,
new(WinoPage.CalendarRenderingSettingsPage,
Translator.CalendarSettings_Rendering_Title,
Translator.CalendarSettings_Rendering_Description,
"\uE787",
searchKeywords: Translator.SettingsSearch_CalendarSettings_Keywords)
,
new(WinoPage.CalendarNotificationSettingsPage,
Translator.CalendarSettings_Notifications_Title,
Translator.CalendarSettings_Notifications_Description,
"\uE7F4",
searchKeywords: Translator.SettingsSearch_CalendarSettings_Keywords),
new(WinoPage.CalendarPreferenceSettingsPage,
Translator.CalendarSettings_Preferences_Title,
Translator.CalendarSettings_Preferences_Description,
"\uE713",
searchKeywords: Translator.SettingsSearch_CalendarSettings_Keywords)
];
}
@@ -140,9 +146,11 @@ public static class SettingsNavigationInfoProvider
WinoPage.AboutPage => Translator.SettingsAbout_Title,
WinoPage.MessageListPage => Translator.SettingsMessageList_Title,
WinoPage.ReadComposePanePage => Translator.SettingsReadComposePane_Title,
WinoPage.LanguageTimePage => Translator.SettingsLanguageTime_Title,
WinoPage.AppPreferencesPage => Translator.SettingsAppPreferences_Title,
WinoPage.CalendarSettingsPage => Translator.SettingsCalendarSettings_Title,
WinoPage.CalendarSettingsPage => Translator.CalendarSettings_Preferences_Title,
WinoPage.CalendarRenderingSettingsPage => Translator.CalendarSettings_Rendering_Title,
WinoPage.CalendarNotificationSettingsPage => Translator.CalendarSettings_Notifications_Title,
WinoPage.CalendarPreferenceSettingsPage => Translator.CalendarSettings_Preferences_Title,
WinoPage.SignatureAndEncryptionPage => Translator.SettingsSignatureAndEncryption_Title,
WinoPage.KeyboardShortcutsPage => Translator.Settings_KeyboardShortcuts_Title,
WinoPage.StoragePage => Translator.SettingsStorage_Title,
@@ -162,7 +170,8 @@ public static class SettingsNavigationInfoProvider
WinoPage.ImapCalDavSettingsPage => WinoPage.ManageAccountsPage,
WinoPage.EmailTemplatesPage => WinoPage.ManageAccountsPage,
WinoPage.CreateEmailTemplatePage => WinoPage.ManageAccountsPage,
WinoPage.CalendarAccountSettingsPage => WinoPage.CalendarSettingsPage,
WinoPage.CalendarSettingsPage => WinoPage.CalendarPreferenceSettingsPage,
WinoPage.CalendarAccountSettingsPage => WinoPage.CalendarPreferenceSettingsPage,
_ => pageType
};
@@ -1127,6 +1127,12 @@
"CalendarSettings_NewEventBehavior_Description": "Choose whether the New Event button should ask for a calendar each time or always open a specific calendar.",
"CalendarSettings_NewEventBehavior_AskEachTime": "Ask each time.",
"CalendarSettings_NewEventBehavior_AlwaysUseSpecificCalendar": "Always use specific calendar.",
"CalendarSettings_Rendering_Title": "Rendering",
"CalendarSettings_Rendering_Description": "Configure calendar layout and display behavior.",
"CalendarSettings_Notifications_Title": "Notifications",
"CalendarSettings_Notifications_Description": "Choose default reminder and snooze behavior.",
"CalendarSettings_Preferences_Title": "Preferences",
"CalendarSettings_Preferences_Description": "Set how the New Event button behaves.",
"WhatIsNew_GetStartedButton": "Get Started",
"WhatIsNew_ContinueAnywayButton": "Continue anyway",
"WhatIsNew_PreparingForNewVersionButton": "Preparing for new version...",
@@ -1176,6 +1182,12 @@
"WinoAccount_Management_AiPackPromoPrice": "$4.99 / mo",
"WinoAccount_Management_AiPackPromoRequests": "1,000 requests",
"WinoAccount_Management_AiPackGetButton": "Get AI Pack",
"WinoAddOn_AI_PACK_Name": "Wino AI Pack",
"WinoAddOn_AI_PACK_Description": "AI-powered tools for translate, rewrite, and summarize actions in Wino Mail.",
"WinoAddOn_AI_PACK_Keywords": "AI, translate, rewrite, summarize, productivity",
"WinoAddOn_UNLIMITED_ACCOUNTS_Name": "Unlimited Accounts",
"WinoAddOn_UNLIMITED_ACCOUNTS_Description": "Remove the account limit and add as many mail accounts as you need.",
"WinoAddOn_UNLIMITED_ACCOUNTS_Keywords": "accounts, unlimited, premium, add-on",
"WinoAccount_Management_PurchaseRequiresSignIn": "Sign in with your Wino Account to complete this purchase.",
"WinoAccount_Management_PurchaseStartFailed": "Wino could not start the checkout session for this add-on.",
"WinoAccount_Management_AiPackSubscriptionActive": "Your subscription is active",
@@ -116,7 +116,7 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel,
[RelayCommand]
private async Task ChangePasswordAsync()
{
var account = await _profileService.GetActiveAccountAsync().ConfigureAwait(false);
var account = await _profileService.GetActiveAccountAsync();
if (account == null)
{
_dialogService.InfoBarMessage(Translator.GeneralTitle_Warning,
@@ -128,14 +128,14 @@ public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel,
var shouldContinue = await _dialogService.ShowConfirmationDialogAsync(
string.Format(Translator.WinoAccount_ChangePassword_ConfirmationMessage, account.Email),
Translator.WinoAccount_ChangePassword_Title,
Translator.WinoAccount_ChangePassword_Action).ConfigureAwait(false);
Translator.WinoAccount_ChangePassword_Action);
if (!shouldContinue)
{
return;
}
var response = await _profileService.ForgotPasswordAsync(account.Email).ConfigureAwait(false);
var response = await _profileService.ForgotPasswordAsync(account.Email);
if (!response.IsSuccess)
{
_dialogService.InfoBarMessage(Translator.GeneralTitle_Error,
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@@ -6,73 +6,22 @@ using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Navigation;
using Wino.Core.Domain.Models.Translations;
namespace Wino.Mail.ViewModels;
public partial class AppPreferencesPageViewModel : MailBaseViewModel
{
public IPreferencesService PreferencesService { get; }
[ObservableProperty]
public partial List<string> SearchModes { get; set; }
[ObservableProperty]
public partial List<string> ApplicationModes { get; set; }
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsStartupBehaviorDisabled))]
[NotifyPropertyChangedFor(nameof(IsStartupBehaviorEnabled))]
private StartupBehaviorResult startupBehaviorResult;
private int _emailSyncIntervalMinutes;
public int EmailSyncIntervalMinutes
{
get => _emailSyncIntervalMinutes;
set
{
SetProperty(ref _emailSyncIntervalMinutes, value);
PreferencesService.EmailSyncIntervalMinutes = value;
}
}
public bool IsStartupBehaviorDisabled => !IsStartupBehaviorEnabled;
public bool IsStartupBehaviorEnabled => StartupBehaviorResult == StartupBehaviorResult.Enabled;
private string _selectedDefaultSearchMode;
public string SelectedDefaultSearchMode
{
get => _selectedDefaultSearchMode;
set
{
SetProperty(ref _selectedDefaultSearchMode, value);
PreferencesService.DefaultSearchMode = (SearchMode)SearchModes.IndexOf(value);
}
}
private string _selectedDefaultApplicationMode;
public string SelectedDefaultApplicationMode
{
get => _selectedDefaultApplicationMode;
set
{
SetProperty(ref _selectedDefaultApplicationMode, value);
PreferencesService.DefaultApplicationMode = (WinoApplicationMode)ApplicationModes.IndexOf(value);
}
}
private readonly IMailDialogService _dialogService;
private readonly IStartupBehaviorService _startupBehaviorService;
public AppPreferencesPageViewModel(IMailDialogService dialogService,
public AppPreferencesPageViewModel(
IMailDialogService dialogService,
IPreferencesService preferencesService,
IStartupBehaviorService startupBehaviorService)
IStartupBehaviorService startupBehaviorService,
ITranslationService translationService)
{
_dialogService = dialogService;
PreferencesService = preferencesService;
_startupBehaviorService = startupBehaviorService;
_translationService = translationService;
SearchModes =
[
@@ -93,17 +42,81 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
EmailSyncIntervalMinutes = PreferencesService.EmailSyncIntervalMinutes;
}
public IPreferencesService PreferencesService { get; }
[ObservableProperty]
public partial List<string> SearchModes { get; set; }
[ObservableProperty]
public partial List<string> ApplicationModes { get; set; }
[ObservableProperty]
public partial List<AppLanguageModel> AvailableLanguages { get; set; } = [];
[ObservableProperty]
public partial AppLanguageModel SelectedLanguage { get; set; }
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsStartupBehaviorDisabled))]
[NotifyPropertyChangedFor(nameof(IsStartupBehaviorEnabled))]
private StartupBehaviorResult startupBehaviorResult;
private readonly IMailDialogService _dialogService;
private readonly IStartupBehaviorService _startupBehaviorService;
private readonly ITranslationService _translationService;
private bool _isLanguageInitialized;
private int _emailSyncIntervalMinutes;
private string _selectedDefaultSearchMode;
private string _selectedDefaultApplicationMode;
public int EmailSyncIntervalMinutes
{
get => _emailSyncIntervalMinutes;
set
{
SetProperty(ref _emailSyncIntervalMinutes, value);
PreferencesService.EmailSyncIntervalMinutes = value;
}
}
public bool IsStartupBehaviorDisabled => !IsStartupBehaviorEnabled;
public bool IsStartupBehaviorEnabled => StartupBehaviorResult == StartupBehaviorResult.Enabled;
public string SelectedDefaultSearchMode
{
get => _selectedDefaultSearchMode;
set
{
SetProperty(ref _selectedDefaultSearchMode, value);
PreferencesService.DefaultSearchMode = (SearchMode)SearchModes.IndexOf(value);
}
}
public string SelectedDefaultApplicationMode
{
get => _selectedDefaultApplicationMode;
set
{
SetProperty(ref _selectedDefaultApplicationMode, value);
PreferencesService.DefaultApplicationMode = (WinoApplicationMode)ApplicationModes.IndexOf(value);
}
}
partial void OnSelectedLanguageChanged(AppLanguageModel value)
{
if (!_isLanguageInitialized || value == null)
return;
_ = _translationService.InitializeLanguageAsync(value.Language);
}
[RelayCommand]
private async Task ToggleStartupBehaviorAsync()
{
if (IsStartupBehaviorEnabled)
{
await DisableStartupAsync();
}
else
{
await EnableStartupAsync();
}
OnPropertyChanged(nameof(IsStartupBehaviorEnabled));
}
@@ -111,14 +124,12 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
private async Task EnableStartupAsync()
{
StartupBehaviorResult = await _startupBehaviorService.ToggleStartupBehavior(true);
NotifyCurrentStartupState();
}
private async Task DisableStartupAsync()
{
StartupBehaviorResult = await _startupBehaviorService.ToggleStartupBehavior(false);
NotifyCurrentStartupState();
}
@@ -146,12 +157,15 @@ public partial class AppPreferencesPageViewModel : MailBaseViewModel
}
}
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
{
base.OnNavigatedTo(mode, parameters);
AvailableLanguages = _translationService.GetAvailableLanguages();
SelectedLanguage = AvailableLanguages.Find(language => language.Language == PreferencesService.CurrentLanguage)
?? (AvailableLanguages.Count > 0 ? AvailableLanguages[0] : null);
_isLanguageInitialized = true;
StartupBehaviorResult = await _startupBehaviorService.GetCurrentStartupBehaviorAsync();
}
}
@@ -1,46 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Navigation;
using Wino.Core.Domain.Models.Translations;
namespace Wino.Mail.ViewModels;
public partial class LanguageTimePageViewModel(IPreferencesService preferencesService, ITranslationService translationService) : MailBaseViewModel
{
public IPreferencesService PreferencesService { get; } = preferencesService;
private readonly ITranslationService _translationService = translationService;
[ObservableProperty]
private List<AppLanguageModel> _availableLanguages;
[ObservableProperty]
private AppLanguageModel _selectedLanguage;
private bool isInitialized = false;
public override void OnNavigatedTo(NavigationMode mode, object parameters)
{
base.OnNavigatedTo(mode, parameters);
AvailableLanguages = _translationService.GetAvailableLanguages();
SelectedLanguage = AvailableLanguages.FirstOrDefault(a => a.Language == PreferencesService.CurrentLanguage);
isInitialized = true;
}
protected override async void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (!isInitialized) return;
if (e.PropertyName == nameof(SelectedLanguage))
{
await _translationService.InitializeLanguageAsync(SelectedLanguage.Language);
}
}
}
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
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.Interfaces;
@@ -40,6 +42,10 @@ public partial class MessageListPageViewModel : MailBaseViewModel
Translator.HoverActionOption_MoveJunk
];
public IMailItemDisplayInformation DemoPreviewMailItemInformation { get; } = new DemoMailItemDisplayInformation();
public MailListDisplayMode SelectedMailSpacingMode => availableMailSpacingOptions[selectedMailSpacingIndex];
private int selectedMarkAsOptionIndex;
public int SelectedMarkAsOptionIndex
{
@@ -62,6 +68,7 @@ public partial class MessageListPageViewModel : MailBaseViewModel
if (SetProperty(ref selectedMailSpacingIndex, value) && value >= 0 && value < availableMailSpacingOptions.Count)
{
PreferencesService.MailItemDisplayMode = availableMailSpacingOptions[value];
OnPropertyChanged(nameof(SelectedMailSpacingMode));
}
}
}
@@ -135,4 +142,32 @@ public partial class MessageListPageViewModel : MailBaseViewModel
_statePersistenceService.MailListPaneLength = 420;
_dialogService.InfoBarMessage(Translator.GeneralTitle_Info, Translator.Info_MailListSizeResetSuccessMessage, InfoBarMessageType.Success);
}
private sealed class DemoMailItemDisplayInformation : IMailItemDisplayInformation
{
public event PropertyChangedEventHandler PropertyChanged
{
add { }
remove { }
}
public string Subject => "Quarterly planning notes";
public string FromName => "Ava Brooks";
public string FromAddress => "ava@contoso.com";
public string PreviewText => "Agenda draft, attendee updates, and a few follow-up items for this week.";
public bool IsRead => false;
public bool IsDraft => false;
public bool HasAttachments => true;
public bool IsCalendarEvent => false;
public bool IsFlagged => true;
public DateTime CreationDate => DateTime.Now.AddMinutes(-12);
public Guid? ContactPictureFileId => null;
public bool ThumbnailUpdatedEvent => false;
public bool IsThreadExpanded => false;
public AccountContact SenderContact => new()
{
Address = "ava@contoso.com",
Name = "Ava Brooks"
};
}
}
+3 -2
View File
@@ -319,7 +319,6 @@ public partial class App : WinoApplication,
services.AddTransient(typeof(MessageListPageViewModel));
services.AddTransient(typeof(ReadComposePanePageViewModel));
services.AddTransient(typeof(MergedAccountDetailsPageViewModel));
services.AddTransient(typeof(LanguageTimePageViewModel));
services.AddTransient(typeof(AppPreferencesPageViewModel));
services.AddTransient(typeof(StoragePageViewModel));
services.AddTransient(typeof(WinoAccountManagementPageViewModel));
@@ -329,7 +328,9 @@ public partial class App : WinoApplication,
services.AddTransient(typeof(EmailTemplatesPageViewModel));
services.AddTransient(typeof(CreateEmailTemplatePageViewModel));
services.AddSingleton(typeof(CalendarPageViewModel));
services.AddTransient(typeof(CalendarSettingsPageViewModel));
services.AddTransient(typeof(CalendarRenderingSettingsPageViewModel));
services.AddTransient(typeof(CalendarNotificationSettingsPageViewModel));
services.AddTransient(typeof(CalendarPreferenceSettingsPageViewModel));
services.AddTransient(typeof(CalendarAccountSettingsPageViewModel));
services.AddTransient(typeof(EventDetailsPageViewModel));
services.AddTransient(typeof(CalendarEventComposePageViewModel));
@@ -80,7 +80,6 @@ public class NavigationService : NavigationServiceBase, INavigationService
WinoPage.PersonalizationPage,
WinoPage.MessageListPage,
WinoPage.ReadComposePanePage,
WinoPage.LanguageTimePage,
WinoPage.AppPreferencesPage,
WinoPage.AliasManagementPage,
WinoPage.ImapCalDavSettingsPage,
@@ -91,6 +90,9 @@ public class NavigationService : NavigationServiceBase, INavigationService
WinoPage.StoragePage,
WinoPage.WinoAccountManagementPage,
WinoPage.CalendarSettingsPage,
WinoPage.CalendarRenderingSettingsPage,
WinoPage.CalendarNotificationSettingsPage,
WinoPage.CalendarPreferenceSettingsPage,
WinoPage.CalendarAccountSettingsPage
];
@@ -148,7 +150,6 @@ public class NavigationService : NavigationServiceBase, INavigationService
WinoPage.SettingOptionsPage => typeof(SettingOptionsPage),
WinoPage.AppPreferencesPage => typeof(AppPreferencesPage),
WinoPage.AliasManagementPage => typeof(AliasManagementPage),
WinoPage.LanguageTimePage => typeof(LanguageTimePage),
WinoPage.ImapCalDavSettingsPage => typeof(ImapCalDavSettingsPage),
WinoPage.KeyboardShortcutsPage => typeof(KeyboardShortcutsPage),
WinoPage.ContactsPage => typeof(ContactsPage),
@@ -164,7 +165,10 @@ public class NavigationService : NavigationServiceBase, INavigationService
WinoPage.CalendarPage => typeof(CalendarPage),
WinoPage.EventDetailsPage => typeof(EventDetailsPage),
WinoPage.CalendarEventComposePage => typeof(CalendarEventComposePage),
WinoPage.CalendarSettingsPage => typeof(CalendarSettingsPage),
WinoPage.CalendarSettingsPage => typeof(CalendarPreferenceSettingsPage),
WinoPage.CalendarRenderingSettingsPage => typeof(CalendarRenderingSettingsPage),
WinoPage.CalendarNotificationSettingsPage => typeof(CalendarNotificationSettingsPage),
WinoPage.CalendarPreferenceSettingsPage => typeof(CalendarPreferenceSettingsPage),
WinoPage.CalendarAccountSettingsPage => typeof(CalendarAccountSettingsPage),
_ => null,
};
@@ -0,0 +1,5 @@
using Wino.Calendar.ViewModels;
namespace Wino.Mail.WinUI.Views.Abstract;
public abstract class CalendarNotificationSettingsPageAbstract : BasePage<CalendarNotificationSettingsPageViewModel> { }
@@ -0,0 +1,5 @@
using Wino.Calendar.ViewModels;
namespace Wino.Mail.WinUI.Views.Abstract;
public abstract class CalendarPreferenceSettingsPageAbstract : BasePage<CalendarPreferenceSettingsPageViewModel> { }
@@ -0,0 +1,5 @@
using Wino.Calendar.ViewModels;
namespace Wino.Mail.WinUI.Views.Abstract;
public abstract class CalendarRenderingSettingsPageAbstract : BasePage<CalendarRenderingSettingsPageViewModel> { }
@@ -1,5 +0,0 @@
using Wino.Calendar.ViewModels;
namespace Wino.Mail.WinUI.Views.Abstract;
public abstract class CalendarSettingsPageAbstract : BasePage<CalendarSettingsPageViewModel> { }
@@ -1,6 +0,0 @@
using Wino.Mail.WinUI;
using Wino.Mail.ViewModels;
namespace Wino.Views.Abstract;
public abstract class LanguageTimePageAbstract : BasePage<LanguageTimePageViewModel> { }
@@ -0,0 +1,29 @@
<abstract:CalendarNotificationSettingsPageAbstract
x:Class="Wino.Mail.WinUI.Views.Calendar.CalendarNotificationSettingsPage"
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:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:domain="using:Wino.Core.Domain"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
<controls:SettingsCard Description="Set a default reminder for all new calendar events." Header="Default reminder">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE7F4;" />
</controls:SettingsCard.HeaderIcon>
<ComboBox ItemsSource="{x:Bind ViewModel.ReminderOptions, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedDefaultReminderIndex, Mode=TwoWay}" />
</controls:SettingsCard>
<controls:SettingsCard Description="{x:Bind domain:Translator.CalendarSettings_DefaultSnoozeDuration_Description}" Header="{x:Bind domain:Translator.CalendarSettings_DefaultSnoozeDuration_Header}">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE823;" />
</controls:SettingsCard.HeaderIcon>
<ComboBox ItemsSource="{x:Bind ViewModel.SnoozeOptions, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedDefaultSnoozeIndex, Mode=TwoWay}" />
</controls:SettingsCard>
</StackPanel>
</ScrollViewer>
</abstract:CalendarNotificationSettingsPageAbstract>
@@ -0,0 +1,9 @@
namespace Wino.Mail.WinUI.Views.Calendar;
public sealed partial class CalendarNotificationSettingsPage : Wino.Mail.WinUI.Views.Abstract.CalendarNotificationSettingsPageAbstract
{
public CalendarNotificationSettingsPage()
{
InitializeComponent();
}
}
@@ -0,0 +1,51 @@
<abstract:CalendarPreferenceSettingsPageAbstract
x:Class="Wino.Mail.WinUI.Views.Calendar.CalendarPreferenceSettingsPage"
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:CommunityToolkit.WinUI.Controls"
xmlns:data="using:Wino.Calendar.ViewModels.Data"
xmlns:domain="using:Wino.Core.Domain"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
<controls:SettingsCard Description="{x:Bind domain:Translator.CalendarSettings_NewEventBehavior_Description}" Header="{x:Bind domain:Translator.CalendarSettings_NewEventBehavior_Header}">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE163;" />
</controls:SettingsCard.HeaderIcon>
<controls:SettingsCard.Content>
<StackPanel Spacing="12">
<ComboBox ItemsSource="{x:Bind ViewModel.NewEventBehaviorOptions, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.SelectedNewEventBehaviorOption, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="calendarViewModels:CalendarNewEventBehaviorOption">
<TextBlock Text="{x:Bind DisplayText}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox
ItemsSource="{x:Bind ViewModel.AvailableNewEventCalendars, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.SelectedNewEventCalendar, Mode=TwoWay}"
Visibility="{x:Bind ViewModel.ShouldShowSpecificNewEventCalendar, Mode=OneWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="data:AccountCalendarViewModel">
<StackPanel Orientation="Vertical" Spacing="2">
<TextBlock Text="{x:Bind Name}" />
<TextBlock
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind Account.Address}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</controls:SettingsCard.Content>
</controls:SettingsCard>
</StackPanel>
</ScrollViewer>
</abstract:CalendarPreferenceSettingsPageAbstract>
@@ -0,0 +1,9 @@
namespace Wino.Mail.WinUI.Views.Calendar;
public sealed partial class CalendarPreferenceSettingsPage : Wino.Mail.WinUI.Views.Abstract.CalendarPreferenceSettingsPageAbstract
{
public CalendarPreferenceSettingsPage()
{
InitializeComponent();
}
}
@@ -0,0 +1,176 @@
<abstract:CalendarRenderingSettingsPageAbstract
x:Class="Wino.Mail.WinUI.Views.Calendar.CalendarRenderingSettingsPage"
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:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:domain="using:Wino.Core.Domain"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
<controls:SettingsCard Description="Adjust the day that week starts." Header="First day of week">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE787;" />
</controls:SettingsCard.HeaderIcon>
<ComboBox ItemsSource="{x:Bind ViewModel.DayNames, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedFirstDayOfWeekIndex, Mode=TwoWay}" />
</controls:SettingsCard>
<controls:SettingsExpander Description="Set the day range for your working hours." Header="Working days">
<controls:SettingsExpander.HeaderIcon>
<FontIcon Glyph="&#xE8EF;" />
</controls:SettingsExpander.HeaderIcon>
<controls:SettingsExpander.Items>
<controls:SettingsCard HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" ContentAlignment="Vertical">
<controls:SettingsCard.Content>
<StackPanel Spacing="16">
<StackPanel Spacing="6">
<TextBlock FontWeight="SemiBold" Text="Highlight working hours" />
<ToggleSwitch
IsOn="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=TwoWay}"
OffContent="Off"
OnContent="On" />
</StackPanel>
<Grid RowSpacing="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" FontWeight="Bold" Text="From" />
<ComboBox
Grid.Column="1"
IsEnabled="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=OneWay}"
ItemsSource="{x:Bind ViewModel.DayNames, Mode=OneWay}"
SelectedIndex="{x:Bind ViewModel.WorkingDayStartIndex, Mode=TwoWay}" />
<TimePicker
x:Name="WorkHourStartPicker"
Grid.Column="2"
Margin="12,0"
IsEnabled="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=OneWay}"
Time="{x:Bind ViewModel.WorkingHourStart, Mode=TwoWay}" />
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" FontWeight="Bold" Text="To" />
<ComboBox
Grid.Column="1"
IsEnabled="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=OneWay}"
ItemsSource="{x:Bind ViewModel.DayNames, Mode=OneWay}"
SelectedIndex="{x:Bind ViewModel.WorkingDayEndIndex, Mode=TwoWay}" />
<TimePicker
x:Name="WorkHourEndPicker"
Grid.Column="2"
Margin="12,0"
IsEnabled="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=OneWay}"
Time="{x:Bind ViewModel.WorkingHourEnd, Mode=TwoWay}" />
</Grid>
</Grid>
</StackPanel>
</controls:SettingsCard.Content>
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
<controls:SettingsExpander Description="Adjust calendar timeline rendering options." Header="Calendar rendering" IsExpanded="True">
<controls:SettingsExpander.HeaderIcon>
<FontIcon Glyph="&#xE9D2;" />
</controls:SettingsExpander.HeaderIcon>
<controls:SettingsExpander.Items>
<controls:SettingsCard
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
ContentAlignment="Vertical"
Description="How many pixels should 1 hour representation occupy in daily/weekly calendars."
Header="Hour height">
<StackPanel Spacing="12">
<Slider
x:Name="HourCellSlider"
LargeChange="10"
Maximum="120"
Minimum="40"
SmallChange="5"
StepFrequency="5"
Value="{x:Bind ViewModel.CellHourHeight, Mode=TwoWay}" />
<Grid ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Bottom" Text="00:00" />
<Grid
Grid.Column="1"
Width="100"
Height="{x:Bind HourCellSlider.Value, Mode=OneWay}"
VerticalAlignment="Center"
BorderBrush="Black"
BorderThickness="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="1" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Grid.Row="1" HorizontalAlignment="Stretch" Stroke="Black" StrokeThickness="0.5" />
</Grid>
</Grid>
</StackPanel>
</controls:SettingsCard>
<controls:SettingsCard Description="Set whether you want to use AM/PM or 24 hour clock identifier." Header="Clock identifier for headers">
<StackPanel Spacing="8">
<ToggleSwitch
HorizontalAlignment="Right"
IsOn="{x:Bind ViewModel.Is24HourHeaders, Mode=TwoWay}"
OffContent="12h"
OnContent="24h" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.TimedHourLabelPreview, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
</StackPanel>
</controls:SettingsCard>
<controls:SettingsCard Description="{x:Bind domain:Translator.CalendarSettings_TimedDayHeaderFormat_Description}" Header="{x:Bind domain:Translator.CalendarSettings_TimedDayHeaderFormat_Header}">
<StackPanel Spacing="8">
<TextBox PlaceholderText="ddd dd" Text="{x:Bind ViewModel.TimedDayHeaderDateFormat, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<ComboBox ItemsSource="{x:Bind ViewModel.TimedDayHeaderFormatPresets, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedTimedDayHeaderFormatPresetIndex, Mode=TwoWay}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.TimedDayHeaderFormatPreview, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
</StackPanel>
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
</StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ClockIdentifierStates">
<VisualState x:Name="TwelveHour" />
<VisualState x:Name="TwentyFourHour">
<VisualState.StateTriggers>
<StateTrigger IsActive="{x:Bind ViewModel.Is24HourHeaders, Mode=OneWay}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="WorkHourStartPicker.ClockIdentifier" Value="24HourClock" />
<Setter Target="WorkHourEndPicker.ClockIdentifier" Value="24HourClock" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ScrollViewer>
</abstract:CalendarRenderingSettingsPageAbstract>
@@ -0,0 +1,9 @@
namespace Wino.Mail.WinUI.Views.Calendar;
public sealed partial class CalendarRenderingSettingsPage : Wino.Mail.WinUI.Views.Abstract.CalendarRenderingSettingsPageAbstract
{
public CalendarRenderingSettingsPage()
{
InitializeComponent();
}
}
@@ -1,338 +0,0 @@
<abstract:CalendarSettingsPageAbstract
x:Class="Wino.Mail.WinUI.Views.Calendar.CalendarSettingsPage"
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:CommunityToolkit.WinUI.Controls"
xmlns:controls1="using:Microsoft.UI.Xaml.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:data="using:Wino.Calendar.ViewModels.Data"
xmlns:domain="using:Wino.Core.Domain"
xmlns:entities="using:Wino.Core.Domain.Entities.Shared"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitExt="using:CommunityToolkit.WinUI"
x:Name="Root"
mc:Ignorable="d">
<Grid>
<StackPanel>
<!-- First day of week -->
<controls:SettingsCard Description="Adjust the day that week starts." Header="First day of week">
<controls:SettingsCard.HeaderIcon>
<PathIcon Data="F1 M 16.328125 2.5 C 16.816406 2.5 17.283527 2.599285 17.729492 2.797852 C 18.175455 2.99642 18.56608 3.263348 18.901367 3.598633 C 19.236652 3.93392 19.50358 4.324545 19.702148 4.770508 C 19.900715 5.216473 20 5.683595 20 6.171875 L 20 13.828125 C 20 14.316406 19.900715 14.783529 19.702148 15.229492 C 19.50358 15.675456 19.236652 16.066082 18.901367 16.401367 C 18.56608 16.736654 18.175455 17.00358 17.729492 17.202148 C 17.283527 17.400717 16.816406 17.5 16.328125 17.5 L 3.671875 17.5 C 3.183594 17.5 2.716471 17.400717 2.270508 17.202148 C 1.824544 17.00358 1.433919 16.736654 1.098633 16.401367 C 0.763346 16.066082 0.496419 15.675456 0.297852 15.229492 C 0.099284 14.783529 0 14.316406 0 13.828125 L 0 6.171875 C 0 5.683595 0.099284 5.216473 0.297852 4.770508 C 0.496419 4.324545 0.763346 3.93392 1.098633 3.598633 C 1.433919 3.263348 1.824544 2.99642 2.270508 2.797852 C 2.716471 2.599285 3.183594 2.5 3.671875 2.5 Z M 18.75 6.201172 C 18.75 5.875651 18.683268 5.564779 18.549805 5.268555 C 18.41634 4.972332 18.237305 4.711915 18.012695 4.487305 C 17.788086 4.262696 17.527668 4.08366 17.231445 3.950195 C 16.935221 3.816732 16.624348 3.75 16.298828 3.75 L 3.701172 3.75 C 3.375651 3.75 3.064779 3.816732 2.768555 3.950195 C 2.472331 4.08366 2.211914 4.262696 1.987305 4.487305 C 1.762695 4.711915 1.583659 4.972332 1.450195 5.268555 C 1.316732 5.564779 1.25 5.875651 1.25 6.201172 L 1.25 13.798828 C 1.25 14.130859 1.318359 14.446615 1.455078 14.746094 C 1.591797 15.045573 1.774089 15.30599 2.001953 15.527344 C 2.229818 15.748698 2.495117 15.924479 2.797852 16.054688 C 3.100586 16.184896 3.417969 16.25 3.75 16.25 L 3.75 8.125 C 3.75 7.871094 3.798828 7.630209 3.896484 7.402344 C 3.99414 7.174479 4.129231 6.974284 4.301758 6.801758 C 4.474284 6.629232 4.674479 6.494141 4.902344 6.396484 C 5.130208 6.298828 5.371094 6.25 5.625 6.25 L 14.375 6.25 C 14.628906 6.25 14.869791 6.298828 15.097656 6.396484 C 15.32552 6.494141 15.525715 6.629232 15.698242 6.801758 C 15.870768 6.974284 16.005859 7.174479 16.103516 7.402344 C 16.201172 7.630209 16.25 7.871094 16.25 8.125 L 16.25 16.25 L 16.298828 16.25 C 16.624348 16.25 16.935221 16.18327 17.231445 16.049805 C 17.527668 15.916342 17.788086 15.737305 18.012695 15.512695 C 18.237305 15.288086 18.41634 15.02767 18.549805 14.731445 C 18.683268 14.435222 18.75 14.12435 18.75 13.798828 Z M 15 16.25 L 15 8.125 C 14.999999 7.95573 14.93815 7.809246 14.814453 7.685547 C 14.690755 7.56185 14.544271 7.5 14.375 7.5 L 5.625 7.5 C 5.455729 7.5 5.309245 7.56185 5.185547 7.685547 C 5.061849 7.809246 5 7.95573 5 8.125 L 5 16.25 Z M 9.0625 9.6875 C 9.0625 9.947917 8.971354 10.169271 8.789062 10.351562 C 8.606771 10.533854 8.385416 10.625 8.125 10.625 C 7.864583 10.625 7.643229 10.533854 7.460938 10.351562 C 7.278646 10.169271 7.1875 9.947917 7.1875 9.6875 C 7.1875 9.427084 7.278646 9.205729 7.460938 9.023438 C 7.643229 8.841146 7.864583 8.75 8.125 8.75 C 8.385416 8.75 8.606771 8.841146 8.789062 9.023438 C 8.971354 9.205729 9.0625 9.427084 9.0625 9.6875 Z M 12.8125 9.6875 C 12.8125 9.947917 12.721354 10.169271 12.539062 10.351562 C 12.356771 10.533854 12.135416 10.625 11.875 10.625 C 11.614583 10.625 11.393229 10.533854 11.210938 10.351562 C 11.028646 10.169271 10.9375 9.947917 10.9375 9.6875 C 10.9375 9.427084 11.028646 9.205729 11.210938 9.023438 C 11.393229 8.841146 11.614583 8.75 11.875 8.75 C 12.135416 8.75 12.356771 8.841146 12.539062 9.023438 C 12.721354 9.205729 12.8125 9.427084 12.8125 9.6875 Z M 9.0625 13.4375 C 9.0625 13.697917 8.971354 13.919271 8.789062 14.101562 C 8.606771 14.283854 8.385416 14.375 8.125 14.375 C 7.864583 14.375 7.643229 14.283854 7.460938 14.101562 C 7.278646 13.919271 7.1875 13.697917 7.1875 13.4375 C 7.1875 13.177084 7.278646 12.955729 7.460938 12.773438 C 7.643229 12.591146 7.864583 12.5 8.125 12.5 C 8.385416 12.5 8.606771 12.591146 8.789062 12.773438 C 8.971354 12.955729 9.0625 13.177084 9.0625 13.4375 Z M 12.8125 13.4375 C 12.8125 13.697917 12.721354 13.919271 12.539062 14.101562 C 12.356771 14.283854 12.135416 14.375 11.875 14.375 C 11.614583 14.375 11.393229 14.283854 11.210938 14.101562 C 11.028646 13.919271 10.9375 13.697917 10.9375 13.4375 C 10.9375 13.177084 11.028646 12.955729 11.210938 12.773438 C 11.393229 12.591146 11.614583 12.5 11.875 12.5 C 12.135416 12.5 12.356771 12.591146 12.539062 12.773438 C 12.721354 12.955729 12.8125 13.177084 12.8125 13.4375 Z " />
</controls:SettingsCard.HeaderIcon>
<controls:SettingsCard.Content>
<ComboBox ItemsSource="{x:Bind ViewModel.DayNames, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedFirstDayOfWeekIndex, Mode=TwoWay}" />
</controls:SettingsCard.Content>
</controls:SettingsCard>
<!-- Working days/hours -->
<controls:SettingsExpander Description="Set the day range for your working hours." Header="Working days">
<controls:SettingsExpander.HeaderIcon>
<PathIcon Data="F1 M 18.75 8.056641 L 18.75 14.443359 C 18.75 14.853516 18.666992 15.244141 18.500977 15.615234 C 18.334961 15.986328 18.113605 16.310221 17.836914 16.586914 C 17.560221 16.863607 17.236328 17.084961 16.865234 17.250977 C 16.494141 17.416992 16.103516 17.5 15.693359 17.5 L 4.306641 17.5 C 3.896484 17.5 3.505859 17.416992 3.134766 17.250977 C 2.763672 17.084961 2.439779 16.863607 2.163086 16.586914 C 1.886393 16.310221 1.665039 15.986328 1.499023 15.615234 C 1.333008 15.244141 1.25 14.853516 1.25 14.443359 L 1.25 8.056641 C 1.25 7.633464 1.334635 7.236328 1.503906 6.865234 C 1.673177 6.494141 1.901042 6.170248 2.1875 5.893555 C 2.473958 5.616862 2.80599 5.398764 3.183594 5.239258 C 3.561198 5.079754 3.958333 5.000001 4.375 5 L 6.25 5 L 6.25 2.5 C 6.25 2.324219 6.282552 2.161459 6.347656 2.011719 C 6.41276 1.86198 6.502278 1.730145 6.616211 1.616211 C 6.730143 1.502279 6.861979 1.412762 7.011719 1.347656 C 7.161458 1.282553 7.324218 1.25 7.5 1.25 L 12.5 1.25 C 12.675781 1.25 12.840169 1.282553 12.993164 1.347656 C 13.146158 1.412762 13.277994 1.500652 13.388672 1.611328 C 13.499349 1.722006 13.587239 1.853842 13.652344 2.006836 C 13.717447 2.159832 13.75 2.324219 13.75 2.5 L 13.75 5 L 15.693359 5 C 16.103516 5.000001 16.494141 5.083009 16.865234 5.249023 C 17.236328 5.41504 17.560221 5.636395 17.836914 5.913086 C 18.113605 6.189779 18.334961 6.513672 18.500977 6.884766 C 18.666992 7.255859 18.75 7.646484 18.75 8.056641 Z M 12.5 2.5 L 7.5 2.5 L 7.5 5 L 12.5 5 Z M 17.5 8.125 C 17.5 7.871094 17.451172 7.630209 17.353516 7.402344 C 17.255859 7.174479 17.120768 6.974284 16.948242 6.801758 C 16.775715 6.629232 16.57552 6.494141 16.347656 6.396484 C 16.119791 6.298828 15.878906 6.25 15.625 6.25 L 4.375 6.25 C 4.121094 6.25 3.880208 6.298828 3.652344 6.396484 C 3.424479 6.494141 3.224284 6.629232 3.051758 6.801758 C 2.879232 6.974284 2.744141 7.174479 2.646484 7.402344 C 2.548828 7.630209 2.5 7.871094 2.5 8.125 L 2.5 14.375 C 2.5 14.628906 2.548828 14.869792 2.646484 15.097656 C 2.744141 15.325521 2.879232 15.525717 3.051758 15.698242 C 3.224284 15.870769 3.424479 16.005859 3.652344 16.103516 C 3.880208 16.201172 4.121094 16.25 4.375 16.25 L 15.625 16.25 C 15.878906 16.25 16.119791 16.201172 16.347656 16.103516 C 16.57552 16.005859 16.775715 15.870769 16.948242 15.698242 C 17.120768 15.525717 17.255859 15.325521 17.353516 15.097656 C 17.451172 14.869792 17.5 14.628906 17.5 14.375 Z " />
</controls:SettingsExpander.HeaderIcon>
<controls:SettingsExpander.Items>
<controls:SettingsCard
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
ContentAlignment="Vertical">
<controls:SettingsCard.Content>
<StackPanel Spacing="16">
<StackPanel Spacing="6">
<TextBlock FontWeight="SemiBold" Text="Highlight working hours" />
<ToggleSwitch
IsOn="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=TwoWay}"
OffContent="Off"
OnContent="On" />
</StackPanel>
<Grid RowSpacing="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
VerticalAlignment="Center"
FontWeight="Bold"
Text="From" />
<ComboBox
Grid.Column="1"
IsEnabled="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=OneWay}"
ItemsSource="{x:Bind ViewModel.DayNames, Mode=OneWay}"
SelectedIndex="{x:Bind ViewModel.WorkingDayStartIndex, Mode=TwoWay}" />
<TimePicker
x:Name="WorkHourStartPicker"
Grid.Column="2"
Margin="12,0"
IsEnabled="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=OneWay}"
Time="{x:Bind ViewModel.WorkingHourStart, Mode=TwoWay}" />
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
VerticalAlignment="Center"
FontWeight="Bold"
Text="To" />
<ComboBox
Grid.Column="1"
IsEnabled="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=OneWay}"
ItemsSource="{x:Bind ViewModel.DayNames, Mode=OneWay}"
SelectedIndex="{x:Bind ViewModel.WorkingDayEndIndex, Mode=TwoWay}" />
<TimePicker
x:Name="WorkEndStartPicker"
Grid.Column="2"
Margin="12,0"
IsEnabled="{x:Bind ViewModel.IsWorkingHoursEnabled, Mode=OneWay}"
Time="{x:Bind ViewModel.WorkingHourEnd, Mode=TwoWay}" />
</Grid>
</Grid>
</StackPanel>
</controls:SettingsCard.Content>
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
<!-- Cell hour height -->
<controls:SettingsExpander
Description="Adjust calendar timeline rendering options."
Header="Calendar rendering"
IsExpanded="True">
<controls:SettingsExpander.HeaderIcon>
<PathIcon Data="F1 M 15.078125 1.25 C 15.566406 1.25 16.033527 1.349285 16.479492 1.547852 C 16.925455 1.74642 17.31608 2.013348 17.651367 2.348633 C 17.986652 2.68392 18.25358 3.074545 18.452148 3.520508 C 18.650715 3.966473 18.75 4.433594 18.75 4.921875 L 18.75 15.078125 C 18.75 15.566406 18.650715 16.033529 18.452148 16.479492 C 18.25358 16.925455 17.986652 17.31608 17.651367 17.651367 C 17.31608 17.986654 16.925455 18.25358 16.479492 18.452148 C 16.033527 18.650717 15.566406 18.75 15.078125 18.75 L 4.921875 18.75 C 4.433594 18.75 3.966471 18.650717 3.520508 18.452148 C 3.074544 18.25358 2.683919 17.986654 2.348633 17.651367 C 2.013346 17.31608 1.746419 16.925455 1.547852 16.479492 C 1.349284 16.033529 1.25 15.566406 1.25 15.078125 L 1.25 4.921875 C 1.25 4.433594 1.349284 3.966473 1.547852 3.520508 C 1.746419 3.074545 2.013346 2.68392 2.348633 2.348633 C 2.683919 2.013348 3.074544 1.74642 3.520508 1.547852 C 3.966471 1.349285 4.433594 1.25 4.921875 1.25 Z M 4.951172 2.5 C 4.625651 2.5 4.314778 2.566732 4.018555 2.700195 C 3.722331 2.83366 3.461914 3.012695 3.237305 3.237305 C 3.012695 3.461914 2.833659 3.722332 2.700195 4.018555 C 2.566732 4.314779 2.5 4.625651 2.5 4.951172 L 2.5 5 L 17.5 5 L 17.5 4.951172 C 17.5 4.625651 17.433268 4.314779 17.299805 4.018555 C 17.16634 3.722332 16.987305 3.461914 16.762695 3.237305 C 16.538086 3.012695 16.277668 2.83366 15.981445 2.700195 C 15.685221 2.566732 15.374349 2.5 15.048828 2.5 Z M 15.048828 17.5 C 15.374349 17.5 15.685221 17.433268 15.981445 17.299805 C 16.277668 17.166342 16.538086 16.987305 16.762695 16.762695 C 16.987305 16.538086 17.16634 16.27767 17.299805 15.981445 C 17.433268 15.685222 17.5 15.37435 17.5 15.048828 L 17.5 6.25 L 2.5 6.25 L 2.5 15.048828 C 2.5 15.37435 2.566732 15.685222 2.700195 15.981445 C 2.833659 16.27767 3.012695 16.538086 3.237305 16.762695 C 3.461914 16.987305 3.722331 17.166342 4.018555 17.299805 C 4.314778 17.433268 4.625651 17.5 4.951172 17.5 Z M 16.25 9.375 C 16.25 9.544271 16.18815 9.690756 16.064453 9.814453 C 15.940754 9.938151 15.79427 10 15.625 10 L 13.642578 10 C 13.577474 10.188803 13.486328 10.359701 13.369141 10.512695 C 13.251953 10.66569 13.115234 10.797526 12.958984 10.908203 C 12.802734 11.018881 12.633463 11.103516 12.451172 11.162109 C 12.26888 11.220703 12.076822 11.25 11.875 11.25 C 11.673177 11.25 11.481119 11.220703 11.298828 11.162109 C 11.116536 11.103516 10.947266 11.018881 10.791016 10.908203 C 10.634766 10.797526 10.498047 10.66569 10.380859 10.512695 C 10.263672 10.359701 10.172525 10.188803 10.107422 10 L 4.375 10 C 4.205729 10 4.059245 9.938151 3.935547 9.814453 C 3.811849 9.690756 3.75 9.544271 3.75 9.375 C 3.75 9.205729 3.811849 9.059245 3.935547 8.935547 C 4.059245 8.81185 4.205729 8.75 4.375 8.75 L 10.107422 8.75 C 10.172525 8.561198 10.263672 8.3903 10.380859 8.237305 C 10.498047 8.084311 10.634766 7.952475 10.791016 7.841797 C 10.947266 7.73112 11.116536 7.646484 11.298828 7.587891 C 11.481119 7.529297 11.673177 7.5 11.875 7.5 C 12.076822 7.5 12.26888 7.529297 12.451172 7.587891 C 12.633463 7.646484 12.802734 7.73112 12.958984 7.841797 C 13.115234 7.952475 13.251953 8.084311 13.369141 8.237305 C 13.486328 8.3903 13.577474 8.561198 13.642578 8.75 L 15.625 8.75 C 15.79427 8.75 15.940754 8.81185 16.064453 8.935547 C 16.18815 9.059245 16.25 9.205729 16.25 9.375 Z M 16.25 14.375 C 16.25 14.544271 16.18815 14.690756 16.064453 14.814453 C 15.940754 14.938151 15.79427 15 15.625 15 L 9.892578 15 C 9.827474 15.188803 9.736328 15.359701 9.619141 15.512695 C 9.501953 15.66569 9.365234 15.797526 9.208984 15.908203 C 9.052734 16.018881 8.883463 16.103516 8.701172 16.162109 C 8.51888 16.220703 8.326822 16.25 8.125 16.25 C 7.923177 16.25 7.731119 16.220703 7.548828 16.162109 C 7.366536 16.103516 7.197266 16.018881 7.041016 15.908203 C 6.884766 15.797526 6.748047 15.66569 6.630859 15.512695 C 6.513672 15.359701 6.422526 15.188803 6.357422 15 L 4.375 15 C 4.205729 15 4.059245 14.938151 3.935547 14.814453 C 3.811849 14.690756 3.75 14.544271 3.75 14.375 C 3.75 14.205729 3.811849 14.059245 3.935547 13.935547 C 4.059245 13.81185 4.205729 13.75 4.375 13.75 L 6.357422 13.75 C 6.422526 13.561198 6.513672 13.3903 6.630859 13.237305 C 6.748047 13.084311 6.884766 12.952475 7.041016 12.841797 C 7.197266 12.73112 7.366536 12.646484 7.548828 12.587891 C 7.731119 12.529297 7.923177 12.5 8.125 12.5 C 8.326822 12.5 8.51888 12.529297 8.701172 12.587891 C 8.883463 12.646484 9.052734 12.73112 9.208984 12.841797 C 9.365234 12.952475 9.501953 13.084311 9.619141 13.237305 C 9.736328 13.3903 9.827474 13.561198 9.892578 13.75 L 15.625 13.75 C 15.79427 13.75 15.940754 13.81185 16.064453 13.935547 C 16.18815 14.059245 16.25 14.205729 16.25 14.375 Z " />
</controls:SettingsExpander.HeaderIcon>
<controls:SettingsExpander.Items>
<controls:SettingsCard
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
ContentAlignment="Vertical"
Description="How many pixels should 1 hour representation occupy in daily/weekly calendars."
Header="Hour height">
<controls:SettingsCard.HeaderIcon>
<PathIcon Data="F1 M 4.921875 18.75 C 4.433594 18.75 3.966471 18.650717 3.520508 18.452148 C 3.074544 18.25358 2.683919 17.986654 2.348633 17.651367 C 2.013346 17.31608 1.746419 16.925455 1.547852 16.479492 C 1.349284 16.033529 1.25 15.566406 1.25 15.078125 L 1.25 4.921875 C 1.25 4.433594 1.349284 3.966473 1.547852 3.520508 C 1.746419 3.074545 2.013346 2.68392 2.348633 2.348633 C 2.683919 2.013348 3.074544 1.74642 3.520508 1.547852 C 3.966471 1.349285 4.433594 1.25 4.921875 1.25 L 15.078125 1.25 C 15.566406 1.25 16.033527 1.349285 16.479492 1.547852 C 16.925455 1.74642 17.31608 2.013348 17.651367 2.348633 C 17.986652 2.68392 18.25358 3.074545 18.452148 3.520508 C 18.650715 3.966473 18.75 4.433594 18.75 4.921875 L 18.75 15.078125 C 18.75 15.566406 18.650715 16.033529 18.452148 16.479492 C 18.25358 16.925455 17.986652 17.31608 17.651367 17.651367 C 17.31608 17.986654 16.925455 18.25358 16.479492 18.452148 C 16.033527 18.650717 15.566406 18.75 15.078125 18.75 Z M 2.5 10 L 17.5 10 L 17.5 4.951172 C 17.5 4.625651 17.433268 4.314779 17.299805 4.018555 C 17.16634 3.722332 16.987305 3.461914 16.762695 3.237305 C 16.538086 3.012695 16.277668 2.83366 15.981445 2.700195 C 15.685221 2.566732 15.374349 2.5 15.048828 2.5 L 4.951172 2.5 C 4.625651 2.5 4.314778 2.566732 4.018555 2.700195 C 3.722331 2.83366 3.461914 3.012695 3.237305 3.237305 C 3.012695 3.461914 2.833659 3.722332 2.700195 4.018555 C 2.566732 4.314779 2.5 4.625651 2.5 4.951172 Z " />
</controls:SettingsCard.HeaderIcon>
<Grid
Padding="0,20"
ColumnSpacing="12"
RowSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Margin="0,5,0,0" VerticalAlignment="Top">
<Run Text="{x:Bind ViewModel.CellHourHeight, Mode=OneWay}" />
<Run Text="px" />
</TextBlock>
<Slider
x:Name="HourCellSlider"
Grid.Column="1"
Maximum="200"
Minimum="60"
Value="{x:Bind ViewModel.CellHourHeight, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
<!-- Hour cell demo -->
<Grid
Grid.Column="2"
HorizontalAlignment="Center"
ColumnSpacing="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right" Text="00:00" />
<TextBlock
Grid.Row="2"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Text="01:00" />
<Grid
Grid.Column="1"
Width="100"
Height="{x:Bind HourCellSlider.Value, Mode=OneWay}"
VerticalAlignment="Center"
BorderBrush="Black"
BorderThickness="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="1" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle
Grid.Row="1"
HorizontalAlignment="Stretch"
Stroke="Black"
StrokeThickness="0.5" />
</Grid>
</Grid>
</Grid>
</controls:SettingsCard>
<controls:SettingsCard Description="Set whether you want to use AM/PM or 24 hour clock identifier." Header="Clock identifier for headers">
<controls:SettingsCard.HeaderIcon>
<PathIcon Data="F1 M 4.921875 18.75 C 4.433594 18.75 3.966471 18.650717 3.520508 18.452148 C 3.074544 18.25358 2.683919 17.986654 2.348633 17.651367 C 2.013346 17.31608 1.746419 16.925455 1.547852 16.479492 C 1.349284 16.033529 1.25 15.566406 1.25 15.078125 L 1.25 4.921875 C 1.25 4.433594 1.349284 3.966473 1.547852 3.520508 C 1.746419 3.074545 2.013346 2.68392 2.348633 2.348633 C 2.683919 2.013348 3.074544 1.74642 3.520508 1.547852 C 3.966471 1.349285 4.433594 1.25 4.921875 1.25 L 15.078125 1.25 C 15.566406 1.25 16.033527 1.349285 16.479492 1.547852 C 16.925455 1.74642 17.31608 2.013348 17.651367 2.348633 C 17.986652 2.68392 18.25358 3.074545 18.452148 3.520508 C 18.650715 3.966473 18.75 4.433594 18.75 4.921875 L 18.75 15.078125 C 18.75 15.566406 18.650715 16.033529 18.452148 16.479492 C 18.25358 16.925455 17.986652 17.31608 17.651367 17.651367 C 17.31608 17.986654 16.925455 18.25358 16.479492 18.452148 C 16.033527 18.650717 15.566406 18.75 15.078125 18.75 Z M 2.5 10 L 17.5 10 L 17.5 4.951172 C 17.5 4.625651 17.433268 4.314779 17.299805 4.018555 C 17.16634 3.722332 16.987305 3.461914 16.762695 3.237305 C 16.538086 3.012695 16.277668 2.83366 15.981445 2.700195 C 15.685221 2.566732 15.374349 2.5 15.048828 2.5 L 4.951172 2.5 C 4.625651 2.5 4.314778 2.566732 4.018555 2.700195 C 3.722331 2.83366 3.461914 3.012695 3.237305 3.237305 C 3.012695 3.461914 2.833659 3.722332 2.700195 4.018555 C 2.566732 4.314779 2.5 4.625651 2.5 4.951172 Z " />
</controls:SettingsCard.HeaderIcon>
<StackPanel Spacing="8">
<ToggleSwitch
HorizontalAlignment="Right"
IsOn="{x:Bind ViewModel.Is24HourHeaders, Mode=TwoWay}"
OffContent="12h"
OnContent="24h" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.TimedHourLabelPreview, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
</StackPanel>
</controls:SettingsCard>
<controls:SettingsCard Description="{x:Bind domain:Translator.CalendarSettings_TimedDayHeaderFormat_Description}" Header="{x:Bind domain:Translator.CalendarSettings_TimedDayHeaderFormat_Header}">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE823;" />
</controls:SettingsCard.HeaderIcon>
<StackPanel Spacing="8">
<TextBox PlaceholderText="ddd dd" Text="{x:Bind ViewModel.TimedDayHeaderDateFormat, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<ComboBox ItemsSource="{x:Bind ViewModel.TimedDayHeaderFormatPresets, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedTimedDayHeaderFormatPresetIndex, Mode=TwoWay}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.TimedDayHeaderFormatPreview, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
</StackPanel>
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
<!-- Calendar Accounts -->
<!--<controls:SettingsExpander
Description="Manage calendar settings for each account"
Header="Calendar Accounts"
IsExpanded="True">
<controls:SettingsExpander.HeaderIcon>
<FontIcon Glyph="&#xE77B;" />
</controls:SettingsExpander.HeaderIcon>
<controls:SettingsExpander.Items>
<controls:SettingsCard
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
ContentAlignment="Vertical">
<ItemsControl ItemsSource="{x:Bind ViewModel.Accounts, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="entities:MailAccount">
<Button
Padding="12,8"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Command="{Binding ElementName=Root, Path=ViewModel.NavigateToAccountSettingsCommand}"
CommandParameter="{x:Bind}"
Style="{StaticResource SubtleButtonStyle}">
<StackPanel Orientation="Horizontal" Spacing="12">
<FontIcon FontSize="20" Glyph="&#xE8D8;" />
<StackPanel VerticalAlignment="Center">
<TextBlock Text="{x:Bind Name}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Address}" />
</StackPanel>
<FontIcon
Margin="0,0,8,0"
HorizontalAlignment="Right"
FontSize="12"
Glyph="&#xE76C;" />
</StackPanel>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>-->
<!-- Default reminder -->
<controls:SettingsCard Description="Set a default reminder for all new calendar events." Header="Default reminder">
<controls:SettingsCard.HeaderIcon>
<PathIcon Data="F1 M 10 1.25 C 10.456706 1.25 10.889486 1.337565 11.298339 1.512695 C 11.707192 1.687826 12.072591 1.927409 12.394531 2.231445 C 12.716471 2.535482 12.97656 2.892253 13.173828 3.301758 C 13.371096 3.711263 13.481771 4.146484 13.505859 4.607422 L 13.505859 5 C 13.969401 5.028646 14.386068 5.16276 14.755859 5.402344 C 15.125651 5.641927 15.414713 5.947917 15.623047 6.320312 C 15.83138 6.692709 15.9349 7.096355 15.933594 7.53125 L 15.933594 8.75 L 16.25 8.75 C 16.822917 8.75 17.317057 8.95638 17.732422 9.369141 C 18.147787 9.781901 18.357422 10.273437 18.359375 10.84375 L 18.359375 16.40625 C 18.359375 16.979167 18.153971 17.473308 17.743164 17.888672 C 17.332357 18.304037 16.839844 18.511719 16.265625 18.511719 L 3.734375 18.511719 C 3.164062 18.511719 2.671549 18.304037 2.256836 17.888672 C 1.842122 17.473308 1.634114 16.979167 1.630859 16.40625 L 1.630859 10.84375 C 1.630859 10.273437 1.837565 9.781901 2.250977 9.369141 C 2.664388 8.95638 3.156901 8.75 3.728516 8.75 L 4.0625 8.75 L 4.0625 7.53125 C 4.0625 7.09375 4.166341 6.689453 4.374023 6.314453 C 4.581706 5.939453 4.86914 5.632486 5.236328 5.393555 C 5.603516 5.154623 6.019532 5.021485 6.484375 4.994141 L 6.484375 4.607422 C 6.506511 4.148438 6.617838 3.714518 6.818359 3.305664 C 7.01888 2.896811 7.282877 2.539063 7.610352 2.232422 C 7.937826 1.92578 8.308268 1.685222 8.721679 1.510742 C 9.135091 1.336264 9.56575 1.249024 10.013672 1.249024 Z M 10.013672 2.5 C 9.441406 2.5 8.947916 2.706381 8.533203 3.119141 C 8.118489 3.531901 7.911459 4.023437 7.912109 4.59375 L 7.912109 6.25 L 12.089844 6.25 L 12.089844 4.59375 C 12.089844 4.023438 11.882161 3.531902 11.466797 3.119141 C 11.051433 2.706382 10.557292 2.5 9.984375 2.5 Z M 5.3125 7.53125 L 5.3125 8.75 L 14.6875 8.75 L 14.6875 7.53125 C 14.6875 7.303385 14.605144 7.107747 14.440429 6.944336 C 14.275714 6.780925 14.080729 6.69987 13.855469 6.703125 L 6.142578 6.703125 C 5.914713 6.703125 5.71875 6.785482 5.552734 6.950195 C 5.386719 7.114909 5.30339 7.310547 5.300781 7.537109 Z M 16.25 10 L 3.75 10 C 3.540365 10 3.361328 10.071615 3.212891 10.214844 C 3.064453 10.358073 2.989258 10.534505 2.986328 10.744141 L 2.986328 16.40625 C 2.986328 16.618489 3.058595 16.797526 3.203125 16.943359 C 3.347656 17.089193 3.526693 17.161458 3.740234 17.15625 L 16.25 17.15625 C 16.458333 17.15625 16.636067 17.082683 16.783203 16.935547 C 16.930339 16.788411 17.003906 16.609375 17.003906 16.398437 L 17.003906 10.742187 C 17.003906 10.536459 16.932942 10.359049 16.791016 10.209961 C 16.64909 10.060873 16.469401 9.986328 16.257812 9.986328 Z M 10 11.5625 C 10.227865 11.5625 10.423502 11.644856 10.586914 11.809571 C 10.750325 11.974285 10.83138 12.16862 10.830078 12.393555 L 10.830078 13.427734 L 11.855469 13.427734 C 12.080404 13.427734 12.273437 13.509115 12.434571 13.671875 C 12.595704 13.834636 12.675781 14.026693 12.675781 14.248047 C 12.675781 14.46224 12.596354 14.653321 12.4375 14.813477 C 12.278646 14.973633 12.089192 15.053711 11.869141 15.053711 L 10.830078 15.053711 L 10.830078 16.074219 C 10.830078 16.296224 10.748372 16.486981 10.584961 16.646484 C 10.42155 16.805989 10.229818 16.885742 10.005859 16.885742 C 9.781901 16.885742 9.590495 16.806315 9.431641 16.647461 C 9.272786 16.488607 9.193359 16.296875 9.193359 16.072266 L 9.193359 15.053711 L 8.15625 15.053711 C 7.931314 15.053711 7.738934 14.972331 7.579102 14.80957 C 7.419269 14.646809 7.339192 14.454753 7.338867 14.233399 C 7.338867 14.008464 7.419921 13.815755 7.582031 13.655274 C 7.744141 13.494793 7.935872 13.414551 8.157227 13.414551 L 9.193359 13.414551 L 9.193359 12.394531 C 9.193359 12.166667 9.275715 11.971029 9.440429 11.807618 C 9.605144 11.644206 9.799479 11.562825 10.023437 11.5625 Z" />
</controls:SettingsCard.HeaderIcon>
<controls:SettingsCard.Content>
<ComboBox ItemsSource="{x:Bind ViewModel.ReminderOptions, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedDefaultReminderIndex, Mode=TwoWay}" />
</controls:SettingsCard.Content>
</controls:SettingsCard>
<controls:SettingsCard Description="{x:Bind domain:Translator.CalendarSettings_DefaultSnoozeDuration_Description}" Header="{x:Bind domain:Translator.CalendarSettings_DefaultSnoozeDuration_Header}">
<controls:SettingsCard.HeaderIcon>
<PathIcon Data="F1 M 10 1.25 C 10.456706 1.25 10.889486 1.337565 11.298339 1.512695 C 11.707192 1.687826 12.072591 1.927409 12.394531 2.231445 C 12.716471 2.535482 12.97656 2.892253 13.173828 3.301758 C 13.371096 3.711263 13.481771 4.146484 13.505859 4.607422 L 13.505859 5 C 13.969401 5.028646 14.386068 5.16276 14.755859 5.402344 C 15.125651 5.641927 15.414713 5.947917 15.623047 6.320312 C 15.83138 6.692709 15.9349 7.096355 15.933594 7.53125 L 15.933594 8.75 L 16.25 8.75 C 16.822917 8.75 17.317057 8.95638 17.732422 9.369141 C 18.147787 9.781901 18.357422 10.273437 18.359375 10.84375 L 18.359375 16.40625 C 18.359375 16.979167 18.153971 17.473308 17.743164 17.888672 C 17.332357 18.304037 16.839844 18.511719 16.265625 18.511719 L 3.734375 18.511719 C 3.164062 18.511719 2.671549 18.304037 2.256836 17.888672 C 1.842122 17.473308 1.634114 16.979167 1.630859 16.40625 L 1.630859 10.84375 C 1.630859 10.273437 1.837565 9.781901 2.250977 9.369141 C 2.664388 8.95638 3.156901 8.75 3.728516 8.75 L 4.0625 8.75 L 4.0625 7.53125 C 4.0625 7.09375 4.166341 6.689453 4.374023 6.314453 C 4.581706 5.939453 4.86914 5.632486 5.236328 5.393555 C 5.603516 5.154623 6.019532 5.021485 6.484375 4.994141 L 6.484375 4.607422 C 6.506511 4.148438 6.617838 3.714518 6.818359 3.305664 C 7.01888 2.896811 7.282877 2.539063 7.610352 2.232422 C 7.937826 1.92578 8.308268 1.685222 8.721679 1.510742 C 9.135091 1.336264 9.56575 1.249024 10.013672 1.249024 Z M 10.013672 2.5 C 9.441406 2.5 8.947916 2.706381 8.533203 3.119141 C 8.118489 3.531901 7.911459 4.023437 7.912109 4.59375 L 7.912109 6.25 L 12.089844 6.25 L 12.089844 4.59375 C 12.089844 4.023438 11.882161 3.531902 11.466797 3.119141 C 11.051433 2.706382 10.557292 2.5 9.984375 2.5 Z M 5.3125 7.53125 L 5.3125 8.75 L 14.6875 8.75 L 14.6875 7.53125 C 14.6875 7.303385 14.605144 7.107747 14.440429 6.944336 C 14.275714 6.780925 14.080729 6.69987 13.855469 6.703125 L 6.142578 6.703125 C 5.914713 6.703125 5.71875 6.785482 5.552734 6.950195 C 5.386719 7.114909 5.30339 7.310547 5.300781 7.537109 Z M 16.25 10 L 3.75 10 C 3.540365 10 3.361328 10.071615 3.212891 10.214844 C 3.064453 10.358073 2.989258 10.534505 2.986328 10.744141 L 2.986328 16.40625 C 2.986328 16.618489 3.058595 16.797526 3.203125 16.943359 C 3.347656 17.089193 3.526693 17.161458 3.740234 17.15625 L 16.25 17.15625 C 16.458333 17.15625 16.636067 17.082683 16.783203 16.935547 C 16.930339 16.788411 17.003906 16.609375 17.003906 16.398437 L 17.003906 10.742187 C 17.003906 10.536459 16.932942 10.359049 16.791016 10.209961 C 16.64909 10.060873 16.469401 9.986328 16.257812 9.986328 Z M 10 11.5625 C 10.227865 11.5625 10.423502 11.644856 10.586914 11.809571 C 10.750325 11.974285 10.83138 12.16862 10.830078 12.393555 L 10.830078 13.427734 L 11.855469 13.427734 C 12.080404 13.427734 12.273437 13.509115 12.434571 13.671875 C 12.595704 13.834636 12.675781 14.026693 12.675781 14.248047 C 12.675781 14.46224 12.596354 14.653321 12.4375 14.813477 C 12.278646 14.973633 12.089192 15.053711 11.869141 15.053711 L 10.830078 15.053711 L 10.830078 16.074219 C 10.830078 16.296224 10.748372 16.486981 10.584961 16.646484 C 10.42155 16.805989 10.229818 16.885742 10.005859 16.885742 C 9.781901 16.885742 9.590495 16.806315 9.431641 16.647461 C 9.272786 16.488607 9.193359 16.296875 9.193359 16.072266 L 9.193359 15.053711 L 8.15625 15.053711 C 7.931314 15.053711 7.738934 14.972331 7.579102 14.80957 C 7.419269 14.646809 7.339192 14.454753 7.338867 14.233399 C 7.338867 14.008464 7.419921 13.815755 7.582031 13.655274 C 7.744141 13.494793 7.935872 13.414551 8.157227 13.414551 L 9.193359 13.414551 L 9.193359 12.394531 C 9.193359 12.166667 9.275715 11.971029 9.440429 11.807618 C 9.605144 11.644206 9.799479 11.562825 10.023437 11.5625 Z" />
</controls:SettingsCard.HeaderIcon>
<controls:SettingsCard.Content>
<ComboBox ItemsSource="{x:Bind ViewModel.SnoozeOptions, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedDefaultSnoozeIndex, Mode=TwoWay}" />
</controls:SettingsCard.Content>
</controls:SettingsCard>
<controls:SettingsCard Description="{x:Bind domain:Translator.CalendarSettings_NewEventBehavior_Description}" Header="{x:Bind domain:Translator.CalendarSettings_NewEventBehavior_Header}">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE163;" />
</controls:SettingsCard.HeaderIcon>
<controls:SettingsCard.Content>
<StackPanel Spacing="12">
<ComboBox ItemsSource="{x:Bind ViewModel.NewEventBehaviorOptions, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.SelectedNewEventBehaviorOption, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="calendarViewModels:CalendarNewEventBehaviorOption">
<TextBlock Text="{x:Bind DisplayText}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox
ItemsSource="{x:Bind ViewModel.AvailableNewEventCalendars, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.SelectedNewEventCalendar, Mode=TwoWay}"
Visibility="{x:Bind ViewModel.ShouldShowSpecificNewEventCalendar, Mode=OneWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="data:AccountCalendarViewModel">
<StackPanel Orientation="Vertical" Spacing="2">
<TextBlock Text="{x:Bind Name}" />
<TextBlock
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind Account.Address}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</controls:SettingsCard.Content>
</controls:SettingsCard>
</StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ClockIdentifierStates">
<VisualState x:Name="TwelweHour" />
<VisualState x:Name="TwentyFourHour">
<VisualState.StateTriggers>
<StateTrigger IsActive="{x:Bind ViewModel.Is24HourHeaders, Mode=OneWay}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="WorkHourStartPicker.ClockIdentifier" Value="24HourClock" />
<Setter Target="WorkEndStartPicker.ClockIdentifier" Value="24HourClock" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</abstract:CalendarSettingsPageAbstract>
@@ -1,11 +0,0 @@
using Wino.Mail.WinUI.Views.Abstract;
namespace Wino.Mail.WinUI.Views.Calendar;
public sealed partial class CalendarSettingsPage : CalendarSettingsPageAbstract
{
public CalendarSettingsPage()
{
InitializeComponent();
}
}
@@ -8,10 +8,24 @@
xmlns:domain="using:Wino.Core.Domain"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:translations="using:Wino.Core.Domain.Models.Translations"
mc:Ignorable="d">
<ScrollViewer>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
<controls:SettingsCard Description="{x:Bind domain:Translator.SettingsLanguage_Description}" Header="{x:Bind domain:Translator.SettingsLanguage_Title}">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE775;" />
</controls:SettingsCard.HeaderIcon>
<ComboBox ItemsSource="{x:Bind ViewModel.AvailableLanguages, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.SelectedLanguage, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="translations:AppLanguageModel">
<TextBlock Text="{x:Bind DisplayName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</controls:SettingsCard>
<controls:SettingsCard Description="{x:Bind domain:Translator.SettingsAppPreferences_StartupBehavior_Description}" Header="{x:Bind domain:Translator.SettingsAppPreferences_StartupBehavior_Title}">
<ToggleButton
x:Name="StartupEnabledToggleButton"
File diff suppressed because one or more lines are too long
@@ -1,18 +0,0 @@
using Wino.Views.Abstract;
namespace Wino.Views.Settings;
public sealed partial class LanguageTimePage : LanguageTimePageAbstract
{
public LanguageTimePage()
{
this.InitializeComponent();
}
public override void OnLanguageChanged()
{
base.OnLanguageChanged();
Bindings.Update();
}
}
@@ -26,7 +26,10 @@
<controls:SettingsExpander.Items>
<controls:SettingsCard VerticalAlignment="Center" HorizontalContentAlignment="Center">
<controls:SettingsCard.Header>
<controls1:MailItemDisplayInformationControl x:Name="PreviewMailItemDisplayInformationControl" />
<controls1:MailItemDisplayInformationControl
x:Name="PreviewMailItemDisplayInformationControl"
DisplayMode="{x:Bind ViewModel.SelectedMailSpacingMode, Mode=OneWay}"
MailItemInformation="{x:Bind ViewModel.DemoPreviewMailItemInformation, Mode=OneWay}" />
</controls:SettingsCard.Header>
<controls:SettingsCard.Content>
<RadioButtons SelectedIndex="{x:Bind ViewModel.SelectedMailSpacingIndex, Mode=TwoWay}">
File diff suppressed because one or more lines are too long
-9
View File
@@ -123,7 +123,6 @@
<None Remove="Styles\WinoCalendarTypeSelectorControl.xaml" />
<None Remove="Views\Calendar\CalendarAppShell.xaml" />
<None Remove="Views\Calendar\CalendarPage.xaml" />
<None Remove="Views\Calendar\CalendarSettingsPage.xaml" />
<None Remove="Views\Calendar\EventDetailsPage.xaml" />
<None Remove="Views\Settings\ContactsPage.xaml" />
</ItemGroup>
@@ -320,9 +319,6 @@
<Page Update="Views\Settings\EmailTemplatesPage.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Settings\LanguageTimePage.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Settings\MessageListPage.xaml">
<SubType>Designer</SubType>
</Page>
@@ -357,11 +353,6 @@
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Views\Calendar\CalendarSettingsPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Styles\CalendarThemeResources.xaml">
<Generator>MSBuild:Compile</Generator>
+2 -2
View File
@@ -28,8 +28,8 @@ public sealed class WinoAccountApiClient : IWinoAccountApiClient, IDisposable
private readonly SemaphoreSlim _tokenRefreshLock = new(1, 1);
private readonly bool _ownsHttpClient;
// private const string ApiUrl = "https://localhost:7204/";
private const string ApiUrl = "https://api.winomail.app/";
private const string ApiUrl = "https://localhost:7204/";
// private const string ApiUrl = "https://api.winomail.app/";
public WinoAccountApiClient(IDatabaseService databaseService, HttpClient? httpClient = null)
{