Settings.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. using System;
  2. using System.ComponentModel;
  3. using System.IO;
  4. using System.Windows.Media;
  5. using Newtonsoft.Json;
  6. using WpfWindowPlacement;
  7. namespace DesktopClock.Properties;
  8. public sealed class Settings : INotifyPropertyChanged
  9. {
  10. private DateTime _fileLastUsed = DateTime.UtcNow;
  11. public static readonly string Path = "DesktopClock.settings";
  12. private static readonly Lazy<Settings> _default = new(() => TryLoad() ?? new Settings());
  13. private static readonly JsonSerializerSettings _jsonSerializerSettings = new()
  14. {
  15. Formatting = Formatting.Indented
  16. };
  17. private Settings()
  18. {
  19. var random = new Random();
  20. // Random default theme.
  21. Theme = App.Themes[random.Next(0, App.Themes.Count)];
  22. }
  23. #pragma warning disable CS0067 // The event 'Settings.PropertyChanged' is never used
  24. public event PropertyChangedEventHandler PropertyChanged;
  25. #pragma warning restore CS0067 // The event 'Settings.PropertyChanged' is never used
  26. public static Settings Default => _default.Value;
  27. #region "Properties"
  28. public WindowPlacement Placement { get; set; }
  29. public bool Topmost { get; set; } = true;
  30. public bool ShowInTaskbar { get; set; } = true;
  31. public double Height { get; set; } = 48;
  32. public string TimeZone { get; set; } = string.Empty;
  33. public string Format { get; set; } = "dddd, MMM dd, HH:mm:ss";
  34. public bool BackgroundEnabled { get; set; } = true;
  35. public double BackgroundOpacity { get; set; } = 0.90;
  36. public Color OuterColor { get; set; }
  37. public Color TextColor { get; set; }
  38. public string FontFamily { get; set; } = "Consolas";
  39. public DateTimeOffset CountdownTo { get; set; } = DateTimeOffset.MinValue;
  40. [JsonIgnore]
  41. public Theme Theme
  42. {
  43. get => new("Custom", TextColor.ToString(), OuterColor.ToString());
  44. set
  45. {
  46. TextColor = (Color)ColorConverter.ConvertFromString(value.PrimaryColor);
  47. OuterColor = (Color)ColorConverter.ConvertFromString(value.SecondaryColor);
  48. }
  49. }
  50. #endregion "Properties"
  51. /// <summary>
  52. /// Determines if the settings file has been modified externally since the last time it was used.
  53. /// </summary>
  54. public bool CheckIfModifiedExternally() =>
  55. File.GetLastWriteTimeUtc(Path) > _fileLastUsed;
  56. /// <summary>
  57. /// Saves to the default path.
  58. /// </summary>
  59. public void Save()
  60. {
  61. using (var fileStream = new FileStream(Path, FileMode.Create))
  62. using (var streamWriter = new StreamWriter(fileStream))
  63. using (var jsonWriter = new JsonTextWriter(streamWriter))
  64. JsonSerializer.Create(_jsonSerializerSettings).Serialize(jsonWriter, this);
  65. _fileLastUsed = DateTime.UtcNow;
  66. }
  67. /// <summary>
  68. /// Saves to the default path unless a save has already happened from an external source.
  69. /// </summary>
  70. public void SaveIfNotModifiedExternally()
  71. {
  72. if (!CheckIfModifiedExternally())
  73. Save();
  74. }
  75. /// <summary>
  76. /// Loads from the default path.
  77. /// </summary>
  78. private static Settings Load()
  79. {
  80. using (var fileStream = new FileStream(Path, FileMode.Open))
  81. using (var streamReader = new StreamReader(fileStream))
  82. using (var jsonReader = new JsonTextReader(streamReader))
  83. return JsonSerializer.Create(_jsonSerializerSettings).Deserialize<Settings>(jsonReader);
  84. }
  85. /// <summary>
  86. /// Returns loaded settings from the default path or null if it fails.
  87. /// </summary>
  88. private static Settings TryLoad()
  89. {
  90. try
  91. {
  92. return Load();
  93. }
  94. catch
  95. {
  96. return null;
  97. }
  98. }
  99. }