1
0
Daniel Chalmers 2 жил өмнө
parent
commit
fd4e714530

+ 7 - 1
.editorconfig

@@ -50,6 +50,7 @@ dotnet_style_null_propagation = true
 dotnet_style_object_initializer = true:silent
 dotnet_style_operator_placement_when_wrapping = beginning_of_line
 dotnet_style_prefer_auto_properties = true:suggestion
+dotnet_style_prefer_collection_expression = true
 dotnet_style_prefer_compound_assignment = true
 dotnet_style_prefer_conditional_expression_over_assignment = true
 dotnet_style_prefer_conditional_expression_over_return = true
@@ -104,12 +105,15 @@ csharp_style_conditional_delegate_call = true
 # Modifier preferences
 csharp_prefer_static_local_function = true:warning
 csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
+csharp_style_prefer_readonly_struct = true
+csharp_style_prefer_readonly_struct_member = true
 
 # Code-block preferences
 csharp_prefer_braces = when_multiline:warning
 csharp_prefer_simple_using_statement = true:silent
 csharp_style_namespace_declarations = file_scoped
 csharp_style_prefer_method_group_conversion = true
+csharp_style_prefer_primary_constructors = true
 csharp_style_prefer_top_level_statements = true
 
 # Expression-level preferences
@@ -124,7 +128,7 @@ csharp_style_prefer_range_operator = true
 csharp_style_prefer_tuple_swap = true:silent
 csharp_style_prefer_utf8_string_literals = true
 csharp_style_throw_expression = true
-csharp_style_unused_value_assignment_preference = discard_variable:warning
+csharp_style_unused_value_assignment_preference = discard_variable
 csharp_style_unused_value_expression_statement_preference = discard_variable
 
 # 'using' directive preferences
@@ -132,6 +136,8 @@ csharp_using_directive_placement = outside_namespace:error
 
 # New line preferences
 csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
+csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true
+csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true
 csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
 csharp_style_allow_embedded_statements_on_same_line_experimental = false:warning
 

+ 2 - 2
DesktopClock.Tests/DesktopClock.Tests.csproj

@@ -7,8 +7,8 @@
 
   <ItemGroup>
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
-    <PackageReference Include="xunit" Version="2.5.1" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.1" PrivateAssets="All">
+    <PackageReference Include="xunit" Version="2.5.2" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" PrivateAssets="all">
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
     <ProjectReference Include="..\DesktopClock\DesktopClock.csproj" />

+ 16 - 16
DesktopClock/App.xaml.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
 using System.Windows;
 using DesktopClock.Properties;
 using Microsoft.Win32;
