< Summary

Information
Class: MyNet.UI.ViewModels.Preferences.TimeAndLanguagePreferencesViewModel
Assembly: MyNet.UI
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/Preferences/TimeAndLanguagePreferencesViewModel.cs
Tag: 323_28699572109
Line coverage
0%
Covered lines: 0
Uncovered lines: 79
Coverable lines: 79
Total lines: 227
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 40
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/Preferences/TimeAndLanguagePreferencesViewModel.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="TimeAndLanguagePreferencesViewModel.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Collections.Generic;
 9using System.Collections.ObjectModel;
 10using System.Globalization;
 11using System.Linq;
 12using System.Reactive.Disposables;
 13using MyNet.Globalization;
 14using MyNet.Globalization.Culture;
 15using MyNet.Globalization.DateTime;
 16using MyNet.Observable.Behaviors.Metadata.Features.Events;
 17using MyNet.UI.Resources;
 18using MyNet.UI.ViewModels.Workspace;
 19
 20namespace MyNet.UI.ViewModels.Preferences;
 21
 22/// <summary>
 23/// Preferences page for culture and time zone settings.
 24/// </summary>
 25public sealed class TimeAndLanguagePreferencesViewModel : WorkspaceViewModel
 26{
 27    private readonly IGlobalizationService _globalization;
 28    private bool _suppressApply;
 29
 30    /// <summary>
 31    /// Initializes a new instance of the <see cref="TimeAndLanguagePreferencesViewModel"/> class.
 32    /// </summary>
 33    public TimeAndLanguagePreferencesViewModel(
 34        IGlobalizationService globalization,
 35        IEnumerable<CultureInfo>? supportedCultures = null,
 36        IEnumerable<TimeZoneInfo>? supportedTimeZones = null)
 037        : base(cultureService: globalization)
 38    {
 039        ArgumentNullException.ThrowIfNull(globalization);
 40
 041        _globalization = globalization;
 42
 043        foreach (var culture in supportedCultures ?? [SupportedCultures.French, SupportedCultures.English])
 044            Cultures.Add(culture);
 45
 046        foreach (var timeZone in supportedTimeZones ?? TimeZoneInfo.GetSystemTimeZones())
 047            TimeZones.Add(timeZone);
 48
 049        _globalization.CultureChanged += OnGlobalizationCultureChanged;
 050        _globalization.TimeZoneChanged += OnGlobalizationTimeZoneChanged;
 51
 052        Disposables.Add(Disposable.Create(() =>
 053        {
 054            _globalization.CultureChanged -= OnGlobalizationCultureChanged;
 055            _globalization.TimeZoneChanged -= OnGlobalizationTimeZoneChanged;
 056        }));
 57
 058        RefreshFromService();
 059    }
 60
 61    /// <summary>
 62    /// Gets or sets the selected culture.
 63    /// </summary>
 64    public CultureInfo? SelectedCulture
 65    {
 66        get;
 67        set
 68        {
 069            if (!SetProperty(ref field, value))
 070                return;
 71
 072            ApplyCulture();
 073        }
 74    }
 75
 76    /// <summary>
 77    /// Gets or sets a value indicating whether the installed UI culture is used.
 78    /// </summary>
 79    public bool AutomaticCulture
 80    {
 81        get;
 82        set
 83        {
 084            if (!SetProperty(ref field, value))
 085                return;
 86
 087            ApplyCulture();
 088        }
 89    }
 90
 91    /// <summary>
 92    /// Gets or sets the selected time zone.
 93    /// </summary>
 94    public TimeZoneInfo? SelectedTimeZone
 95    {
 96        get;
 97        set
 98        {
 099            if (!SetProperty(ref field, value))
 0100                return;
 101
 0102            ApplyTimeZone();
 0103        }
 104    }
 105
 106    /// <summary>
 107    /// Gets or sets a value indicating whether the local system time zone is used.
 108    /// </summary>
 109    public bool AutomaticTimeZone
 110    {
 111        get;
 112        set
 113        {
 0114            if (!SetProperty(ref field, value))
 0115                return;
 116
 0117            ApplyTimeZone();
 0118        }
 119    }
 120
 121    /// <summary>
 122    /// Gets the cultures available for selection.
 123    /// </summary>
 124    public ObservableCollection<CultureInfo> Cultures { get; } = [];
 125
 126    /// <summary>
 127    /// Gets the time zones available for selection.
 128    /// </summary>
 129    public ObservableCollection<TimeZoneInfo> TimeZones { get; } = [];
 130
 131    /// <inheritdoc />
 0132    protected override string? CreateTitle(CultureInfo culture) => UiResources.TimeAndLanguage;
 133
 134    /// <inheritdoc />
 135    public override void OnEvent(CultureChangedEvent e)
 136    {
 0137        base.OnEvent(e);
 0138        RefreshCultureFromService();
 0139    }
 140
 141    private void OnGlobalizationCultureChanged(object? sender, CultureChangedEventArgs e)
 0142        => RefreshCultureFromService();
 143
 144    private void OnGlobalizationTimeZoneChanged(object? sender, TimeZoneChangedEventArgs e)
 0145        => RefreshTimeZoneFromService();
 146
 147    private void RefreshFromService()
 148    {
 0149        _suppressApply = true;
 150        try
 151        {
 0152            RefreshCultureFromService();
 0153            RefreshTimeZoneFromService();
 0154        }
 155        finally
 156        {
 0157            _suppressApply = false;
 0158        }
 0159    }
 160
 161    private void RefreshCultureFromService()
 162    {
 0163        _suppressApply = true;
 164        try
 165        {
 0166            SelectedCulture = ResolveSupportedCulture(_globalization.CurrentCulture);
 0167        }
 168        finally
 169        {
 0170            _suppressApply = false;
 0171        }
 0172    }
 173
 174    private void RefreshTimeZoneFromService()
 175    {
 0176        _suppressApply = true;
 177        try
 178        {
 0179            SelectedTimeZone = _globalization.CurrentTimeZone;
 0180        }
 181        finally
 182        {
 0183            _suppressApply = false;
 0184        }
 0185    }
 186
 187    private void ApplyCulture()
 188    {
 0189        if (_suppressApply)
 0190            return;
 191
 0192        var cultureCode = SelectedCulture is null || AutomaticCulture
 0193            ? CultureInfo.InstalledUICulture.ToString()
 0194            : SelectedCulture.ToString();
 195
 0196        var current = _globalization.CurrentCulture;
 0197        if (cultureCode != current.Name && cultureCode != current.Parent.Name)
 0198            _globalization.SetCulture(cultureCode);
 0199    }
 200
 201    private void ApplyTimeZone()
 202    {
 0203        if (_suppressApply)
 0204            return;
 205
 0206        var timeZone = SelectedTimeZone is null || AutomaticTimeZone
 0207            ? TimeZoneInfo.Local
 0208            : SelectedTimeZone;
 209
 0210        if (!timeZone.Equals(_globalization.CurrentTimeZone))
 0211            _globalization.SetTimeZone(timeZone);
 0212    }
 213
 214    private CultureInfo ResolveSupportedCulture(CultureInfo culture)
 215    {
 0216        while (!culture.Equals(CultureInfo.InvariantCulture))
 217        {
 0218            if (Cultures.Contains(culture))
 0219                return culture;
 220
 0221            culture = culture.Parent;
 222        }
 223
 0224        return Cultures.FirstOrDefault() ?? _globalization.CurrentCulture;
 225    }
 226}
 227