@@ -12,20 +13,20 @@ namespace DesktopClock;
 /// </summary>
 public partial class App : Application
 {
-    public static string FilePath = Process.GetCurrentProcess().MainModule.FileName;
+    public static FileInfo MainFileInfo = new(Process.GetCurrentProcess().MainModule.FileName);
 
     // https://www.materialui.co/colors - A100, A700.
-    public static IReadOnlyList<Theme> Themes { get; } = new[]
+    public static IReadOnlyList<Theme> Themes { get; } = new Theme[]
     {
-        new Theme("Light Text", "#F5F5F5", "#212121"),
-        new Theme("Dark Text", "#212121", "#F5F5F5"),
-        new Theme("Red", "#D50000", "#FF8A80"),
-        new Theme("Pink", "#C51162", "#FF80AB"),
-        new Theme("Purple", "#AA00FF", "#EA80FC"),
-        new Theme("Blue", "#2962FF", "#82B1FF"),
-        new Theme("Cyan", "#00B8D4", "#84FFFF"),
-        new Theme("Green", "#00C853", "#B9F6CA"),
-        new Theme("Orange", "#FF6D00", "#FFD180"),
+        new("Light Text", "#F5F5F5", "#212121"),
+        new("Dark Text", "#212121", "#F5F5F5"),
+        new("Red", "#D50000", "#FF8A80"),
+        new("Pink", "#C51162", "#FF80AB"),
+        new("Purple", "#AA00FF", "#EA80FC"),
+        new("Blue", "#2962FF", "#82B1FF"),
+        new("Cyan", "#00B8D4", "#84FFFF"),
+        new("Green", "#00C853", "#B9F6CA"),
+        new("Orange", "#FF6D00", "#FFD180"),
     };
 
     /// <summary>
@@ -35,22 +36,21 @@ public partial class App : Application
         DateTimeUtil.TryGetTimeZoneById(Settings.Default.TimeZone, out var timeZoneInfo) ? timeZoneInfo : TimeZoneInfo.Local;
 
     /// <summary>
-    /// Selects a time zone to use.
+    /// Sets the time zone to be used.
     /// </summary>
     public static void SetTimeZone(TimeZoneInfo timeZone) =>
         Settings.Default.TimeZone = timeZone.Id;
 
     /// <summary>
-    /// Sets a value in the registry determining whether the current executable should run on system startup.
+    /// Sets or deletes a value in the registry which enables the current executable to run on system startup.
     /// </summary>
-    /// <param name="runOnStartup"></param>
     public static void SetRunOnStartup(bool runOnStartup)
     {
-        var keyName = GetSha256Hash(FilePath);
+        var keyName = GetSha256Hash(MainFileInfo.FullName);
         using var key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
 
         if (runOnStartup)
-            key?.SetValue(keyName, FilePath); // Use the path as the name so we can handle multiple exes, but hash it or Windows won't like it.
+            key?.SetValue(keyName, MainFileInfo.FullName); // Use the path as the name so we can handle multiple exes, but hash it or Windows won't like it.
         else
             key?.DeleteValue(keyName, false);
     }

+ 1 - 1
DesktopClock/DesktopClock.csproj

@@ -18,7 +18,7 @@
   <ItemGroup>
     <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
     <PackageReference Include="Costura.Fody" Version="5.7.0" PrivateAssets="All" />
-    <PackageReference Include="H.NotifyIcon.Wpf" Version="2.0.116" />
+    <PackageReference Include="H.NotifyIcon.Wpf" Version="2.0.118" />
     <PackageReference Include="Humanizer.Core" Version="2.14.1" />
     <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
     <PackageReference Include="PropertyChanged.Fody" Version="4.1.0" PrivateAssets="All" />

+ 16 - 14
DesktopClock/MainWindow.xaml.cs

@@ -26,7 +26,7 @@ public partial class MainWindow : Window
     private TimeZoneInfo _timeZone;
 
     /// <summary>
-    /// Should the clock be a countdown?
+    /// Indicates whether the clock should be shown as a countdown.
     /// </summary>
     [ObservableProperty]
     private bool _isCountdown;
@@ -52,26 +52,26 @@ public partial class MainWindow : Window
 
         ContextMenu = Resources["MainContextMenu"] as ContextMenu;
 
-        CreateOrDestroyTrayIcon(!Settings.Default.ShowInTaskbar, true);
+        ConfigureTrayIcon(!Settings.Default.ShowInTaskbar, true);
     }
 
     [RelayCommand]
     public void CopyToClipboard() => Clipboard.SetText(CurrentTimeOrCountdownString);
 
     /// <summary>
-    /// Sets app theme to parameter's value.
+    /// Sets app's theme to given value.
     /// </summary>
     [RelayCommand]
     public void SetTheme(Theme theme) => Settings.Default.Theme = theme;
 
     /// <summary>
-    /// Sets format string in settings to parameter's string.
+    /// Sets format string in settings to given string.
     /// </summary>
     [RelayCommand]
     public void SetFormat(string format) => Settings.Default.Format = format;
 
     /// <summary>
-    /// Sets time zone ID in settings to parameter's time zone ID.
+    /// Sets time zone ID in settings to given time zone ID.
     /// </summary>
     [RelayCommand]
     public void SetTimeZone(TimeZoneInfo tzi) => App.SetTimeZone(tzi);
@@ -90,16 +90,15 @@ public partial class MainWindow : Window
         if (result != MessageBoxResult.OK)
             return;
 
-        var currentExe = new FileInfo(App.FilePath);
-        var newExePath = Path.Combine(currentExe.DirectoryName, currentExe.GetFileAtNextIndex().Name);
+        var newExePath = Path.Combine(App.MainFileInfo.DirectoryName, App.MainFileInfo.GetFileAtNextIndex().Name);
 
         // Copy and start the new clock.
-        File.Copy(currentExe.FullName, newExePath);
+        File.Copy(App.MainFileInfo.FullName, newExePath);
         Process.Start(newExePath);
     }
 
     /// <summary>
-    /// Explains how to enable countdown mode, then asks user if they want to go to Advanced settings to do so.
+    /// Explains how to enable countdown mode, then asks user if they want to view Advanced settings to do so.
     /// </summary>
     [RelayCommand]
     public void CountdownTo()
@@ -110,8 +109,10 @@ public partial class MainWindow : Window
             "Open advanced settings now?",
             Title, MessageBoxButton.OKCancel, MessageBoxImage.Question, MessageBoxResult.OK);
 
-        if (result == MessageBoxResult.OK)
-            OpenSettings();
+        if (result != MessageBoxResult.OK)
+            return;
+
+        OpenSettings();
     }
 
     /// <summary>
@@ -159,9 +160,9 @@ public partial class MainWindow : Window
         Close();
     }
 
-    private void CreateOrDestroyTrayIcon(bool showTrayIcon, bool firstLaunch)
+    private void ConfigureTrayIcon(bool showIcon, bool firstLaunch)
     {
-        if (showTrayIcon)
+        if (showIcon)
         {
             if (_trayIcon == null)
             {
@@ -195,7 +196,7 @@ public partial class MainWindow : Window
                 break;
 
             case nameof(Settings.Default.ShowInTaskbar):
-                CreateOrDestroyTrayIcon(!Settings.Default.ShowInTaskbar, false);
+                ConfigureTrayIcon(!Settings.Default.ShowInTaskbar, false);
                 break;
 
             case nameof(Settings.Default.CountdownTo):
@@ -251,6 +252,7 @@ public partial class MainWindow : Window
             // Scale size based on scroll amount, with one notch on a default PC mouse being a change of 15%.
             var steps = e.Delta / (double)Mouse.MouseWheelDeltaForOneLine;
             var change = Settings.Default.Height * steps * 0.15;
+
             Settings.Default.Height = (int)Math.Min(Math.Max(Settings.Default.Height + change, 16), 160);
         }
     }

+ 1 - 1
DesktopClock/OutlinedTextBlock.cs

@@ -184,7 +184,7 @@ public class OutlinedTextBlock : FrameworkElement
     public OutlinedTextBlock()
     {
         UpdatePen();
-        TextDecorations = new TextDecorationCollection();
+        TextDecorations = [];
     }
 
     protected override void OnRender(DrawingContext drawingContext)

+ 3 - 4
DesktopClock/Properties/Settings.cs

@@ -26,12 +26,11 @@ public sealed class Settings : INotifyPropertyChanged, IDisposable
     private Settings()
     {
         // Settings file path from same directory as the executable.
-        var exeInfo = new FileInfo(App.FilePath);
-        var settingsFileName = Path.GetFileNameWithoutExtension(exeInfo.FullName) + ".settings";
-        FilePath = Path.Combine(exeInfo.DirectoryName, settingsFileName);
+        var settingsFileName = Path.GetFileNameWithoutExtension(App.MainFileInfo.FullName) + ".settings";
+        FilePath = Path.Combine(App.MainFileInfo.DirectoryName, settingsFileName);
 
         // Watch for changes.
-        _watcher = new(exeInfo.DirectoryName, settingsFileName)
+        _watcher = new(App.MainFileInfo.DirectoryName, settingsFileName)
         {
             EnableRaisingEvents = true
         };

+ 1 - 1
DesktopClock/Theme.cs

@@ -1,6 +1,6 @@
 namespace DesktopClock;
 
-public readonly struct Theme
+public readonly record struct Theme
 {
     public string Name { get; }
     public string PrimaryColor { get; }