From 1f936df3ebce73b726ed11c9fa38fd477b4b0fbd Mon Sep 17 00:00:00 2001
From: Laszlo Nemeth <57342539+donlaci@users.noreply.github.com>
Date: Fri, 20 Oct 2023 14:23:25 +0200
Subject: [PATCH] [Settings]Adding a Dashboard Panel (#29023)

* Dashboard: modifying page content + adding SW version button.

* Visual tweaks and minor viewmodel changes

* Updated spacing

* Adding Settings icon

* Settiing the Dashboard page as the default one. Adding functionality to switch to settings pages from the Dashboard page. Localizing texts.

* fixing csproj file

* Reimplementing Active modules handling, showing only the active modules (and not having invisible inactive modules).

* Removing unneccessary binding

* Fix text wrapping

* Adding Registry previewer launch, adding activation mode for FindMyMouse and QuickAccent, modify File Locksmith description.

* Spell checker fix typo

* Adding GPO-blocked state, modifying buttons: adding description, icon.

* Modifying dashboard button layout

* Use SettingsCard instead of button

* Restructuring the dashboard panel

* Removing togglebuttons from the left panel. Showing only active modules. Adding key remappings (to KBM)

* Removing settings buttons, removing descriptions, icons from buttons. Add update of remapped keys, shortcuts.

* Refactoring dashboard

* Making list always visible and fixing scrolling behavior

* Adding background gradient to cards

* Removing keyboard manager's key mappings, minor changes in texts, fixing enabled state when GPO-enabled.

* Use ListView instead of ItemsRepeater

* Updates

* removing right panel with all modules. Extending "left" panel with toggleswitches, showing all modules.

* Separate lists

* Adding Flyout with key remappings for KBM module, adding IsLocked property, icons

* Visual tweaks

* Tweaks

* Fixing lock icon margin

* Minor fixes.

* Removing unused resources

* Make Dashboard default when coming from the OOBE General

* Removed the Previous, Next Layout buttons from FancyZones. Added activation information

---------

Co-authored-by: Niels Laute <niels.laute@live.nl>
---
 src/common/Common.UI/SettingsDeepLink.cs      |   3 +
 src/runner/main.cpp                           |   2 +-
 src/runner/settings_window.cpp                |  10 +-
 src/runner/settings_window.h                  |   3 +-
 .../Converters/ModuleItemTemplateSelector.cs  |  33 +
 .../NegativeBoolToVisibilityConverter.cs      |  37 +
 .../Settings.UI/PowerToys.Settings.csproj     |  11 +-
 .../Settings.UI/SettingsXAML/App.xaml.cs      |  11 +-
 .../Controls/KeyVisual/KeyVisual.cs           |   7 +-
 .../Controls/KeyVisual/KeyVisual.xaml         |  76 +-
 .../ShortcutWithTextLabelControl.xaml         |   5 +-
 .../OOBE/Views/OobeOverview.xaml.cs           |   2 +-
 .../OOBE/Views/OobeOverviewAlternate.xaml.cs  |   2 +-
 .../Views/OobeOverviewPlaceholder.xaml.cs     |   2 +-
 .../SettingsXAML/Views/DashboardPage.xaml     | 446 ++++++++++
 .../SettingsXAML/Views/DashboardPage.xaml.cs  |  58 ++
 .../Views/KeyboardManagerPage.xaml.cs         |   2 +-
 .../SettingsXAML/Views/ShellPage.xaml         |   8 +-
 .../SettingsXAML/Views/ShellPage.xaml.cs      |   4 +-
 .../Settings.UI/Strings/en-us/Resources.resw  |  97 ++-
 .../ViewModels/DashboardListItem.cs           |  69 ++
 .../ViewModels/DashboardModuleItem.cs         |  75 ++
 .../ViewModels/DashboardViewModel.cs          | 803 ++++++++++++++++++
 .../ViewModels/KeyboardManagerViewModel.cs    |   4 +-
 24 files changed, 1721 insertions(+), 49 deletions(-)
 create mode 100644 src/settings-ui/Settings.UI/Converters/ModuleItemTemplateSelector.cs
 create mode 100644 src/settings-ui/Settings.UI/Converters/NegativeBoolToVisibilityConverter.cs
 create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml
 create mode 100644 src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs
 create mode 100644 src/settings-ui/Settings.UI/ViewModels/DashboardListItem.cs
 create mode 100644 src/settings-ui/Settings.UI/ViewModels/DashboardModuleItem.cs
 create mode 100644 src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs

diff --git a/src/common/Common.UI/SettingsDeepLink.cs b/src/common/Common.UI/SettingsDeepLink.cs
index 1a154f0a8255..97547c42920c 100644
--- a/src/common/Common.UI/SettingsDeepLink.cs
+++ b/src/common/Common.UI/SettingsDeepLink.cs
@@ -28,6 +28,7 @@ public enum SettingsWindow
             PowerOCR,
             RegistryPreview,
             CropAndLock,
+            Dashboard,
         }
 
         private static string SettingsWindowNameToString(SettingsWindow value)
@@ -68,6 +69,8 @@ private static string SettingsWindowNameToString(SettingsWindow value)
                     return "RegistryPreview";
                 case SettingsWindow.CropAndLock:
                     return "CropAndLock";
+                case SettingsWindow.Dashboard:
+                    return "Dashboard";
                 default:
                     {
                         return string.Empty;
diff --git a/src/runner/main.cpp b/src/runner/main.cpp
index eb1fb485031b..fab4a6500b5a 100644
--- a/src/runner/main.cpp
+++ b/src/runner/main.cpp
@@ -81,7 +81,7 @@ inline wil::unique_mutex_nothrow create_msi_mutex()
 void open_menu_from_another_instance(std::optional<std::string> settings_window)
 {
     const HWND hwnd_main = FindWindowW(L"PToyTrayIconWindow", nullptr);
-    LPARAM msg = static_cast<LPARAM>(ESettingsWindowNames::Overview);
+    LPARAM msg = static_cast<LPARAM>(ESettingsWindowNames::Dashboard);
     if (settings_window.has_value() && settings_window.value() != "")
     {
         msg = static_cast<LPARAM>(ESettingsWindowNames_from_string(settings_window.value()));
diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp
index bcba0915b175..f7f8d5df637a 100644
--- a/src/runner/settings_window.cpp
+++ b/src/runner/settings_window.cpp
@@ -596,7 +596,7 @@ void open_settings_window(std::optional<std::wstring> settings_window, bool show
                 }
                 else
                 {
-                    current_settings_ipc->send(L"{\"ShowYourself\":\"Overview\"}");
+                    current_settings_ipc->send(L"{\"ShowYourself\":\"Dashboard\"}");
                 }
             }
         }
@@ -676,6 +676,8 @@ std::string ESettingsWindowNames_to_string(ESettingsWindowNames value)
         return "RegistryPreview";
     case ESettingsWindowNames::CropAndLock:
         return "CropAndLock";
+    case ESettingsWindowNames::Dashboard:
+        return "Dashboard";
     default:
     {
         Logger::error(L"Can't convert ESettingsWindowNames value={} to string", static_cast<int>(value));
@@ -755,11 +757,15 @@ ESettingsWindowNames ESettingsWindowNames_from_string(std::string value)
     {
         return ESettingsWindowNames::CropAndLock;
     }
+    else if (value == "Dashboard")
+    {
+        return ESettingsWindowNames::Dashboard;
+    }
     else
     {
         Logger::error(L"Can't convert string value={} to ESettingsWindowNames", winrt::to_hstring(value));
         assert(false);
     }
 
-    return ESettingsWindowNames::Overview;
+    return ESettingsWindowNames::Dashboard;
 }
diff --git a/src/runner/settings_window.h b/src/runner/settings_window.h
index 2a14ec46e04e..06aac30dc8d5 100644
--- a/src/runner/settings_window.h
+++ b/src/runner/settings_window.h
@@ -4,7 +4,8 @@
 
 enum class ESettingsWindowNames
 {
-    Overview = 0,
+    Dashboard = 0,
+    Overview,
     Awake,
     ColorPicker,
     FancyZones,
diff --git a/src/settings-ui/Settings.UI/Converters/ModuleItemTemplateSelector.cs b/src/settings-ui/Settings.UI/Converters/ModuleItemTemplateSelector.cs
new file mode 100644
index 000000000000..b34331a0e7a4
--- /dev/null
+++ b/src/settings-ui/Settings.UI/Converters/ModuleItemTemplateSelector.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Settings.UI.ViewModels;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+
+namespace Microsoft.PowerToys.Settings.UI.Converters
+{
+    public class ModuleItemTemplateSelector : DataTemplateSelector
+    {
+        public DataTemplate TextTemplate { get; set; }
+
+        public DataTemplate ButtonTemplate { get; set; }
+
+        public DataTemplate ShortcutTemplate { get; set; }
+
+        public DataTemplate KBMTemplate { get; set; }
+
+        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
+        {
+            switch (item)
+            {
+                case DashboardModuleButtonItem: return ButtonTemplate;
+                case DashboardModuleShortcutItem: return ShortcutTemplate;
+                case DashboardModuleTextItem: return TextTemplate;
+                case DashboardModuleKBMItem: return KBMTemplate;
+                default: return TextTemplate;
+            }
+        }
+    }
+}
diff --git a/src/settings-ui/Settings.UI/Converters/NegativeBoolToVisibilityConverter.cs b/src/settings-ui/Settings.UI/Converters/NegativeBoolToVisibilityConverter.cs
new file mode 100644
index 000000000000..df9f02eca702
--- /dev/null
+++ b/src/settings-ui/Settings.UI/Converters/NegativeBoolToVisibilityConverter.cs
@@ -0,0 +1,37 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Globalization;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Data;
+
+namespace Microsoft.PowerToys.Settings.UI.Converters
+{
+    public class NegativeBoolToVisibilityConverter : IValueConverter
+    {
+        object IValueConverter.Convert(object value, Type targetType, object parameter, string language)
+        {
+            if ((bool)value)
+            {
+                return Visibility.Collapsed;
+            }
+
+            return Visibility.Visible;
+        }
+
+        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, string language)
+        {
+            if (value is Visibility)
+            {
+                if ((Visibility)value == Visibility.Visible)
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+    }
+}
diff --git a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj
index 98be30ec56c5..e601b11886d5 100644
--- a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj
+++ b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj
@@ -21,6 +21,9 @@
     <!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
     <ProjectPriFileName>PowerToys.Settings.pri</ProjectPriFileName>
   </PropertyGroup>
+  <ItemGroup>
+    <None Remove="SettingsXAML\Views\DashboardPage.xaml" />
+  </ItemGroup>
 
   <ItemGroup>
     <Page Remove="SettingsXAML\App.xaml" />
@@ -124,5 +127,11 @@
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </None>
   </ItemGroup>
+
+  <ItemGroup>
+    <Page Update="SettingsXAML\Views\DashboardPage.xaml">
+      <XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
+    </Page>
+  </ItemGroup>
 	
-</Project>
+</Project>
\ No newline at end of file
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs
index ba9988dd2dd4..ea02e1779e74 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs
+++ b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs
@@ -60,7 +60,7 @@ private enum Arguments
 
         public bool ShowScoobe { get; set; }
 
-        public Type StartupPage { get; set; } = typeof(Views.GeneralPage);
+        public Type StartupPage { get; set; } = typeof(Views.DashboardPage);
 
         public static Action<string> IPCMessageReceivedCallback { get; set; }
 
@@ -218,8 +218,8 @@ protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs ar
                 settingsWindow.NavigateToSection(StartupPage);
                 ShowMessageDialog("The application is running in Debug mode.", "DEBUG");
 #else
-                /* If we try to run Settings as a standalone app, it will start PowerToys.exe if not running and open Settings again through it in the General page. */
-                SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.Overview, true);
+                /* If we try to run Settings as a standalone app, it will start PowerToys.exe if not running and open Settings again through it in the Dashboard page. */
+                SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.Dashboard, true);
                 Exit();
 #endif
             }
@@ -380,6 +380,7 @@ public static Type GetPage(string settingWindow)
         {
             switch (settingWindow)
             {
+                case "Dashboard": return typeof(DashboardPage);
                 case "Overview": return typeof(GeneralPage);
                 case "AlwaysOnTop": return typeof(AlwaysOnTopPage);
                 case "Awake": return typeof(AwakePage);
@@ -404,9 +405,9 @@ public static Type GetPage(string settingWindow)
                 case "Peek": return typeof(PeekPage);
                 case "CropAndLock": return typeof(CropAndLockPage);
                 default:
-                    // Fallback to general
+                    // Fallback to Dashboard
                     Debug.Assert(false, "Unexpected SettingsWindow argument value");
-                    return typeof(GeneralPage);
+                    return typeof(DashboardPage);
             }
         }
     }
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.cs
index 5e5d3ee846a3..8b3683198425 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.cs
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.cs
@@ -116,7 +116,7 @@ private void Update()
 
                         case 91: // The left Windows key
                         case 92: // The right Windows key
-                            PathIcon winIcon = XamlReader.Load(@"<PathIcon xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" Data=""M9,17V9h8v8ZM0,17V9H8v8ZM9,8V0h8V8ZM0,8V0H8V8Z"" />") as PathIcon;
+                            PathIcon winIcon = XamlReader.Load(@"<PathIcon xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" Data=""M683 1229H0V546h683v683zm819 0H819V546h683v683zm-819 819H0v-683h683v683zm819 0H819v-683h683v683z"" />") as PathIcon;
                             Viewbox winIconContainer = new Viewbox();
                             winIconContainer.Child = winIcon;
                             winIconContainer.HorizontalAlignment = HorizontalAlignment.Center;
@@ -143,6 +143,10 @@ public Style GetStyleSize(string styleName)
             {
                 return (Style)App.Current.Resources["SmallOutline" + styleName];
             }
+            else if (VisualType == VisualType.TextOnly)
+            {
+                return (Style)App.Current.Resources["Only" + styleName];
+            }
             else
             {
                 return (Style)App.Current.Resources["Default" + styleName];
@@ -181,6 +185,7 @@ public enum VisualType
     {
         Small,
         SmallOutline,
+        TextOnly,
         Large,
     }
 }
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml
index 2d469563a233..68590a040abf 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml
@@ -5,9 +5,7 @@
 
     <x:Double x:Key="DefaultIconSize">16</x:Double>
     <x:Double x:Key="SmallIconSize">12</x:Double>
-    <Style
-        x:Key="DefaultTextKeyVisualStyle"
-        TargetType="local:KeyVisual">
+    <Style x:Key="DefaultTextKeyVisualStyle" TargetType="local:KeyVisual">
         <Setter Property="MinWidth" Value="56" />
         <Setter Property="MinHeight" Value="48" />
         <Setter Property="Background" Value="{ThemeResource AccentButtonBackground}" />
@@ -23,26 +21,6 @@
             <Setter.Value>
                 <ControlTemplate TargetType="local:KeyVisual">
                     <Grid>
-                        <Grid>
-                            <Rectangle
-                                x:Name="ContentHolder"
-                                Height="{TemplateBinding Height}"
-                                MinWidth="{TemplateBinding MinWidth}"
-                                Fill="{TemplateBinding Background}"
-                                RadiusX="4"
-                                RadiusY="4"
-                                Stroke="{TemplateBinding BorderBrush}"
-                                StrokeThickness="{TemplateBinding BorderThickness}" />
-                            <ContentPresenter
-                                x:Name="KeyPresenter"
-                                Margin="{TemplateBinding Padding}"
-                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
-                                VerticalAlignment="Center"
-                                Content="{TemplateBinding Content}"
-                                FontSize="{TemplateBinding FontSize}"
-                                FontWeight="{TemplateBinding FontWeight}"
-                                Foreground="{TemplateBinding Foreground}" />
-                        </Grid>
                         <VisualStateManager.VisualStateGroups>
                             <VisualStateGroup x:Name="CommonStates">
                                 <VisualState x:Name="Normal" />
@@ -67,6 +45,26 @@
                                 </VisualState>
                             </VisualStateGroup>
                         </VisualStateManager.VisualStateGroups>
+                        <Grid>
+                            <Rectangle
+                                x:Name="ContentHolder"
+                                Height="{TemplateBinding Height}"
+                                MinWidth="{TemplateBinding MinWidth}"
+                                Fill="{TemplateBinding Background}"
+                                RadiusX="4"
+                                RadiusY="4"
+                                Stroke="{TemplateBinding BorderBrush}"
+                                StrokeThickness="{TemplateBinding BorderThickness}" />
+                            <ContentPresenter
+                                x:Name="KeyPresenter"
+                                Margin="{TemplateBinding Padding}"
+                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+                                VerticalAlignment="Center"
+                                Content="{TemplateBinding Content}"
+                                FontSize="{TemplateBinding FontSize}"
+                                FontWeight="{TemplateBinding FontWeight}"
+                                Foreground="{TemplateBinding Foreground}" />
+                        </Grid>
                     </Grid>
                 </ControlTemplate>
             </Setter.Value>
@@ -101,6 +99,7 @@
     </Style>
 
 
+
     <Style
         x:Key="DefaultIconKeyVisualStyle"
         BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
@@ -141,4 +140,35 @@
         <Setter Property="FontSize" Value="9" />
         <Setter Property="HorizontalContentAlignment" Value="Center" />
     </Style>
+
+    <Style
+        x:Key="OnlyTextKeyVisualStyle"
+        BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
+        TargetType="local:KeyVisual">
+        <Setter Property="MinHeight" Value="12" />
+        <Setter Property="MinWidth" Value="12" />
+        <Setter Property="Background" Value="Transparent" />
+        <Setter Property="Foreground" Value="{ThemeResource ButtonForeground}" />
+        <Setter Property="BorderBrush" Value="Transparent" />
+        <Setter Property="FontWeight" Value="Normal" />
+        <Setter Property="Padding" Value="0" />
+        <Setter Property="FontSize" Value="12" />
+        <Setter Property="HorizontalContentAlignment" Value="Center" />
+    </Style>
+
+    <Style
+        x:Key="OnlyIconKeyVisualStyle"
+        BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
+        TargetType="local:KeyVisual">
+        <Setter Property="MinHeight" Value="10" />
+        <Setter Property="MinWidth" Value="10" />
+        <Setter Property="Background" Value="Transparent" />
+        <Setter Property="Foreground" Value="{ThemeResource ButtonForeground}" />
+        <Setter Property="BorderBrush" Value="Transparent" />
+        <Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
+        <Setter Property="FontWeight" Value="Normal" />
+        <Setter Property="Padding" Value="0,0,0,3" />
+        <!--<Setter Property="FontSize" Value="9" />-->
+        <Setter Property="HorizontalContentAlignment" Value="Center" />
+    </Style>
 </ResourceDictionary>
\ No newline at end of file
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutWithTextLabelControl.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutWithTextLabelControl.xaml
index 1a51b178741d..1f1fc9e071ef 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutWithTextLabelControl.xaml
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutWithTextLabelControl.xaml
@@ -23,9 +23,7 @@
             ItemsSource="{x:Bind Keys}">
             <ItemsControl.ItemsPanel>
                 <ItemsPanelTemplate>
-                    <StackPanel
-                        Orientation="Horizontal"
-                        Spacing="4" />
+                    <StackPanel Orientation="Horizontal" Spacing="4" />
                 </ItemsPanelTemplate>
             </ItemsControl.ItemsPanel>
             <ItemsControl.ItemTemplate>
@@ -41,7 +39,6 @@
         </ItemsControl>
         <toolkitcontrols:MarkdownTextBlock
             Grid.Column="1"
-            Margin="8,0,0,0"
             VerticalAlignment="Center"
             Background="Transparent"
             Text="{x:Bind Text}" />
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverview.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverview.xaml.cs
index b86a17aa388e..d43bda83bfd2 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverview.xaml.cs
+++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverview.xaml.cs
@@ -25,7 +25,7 @@ private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedE
         {
             if (OobeShellPage.OpenMainWindowCallback != null)
             {
-                OobeShellPage.OpenMainWindowCallback(typeof(GeneralPage));
+                OobeShellPage.OpenMainWindowCallback(typeof(DashboardPage));
             }
 
             ViewModel.LogOpeningSettingsEvent();
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewAlternate.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewAlternate.xaml.cs
index c5171f415918..d0ae488347fd 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewAlternate.xaml.cs
+++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewAlternate.xaml.cs
@@ -31,7 +31,7 @@ private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedE
         {
             if (OobeShellPage.OpenMainWindowCallback != null)
             {
-                OobeShellPage.OpenMainWindowCallback(typeof(GeneralPage));
+                OobeShellPage.OpenMainWindowCallback(typeof(DashboardPage));
             }
 
             ViewModel.LogOpeningSettingsEvent();
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewPlaceholder.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewPlaceholder.xaml.cs
index 40dcb56aa28e..18a18189abf3 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewPlaceholder.xaml.cs
+++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewPlaceholder.xaml.cs
@@ -54,7 +54,7 @@ private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedE
         {
             if (OobeShellPage.OpenMainWindowCallback != null)
             {
-                OobeShellPage.OpenMainWindowCallback(typeof(GeneralPage));
+                OobeShellPage.OpenMainWindowCallback(typeof(DashboardPage));
             }
 
             ViewModel.LogOpeningSettingsEvent();
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml
new file mode 100644
index 000000000000..cac07b5bfd6a
--- /dev/null
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml
@@ -0,0 +1,446 @@
+<Page
+    x:Class="Microsoft.PowerToys.Settings.UI.Views.DashboardPage"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:Lib="using:Microsoft.PowerToys.Settings.UI.Library"
+    xmlns:controls="using:CommunityToolkit.WinUI.Controls"
+    xmlns:converters="using:CommunityToolkit.WinUI.Converters"
+    xmlns:custom="using:Microsoft.PowerToys.Settings.UI.Controls"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:localConverters="using:Microsoft.PowerToys.Settings.UI.Converters"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:viewmodels="using:Microsoft.PowerToys.Settings.UI.ViewModels"
+    AutomationProperties.LandmarkType="Main"
+    DataContext="DashboardViewModel"
+    mc:Ignorable="d">
+
+    <Page.Resources>
+        <localConverters:ModuleItemTemplateSelector
+            x:Key="ModuleItemTemplateSelector"
+            ButtonTemplate="{StaticResource ModuleItemButtonTemplate}"
+            KBMTemplate="{StaticResource ModuleItemKBMTemplate}"
+            ShortcutTemplate="{StaticResource ModuleItemShortcutTemplate}"
+            TextTemplate="{StaticResource ModuleItemTextTemplate}" />
+        <converters:CollectionVisibilityConverter x:Key="CollectionVisibilityConverter" />
+        <Style x:Name="KeysListViewContainerStyle" TargetType="ListViewItem">
+            <Setter Property="IsTabStop" Value="False" />
+        </Style>
+        <localConverters:UpdateStateToBoolConverter x:Key="UpdateStateToBoolConverter" />
+        <converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
+        <converters:BoolNegationConverter x:Key="BoolNegationConverter" />
+        <converters:BoolToVisibilityConverter
+            x:Key="BoolToInvertedVisibilityConverter"
+            FalseValue="Visible"
+            TrueValue="Collapsed" />
+        <DataTemplate x:Key="OriginalKeyTemplate" x:DataType="x:String">
+            <custom:KeyVisual Content="{Binding}" VisualType="SmallOutline" />
+        </DataTemplate>
+
+        <DataTemplate x:Key="RemappedKeyTemplate" x:DataType="x:String">
+            <custom:KeyVisual Content="{Binding}" VisualType="Small" />
+        </DataTemplate>
+
+        <DataTemplate x:Key="ModuleItemTextTemplate" x:DataType="viewmodels:DashboardModuleTextItem">
+            <TextBlock
+                Foreground="{ThemeResource TextFillColorSecondaryBrush}"
+                Style="{StaticResource CaptionTextBlockStyle}"
+                Text="{x:Bind Label, Mode=OneWay}"
+                TextWrapping="WrapWholeWords" />
+        </DataTemplate>
+
+        <DataTemplate x:Key="ModuleItemButtonTemplate" x:DataType="viewmodels:DashboardModuleButtonItem">
+            <Button
+                HorizontalAlignment="Stretch"
+                Click="{x:Bind ButtonClickHandler, Mode=OneWay}"
+                Content="{x:Bind ButtonTitle}" />
+        </DataTemplate>
+
+        <DataTemplate x:Key="ModuleItemShortcutTemplate" x:DataType="viewmodels:DashboardModuleShortcutItem">
+            <Grid ColumnSpacing="12">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="Auto" />
+                    <ColumnDefinition Width="*" />
+                </Grid.ColumnDefinitions>
+                <Border
+                    Padding="8,4"
+                    Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
+                    BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
+                    BorderThickness="1"
+                    CornerRadius="{StaticResource ControlCornerRadius}">
+                    <ItemsControl
+                        AutomationProperties.AccessibilityView="Raw"
+                        IsTabStop="False"
+                        ItemsSource="{x:Bind Path=Shortcut, Mode=TwoWay}">
+                        <ItemsControl.ItemsPanel>
+                            <ItemsPanelTemplate>
+                                <StackPanel Orientation="Horizontal" Spacing="12" />
+                            </ItemsPanelTemplate>
+                        </ItemsControl.ItemsPanel>
+                        <ItemsControl.ItemTemplate>
+                            <DataTemplate>
+                                <custom:KeyVisual
+                                    VerticalAlignment="Center"
+                                    AutomationProperties.AccessibilityView="Raw"
+                                    Content="{Binding}"
+                                    IsTabStop="False"
+                                    VisualType="TextOnly" />
+                            </DataTemplate>
+                        </ItemsControl.ItemTemplate>
+                    </ItemsControl>
+                </Border>
+
+                <TextBlock
+                    Grid.Column="1"
+                    VerticalAlignment="Center"
+                    Foreground="{ThemeResource TextFillColorSecondaryBrush}"
+                    Style="{StaticResource CaptionTextBlockStyle}"
+                    Text="{x:Bind Label, Mode=OneWay}"
+                    TextWrapping="WrapWholeWords" />
+            </Grid>
+        </DataTemplate>
+        <DataTemplate x:Key="ModuleItemKBMTemplate" x:DataType="viewmodels:DashboardModuleKBMItem">
+            <Button x:Uid="DashboardKBMShowMappingsButton" HorizontalAlignment="Stretch">
+                <Button.Flyout>
+                    <Flyout x:Name="DetailsFlyout" Placement="Bottom">
+                        <StackPanel Orientation="Vertical" Spacing="4">
+                            <ItemsControl ItemsSource="{x:Bind Path=RemapKeys, Mode=OneWay}">
+                                <ItemsControl.ItemsPanel>
+                                    <ItemsPanelTemplate>
+                                        <StackPanel Spacing="4" />
+                                    </ItemsPanelTemplate>
+                                </ItemsControl.ItemsPanel>
+                                <ItemsControl.ItemTemplate>
+                                    <DataTemplate x:DataType="Lib:KeysDataModel">
+                                        <StackPanel Orientation="Horizontal">
+                                            <Border
+                                                Padding="8,4"
+                                                Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
+                                                BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
+                                                BorderThickness="1"
+                                                CornerRadius="{StaticResource ControlCornerRadius}">
+                                                <ItemsControl
+                                                    AutomationProperties.AccessibilityView="Raw"
+                                                    IsTabStop="False"
+                                                    ItemsSource="{x:Bind GetMappedOriginalKeys()}">
+                                                    <ItemsControl.ItemsPanel>
+                                                        <ItemsPanelTemplate>
+                                                            <StackPanel Orientation="Horizontal" Spacing="12" />
+                                                        </ItemsPanelTemplate>
+                                                    </ItemsControl.ItemsPanel>
+                                                    <ItemsControl.ItemTemplate>
+                                                        <DataTemplate>
+                                                            <custom:KeyVisual
+                                                                VerticalAlignment="Center"
+                                                                AutomationProperties.AccessibilityView="Raw"
+                                                                Content="{Binding}"
+                                                                IsTabStop="False"
+                                                                VisualType="TextOnly" />
+                                                        </DataTemplate>
+                                                    </ItemsControl.ItemTemplate>
+                                                </ItemsControl>
+                                            </Border>
+                                            <custom:IsEnabledTextBlock
+                                                x:Uid="To"
+                                                Margin="8,0,8,0"
+                                                VerticalAlignment="Center"
+                                                Style="{StaticResource SecondaryIsEnabledTextBlockStyle}" />
+                                            <Border
+                                                Padding="8,4"
+                                                Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
+                                                BorderBrush="{ThemeResource AccentFillColorDefaultBrush}"
+                                                BorderThickness="1"
+                                                CornerRadius="{StaticResource ControlCornerRadius}">
+                                                <ItemsControl
+                                                    AutomationProperties.AccessibilityView="Raw"
+                                                    IsTabStop="False"
+                                                    ItemsSource="{x:Bind GetMappedNewRemapKeys()}">
+                                                    <ItemsControl.ItemsPanel>
+                                                        <ItemsPanelTemplate>
+                                                            <StackPanel Orientation="Horizontal" Spacing="12" />
+                                                        </ItemsPanelTemplate>
+                                                    </ItemsControl.ItemsPanel>
+                                                    <ItemsControl.ItemTemplate>
+                                                        <DataTemplate>
+                                                            <custom:KeyVisual
+                                                                VerticalAlignment="Center"
+                                                                AutomationProperties.AccessibilityView="Raw"
+                                                                Content="{Binding}"
+                                                                FontSize="12"
+                                                                Foreground="{ThemeResource AccentFillColorDefaultBrush}"
+                                                                IsTabStop="False"
+                                                                VisualType="TextOnly" />
+                                                        </DataTemplate>
+                                                    </ItemsControl.ItemTemplate>
+                                                </ItemsControl>
+                                            </Border>
+                                        </StackPanel>
+                                    </DataTemplate>
+                                </ItemsControl.ItemTemplate>
+                            </ItemsControl>
+                            <ItemsControl ItemsSource="{x:Bind Path=RemapShortcuts, Mode=OneWay}">
+                                <ItemsControl.ItemsPanel>
+                                    <ItemsPanelTemplate>
+                                        <StackPanel Spacing="4" />
+                                    </ItemsPanelTemplate>
+                                </ItemsControl.ItemsPanel>
+                                <ItemsControl.ItemTemplate>
+                                    <DataTemplate x:DataType="Lib:AppSpecificKeysDataModel">
+                                        <StackPanel Orientation="Horizontal">
+                                            <Border
+                                                Padding="8,4"
+                                                Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
+                                                BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
+                                                BorderThickness="1"
+                                                CornerRadius="{StaticResource ControlCornerRadius}">
+                                                <ItemsControl
+                                                    AutomationProperties.AccessibilityView="Raw"
+                                                    IsTabStop="False"
+                                                    ItemsSource="{x:Bind GetMappedOriginalKeys()}">
+                                                    <ItemsControl.ItemsPanel>
+                                                        <ItemsPanelTemplate>
+                                                            <StackPanel Orientation="Horizontal" Spacing="12" />
+                                                        </ItemsPanelTemplate>
+                                                    </ItemsControl.ItemsPanel>
+                                                    <ItemsControl.ItemTemplate>
+                                                        <DataTemplate>
+                                                            <custom:KeyVisual
+                                                                VerticalAlignment="Center"
+                                                                AutomationProperties.AccessibilityView="Raw"
+                                                                Content="{Binding}"
+                                                                IsTabStop="False"
+                                                                VisualType="TextOnly" />
+                                                        </DataTemplate>
+                                                    </ItemsControl.ItemTemplate>
+                                                </ItemsControl>
+                                            </Border>
+                                            <custom:IsEnabledTextBlock
+                                                x:Uid="To"
+                                                Margin="8,0,8,0"
+                                                VerticalAlignment="Center"
+                                                Style="{StaticResource SecondaryIsEnabledTextBlockStyle}" />
+                                            <Border
+                                                Padding="8,4"
+                                                Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
+                                                BorderBrush="{ThemeResource AccentFillColorDefaultBrush}"
+                                                BorderThickness="1"
+                                                CornerRadius="{StaticResource ControlCornerRadius}">
+                                                <ItemsControl
+                                                    AutomationProperties.AccessibilityView="Raw"
+                                                    IsTabStop="False"
+                                                    ItemsSource="{x:Bind GetMappedNewRemapKeys()}">
+                                                    <ItemsControl.ItemsPanel>
+                                                        <ItemsPanelTemplate>
+                                                            <StackPanel Orientation="Horizontal" Spacing="12" />
+                                                        </ItemsPanelTemplate>
+                                                    </ItemsControl.ItemsPanel>
+                                                    <ItemsControl.ItemTemplate>
+                                                        <DataTemplate>
+                                                            <custom:KeyVisual
+                                                                VerticalAlignment="Center"
+                                                                AutomationProperties.AccessibilityView="Raw"
+                                                                Content="{Binding}"
+                                                                Foreground="{ThemeResource AccentFillColorDefaultBrush}"
+                                                                IsTabStop="False"
+                                                                VisualType="TextOnly" />
+                                                        </DataTemplate>
+                                                    </ItemsControl.ItemTemplate>
+                                                </ItemsControl>
+                                            </Border>
+                                            <TextBlock
+                                                Margin="4,0,0,0"
+                                                VerticalAlignment="Center"
+                                                Foreground="{ThemeResource AccentFillColorDefaultBrush}"
+                                                Text="{x:Bind TargetApp}" />
+                                        </StackPanel>
+                                    </DataTemplate>
+                                </ItemsControl.ItemTemplate>
+                            </ItemsControl>
+                        </StackPanel>
+                    </Flyout>
+                </Button.Flyout>
+            </Button>
+        </DataTemplate>
+    </Page.Resources>
+    <Grid Margin="16,0,0,0" RowSpacing="24">
+        <Grid.RowDefinitions>
+            <RowDefinition Height="Auto" />
+            <RowDefinition Height="*" />
+        </Grid.RowDefinitions>
+        <TextBlock
+            x:Uid="DashboardTitle"
+            VerticalAlignment="Center"
+            Style="{StaticResource TitleTextBlockStyle}" />
+
+        <InfoBar
+            x:Uid="UpdateAvailable"
+            Margin="0,0,16,0"
+            HorizontalAlignment="Right"
+            VerticalAlignment="Center"
+            CornerRadius="8"
+            IsClosable="False"
+            IsOpen="{x:Bind ViewModel.UpdateAvailable, Mode=OneWay}"
+            Severity="Informational">
+            <InfoBar.ActionButton>
+                <Button x:Uid="LearnMore" Click="SWVersionButtonClicked" />
+            </InfoBar.ActionButton>
+        </InfoBar>
+
+        <ScrollViewer x:Name="MainScrollViewer" Grid.Row="1">
+            <StackPanel Padding="0,0,16,16" Orientation="Vertical">
+                <TextBlock
+                    x:Uid="EnabledModules"
+                    Margin="0,0,0,12"
+                    Style="{StaticResource SubtitleTextBlockStyle}" />
+                <ItemsRepeater x:Name="DashboardView" ItemsSource="{x:Bind ViewModel.ActiveModules, Mode=OneWay}">
+                    <ItemsRepeater.Layout>
+                        <controls:StaggeredLayout
+                            ColumnSpacing="8"
+                            DesiredColumnWidth="378"
+                            RowSpacing="8" />
+                    </ItemsRepeater.Layout>
+                    <ItemsRepeater.ItemTemplate>
+                        <DataTemplate x:DataType="viewmodels:DashboardListItem">
+                            <Grid
+                                Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
+                                BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
+                                BorderThickness="1"
+                                CornerRadius="{StaticResource OverlayCornerRadius}"
+                                RowSpacing="0">
+                                <Grid.RowDefinitions>
+                                    <RowDefinition />
+                                    <RowDefinition />
+                                </Grid.RowDefinitions>
+                                <Border Grid.RowSpan="2" Opacity="0.05">
+                                    <Border.Background>
+                                        <LinearGradientBrush StartPoint="0,0" EndPoint="1,3">
+                                            <GradientStop Offset="0.5" Color="{x:Bind AccentColor, Mode=OneWay}" />
+                                            <GradientStop Offset="0.9" Color="Transparent" />
+                                        </LinearGradientBrush>
+                                    </Border.Background>
+                                </Border>
+                                <Grid Margin="16,8,16,0" ColumnSpacing="12">
+                                    <Grid.ColumnDefinitions>
+                                        <ColumnDefinition Width="Auto" />
+                                        <ColumnDefinition Width="*" />
+                                        <ColumnDefinition Width="Auto" />
+                                        <ColumnDefinition Width="Auto" />
+                                    </Grid.ColumnDefinitions>
+                                    <Image Width="20" Margin="0,0,0,0">
+                                        <Image.Source>
+                                            <BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
+                                        </Image.Source>
+                                    </Image>
+                                    <TextBlock
+                                        Grid.Column="1"
+                                        VerticalAlignment="Center"
+                                        FontWeight="SemiBold"
+                                        Text="{x:Bind Label, Mode=OneWay}"
+                                        TextTrimming="CharacterEllipsis" />
+                                    <FontIcon
+                                        Grid.Column="2"
+                                        Width="20"
+                                        Margin="0,0,-12,0"
+                                        FontSize="16"
+                                        Glyph="&#xE72E;"
+                                        Visibility="{x:Bind IsLocked, Converter={StaticResource BoolToInvertedVisibilityConverter}, ConverterParameter=True, Mode=OneWay}">
+                                        <ToolTipService.ToolTip>
+                                            <TextBlock x:Uid="GPO_IsSettingForcedText" TextWrapping="WrapWholeWords" />
+                                        </ToolTipService.ToolTip>
+                                    </FontIcon>
+                                    <ToggleSwitch
+                                        Grid.Column="3"
+                                        Margin="0,-2,0,0"
+                                        HorizontalAlignment="Right"
+                                        IsEnabled="{x:Bind IsLocked, Converter={StaticResource BoolNegationConverter}, ConverterParameter=True, Mode=OneWay}"
+                                        IsOn="{x:Bind IsEnabled, Mode=TwoWay}"
+                                        OffContent=""
+                                        OnContent=""
+                                        Style="{StaticResource RightAlignedCompactToggleSwitchStyle}" />
+                                </Grid>
+
+                                <ItemsControl
+                                    Grid.Row="1"
+                                    Margin="16,8,16,16"
+                                    ItemTemplateSelector="{StaticResource ModuleItemTemplateSelector}"
+                                    ItemsSource="{x:Bind DashboardModuleItems, Mode=OneWay}"
+                                    Visibility="{x:Bind IsEnabled, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}">
+                                    <ItemsControl.ItemsPanel>
+                                        <ItemsPanelTemplate>
+                                            <StackPanel Spacing="4" />
+                                        </ItemsPanelTemplate>
+                                    </ItemsControl.ItemsPanel>
+                                </ItemsControl>
+                            </Grid>
+                        </DataTemplate>
+                    </ItemsRepeater.ItemTemplate>
+                </ItemsRepeater>
+
+                <TextBlock
+                    x:Uid="DisabledModules"
+                    Margin="0,24,0,12"
+                    Style="{StaticResource SubtitleTextBlockStyle}" />
+
+                <ItemsRepeater ItemsSource="{x:Bind ViewModel.DisabledModules, Mode=OneWay}">
+                    <ItemsRepeater.Layout>
+                        <controls:StaggeredLayout
+                            ColumnSpacing="8"
+                            DesiredColumnWidth="378"
+                            RowSpacing="8" />
+                    </ItemsRepeater.Layout>
+                    <ItemsRepeater.ItemTemplate>
+                        <DataTemplate x:DataType="viewmodels:DashboardListItem">
+                            <Grid
+                                Padding="16,12"
+                                Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
+                                BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
+                                BorderThickness="1"
+                                CornerRadius="{StaticResource OverlayCornerRadius}"
+                                RowSpacing="12">
+                                <Grid ColumnSpacing="12">
+                                    <Grid.ColumnDefinitions>
+                                        <ColumnDefinition Width="Auto" />
+                                        <ColumnDefinition Width="*" />
+                                        <ColumnDefinition Width="Auto" />
+                                        <ColumnDefinition Width="Auto" />
+                                    </Grid.ColumnDefinitions>
+                                    <Image Width="20">
+                                        <Image.Source>
+                                            <BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
+                                        </Image.Source>
+                                    </Image>
+                                    <TextBlock
+                                        Grid.Column="1"
+                                        VerticalAlignment="Center"
+                                        FontWeight="SemiBold"
+                                        Text="{x:Bind Label, Mode=OneWay}"
+                                        TextTrimming="CharacterEllipsis" />
+                                    <FontIcon
+                                        Grid.Column="2"
+                                        Width="20"
+                                        Margin="0,0,-12,0"
+                                        FontSize="16"
+                                        Glyph="&#xE72E;"
+                                        Visibility="{x:Bind IsLocked, Converter={StaticResource BoolToInvertedVisibilityConverter}, ConverterParameter=True, Mode=OneWay}">
+                                        <ToolTipService.ToolTip>
+                                            <TextBlock x:Uid="GPO_IsSettingForcedText" TextWrapping="WrapWholeWords" />
+                                        </ToolTipService.ToolTip>
+                                    </FontIcon>
+                                    <ToggleSwitch
+                                        Grid.Column="3"
+                                        Margin="0,-2,0,0"
+                                        HorizontalAlignment="Right"
+                                        IsEnabled="{x:Bind IsLocked, Converter={StaticResource BoolNegationConverter}, ConverterParameter=True, Mode=OneWay}"
+                                        IsOn="{x:Bind IsEnabled, Mode=TwoWay}"
+                                        OffContent=""
+                                        OnContent=""
+                                        Style="{StaticResource RightAlignedCompactToggleSwitchStyle}" />
+                                </Grid>
+                            </Grid>
+                        </DataTemplate>
+                    </ItemsRepeater.ItemTemplate>
+                </ItemsRepeater>
+            </StackPanel>
+
+        </ScrollViewer>
+    </Grid>
+</Page>
\ No newline at end of file
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs
new file mode 100644
index 000000000000..26f472744178
--- /dev/null
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs
@@ -0,0 +1,58 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using ManagedCommon;
+using Microsoft.PowerToys.Settings.UI.Helpers;
+using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.PowerToys.Settings.UI.OOBE.Views;
+using Microsoft.PowerToys.Settings.UI.ViewModels;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Windows.Storage.Pickers;
+
+namespace Microsoft.PowerToys.Settings.UI.Views
+{
+    /// <summary>
+    /// Dashboard Settings Page.
+    /// </summary>
+    public sealed partial class DashboardPage : Page, IRefreshablePage
+    {
+        /// <summary>
+        /// Gets or sets view model.
+        /// </summary>
+        public DashboardViewModel ViewModel { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DashboardPage"/> class.
+        /// Dashboard Settings page constructor.
+        /// </summary>
+        public DashboardPage()
+        {
+            InitializeComponent();
+            var settingsUtils = new SettingsUtils();
+
+            ViewModel = new DashboardViewModel(
+               SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
+            DataContext = ViewModel;
+        }
+
+        public void RefreshEnabledState()
+        {
+            ViewModel.ModuleEnabledChangedOnSettingsPage();
+        }
+
+        private void SWVersionButtonClicked(object sender, RoutedEventArgs e)
+        {
+            ViewModel.SWVersionButtonClicked();
+        }
+
+        private void SettingsButtonClicked(object sender, RoutedEventArgs e)
+        {
+            ViewModel.SettingsButtonClicked(sender);
+        }
+    }
+}
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml.cs
index eabe0ff2dbea..9d8496820632 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml.cs
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml.cs
@@ -73,7 +73,7 @@ private static void CombineRemappings(List<KeysDataModel> remapKeysList, uint le
             }
         }
 
-        private int FilterRemapKeysList(List<KeysDataModel> remapKeysList)
+        public static int FilterRemapKeysList(List<KeysDataModel> remapKeysList)
         {
             if (remapKeysList != null)
             {
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml
index c0b12c89143d..817b40b94ba5 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml
@@ -85,10 +85,16 @@
                 <SolidColorBrush x:Key="NavigationViewContentGridBorderBrush" Color="Transparent" />
             </NavigationView.Resources>
             <NavigationView.MenuItems>
+                <NavigationViewItem
+                    x:Uid="Shell_Dashboard"
+                    helpers:NavHelper.NavigateTo="views:DashboardPage"
+                    Icon="{ui:FontIcon Glyph=&#xE80F;}" />
+
                 <NavigationViewItem
                     x:Uid="Shell_General"
                     helpers:NavHelper.NavigateTo="views:GeneralPage"
-                    Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsSettings.png}" />
+                    Icon="{ui:FontIcon Glyph=&#xE713;}" />
+                <NavigationViewItemSeparator />
 
                 <NavigationViewItem
                     x:Uid="Shell_AlwaysOnTop"
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs
index 1892091d9a6f..3fc3c1a39e60 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs
@@ -236,7 +236,7 @@ public static void Navigate(Type type)
 
         public void Refresh()
         {
-            shellFrame.Navigate(typeof(GeneralPage));
+            shellFrame.Navigate(typeof(DashboardPage));
         }
 
         // Tell the current page view model to update
@@ -361,7 +361,7 @@ private void ReceiveMessage(JsonObject json)
 
         internal static void EnsurePageIsSelected()
         {
-            NavigationService.EnsurePageIsSelected(typeof(GeneralPage));
+            NavigationService.EnsurePageIsSelected(typeof(DashboardPage));
         }
 
         private void SetTitleBar()
diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw
index 94d256bbdb45..02c94f968318 100644
--- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw
+++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw
@@ -928,7 +928,10 @@
     <value>This overrides the Windows Snap shortcut (Win + arrow) to move windows between zones</value>
   </data>
   <data name="FancyZones_ShiftDragCheckBoxControl_Header.Content" xml:space="preserve">
-    <value>Hold Shift key to activate zones while dragging</value>
+    <value>Hold Shift key to activate zones while dragging a window</value>
+  </data>
+  <data name="FancyZones_ActivationNoShiftDrag" xml:space="preserve">
+    <value>Drag windows to activate zones</value>
   </data>
   <data name="FancyZones_ShowZonesOnAllMonitorsCheckBoxControl.Content" xml:space="preserve">
     <value>Show zones on all monitors while dragging a window</value>
@@ -2716,6 +2719,9 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
   <data name="VideoConference_DeprecationWarningButton.Content" xml:space="preserve">
     <value>Learn more</value>
   </data>
+  <data name="LearnMore.Content" xml:space="preserve">
+    <value>Learn more</value>
+  </data>
   <data name="VideoConference_RunAsAdminRequired.Title" xml:space="preserve">
     <value>You need to run as administrator to modify these settings.</value>
   </data>
@@ -2991,6 +2997,78 @@ Activate by holding the key for the character you want to add an accent to, then
   <data name="QuickAccent.SecondaryLinksHeader" xml:space="preserve">
     <value>Attribution</value>
   </data>
+  <data name="AlwaysOnTop_ShortDescription" xml:space="preserve">
+    <value>Pin a window</value>
+  </data>
+  <data name="Awake_ShortDescription" xml:space="preserve">
+    <value>Keep your PC awake</value>
+  </data>
+  <data name="ColorPicker_ShortDescription" xml:space="preserve">
+    <value>Pick a color</value>
+  </data>
+  <data name="CropAndLock_Thumbnail" xml:space="preserve">
+    <value>Thumbnail</value>
+  </data>
+  <data name="CropAndLock_Reparent" xml:space="preserve">
+    <value>Reparent</value>
+  </data>
+  <data name="FancyZones_OpenEditor" xml:space="preserve">
+    <value>Open editor</value>
+  </data>
+  <data name="FileLocksmith_ShortDescription" xml:space="preserve">
+    <value>Right-click on files or directories to show running processes</value>
+  </data>
+  <data name="FindMyMouse_ShortDescription" xml:space="preserve">
+    <value>Find the mouse</value>
+  </data>
+  <data name="ImageResizer_ShortDescription" xml:space="preserve">
+    <value>Select Image Resizer in the right-click context menu</value>
+  </data>
+  <data name="MouseHighlighter_ShortDescription" xml:space="preserve">
+    <value>Highlight clicks</value>
+  </data>
+  <data name="MouseJump_ShortDescription" xml:space="preserve">
+    <value>Quickly move the mouse pointer</value>
+  </data>
+  <data name="MouseCrosshairs_ShortDescription" xml:space="preserve">
+    <value>Draw crosshairs centered on the mouse pointer</value>
+  </data>
+  <data name="MouseWithoutBorders_ShortDescription" xml:space="preserve">
+    <value>Move your cursor across multiple devices</value>
+  </data>
+  <data name="PastePlain_ShortDescription" xml:space="preserve">
+    <value>Paste clipboard content without formatting</value>
+  </data>
+  <data name="Peek_ShortDescription" xml:space="preserve">
+    <value>Quick and easy previewer</value>
+  </data>
+  <data name="PowerRename_ShortDescription" xml:space="preserve">
+    <value>Select Power Rename in right-click context menu</value>
+  </data>
+  <data name="Run_ShortDescription" xml:space="preserve">
+    <value>A quick launcher</value>
+  </data>
+  <data name="PowerAccent_ShortDescription" xml:space="preserve">
+    <value>An alternative way to type accented characters</value>
+  </data>
+  <data name="RegistryPreview_ShortDescription" xml:space="preserve">
+    <value>Visualize and edit Windows Registry files</value>
+  </data>
+  <data name="ScreenRuler_ShortDescription" xml:space="preserve">
+    <value>Measure pixels on your screen</value>
+  </data>
+  <data name="ShortcutGuide_ShortDescription" xml:space="preserve">
+    <value>Show a help overlay with Windows shortcuts</value>
+  </data>
+  <data name="PowerOcr_ShortDescription" xml:space="preserve">
+    <value>A convenient way to copy text from anywhere on screen</value>
+  </data>
+  <data name="Dashboard_Activation" xml:space="preserve">
+    <value>Activation</value>
+  </data>
+  <data name="DashboardKBMShowMappingsButton.Content" xml:space="preserve">
+    <value>Show remappings</value>
+  </data>
   <data name="Oobe_QuickAccent.Description" xml:space="preserve">
     <value>Quick Accent is an easy way to write letters with accents, like on a smartphone.</value>
   </data>
@@ -3415,7 +3493,7 @@ Activate by holding the key for the character you want to add an accent to, then
     <comment>This refers to directly integrating in with Windows</comment>
   </data>
   <data name="GPO_IsSettingForced.Title" xml:space="preserve">
-    <value>The system administrator is forcing this setting.</value>
+    <value>This setting is enforced by your System Administrator.</value>
   </data>
   <data name="Hosts_AdditionalLinesPosition.Description" xml:space="preserve">
     <value>Additional content includes the file header and lines that can't parse</value>
@@ -3703,4 +3781,19 @@ Activate by holding the key for the character you want to add an accent to, then
     <value>Administrator: PowerToys Settings</value>
     <comment>Title of the settings window when running as administrator</comment>
   </data>
+  <data name="DashboardTitle.Text" xml:space="preserve">
+    <value>Dashboard</value>
+  </data>
+  <data name="Shell_Dashboard.Content" xml:space="preserve">
+    <value>Dashboard</value>
+  </data>
+  <data name="GPO_IsSettingForcedText.Text" xml:space="preserve">
+    <value>This setting is enforced by your System Administrator.</value>
+  </data>
+  <data name="DisabledModules.Text" xml:space="preserve">
+    <value>Disabled modules</value>
+  </data>
+  <data name="EnabledModules.Text" xml:space="preserve">
+    <value>Enabled modules</value>
+  </data>
 </root>
\ No newline at end of file
diff --git a/src/settings-ui/Settings.UI/ViewModels/DashboardListItem.cs b/src/settings-ui/Settings.UI/ViewModels/DashboardListItem.cs
new file mode 100644
index 000000000000..1efe8257d053
--- /dev/null
+++ b/src/settings-ui/Settings.UI/ViewModels/DashboardListItem.cs
@@ -0,0 +1,69 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using Microsoft.UI;
+using Windows.UI;
+
+namespace Microsoft.PowerToys.Settings.UI.ViewModels
+{
+    public class DashboardListItem : INotifyPropertyChanged
+    {
+        private bool _visible;
+        private bool _isEnabled;
+
+        public string Label { get; set; }
+
+        public string Icon { get; set; }
+
+        public string ToolTip { get; set; }
+
+        public string Tag { get; set; }
+
+        public Color AccentColor { get; set; } = Colors.Transparent;
+
+        public bool IsLocked { get; set; }
+
+        public bool IsEnabled
+        {
+            get => _isEnabled;
+            set
+            {
+                if (_isEnabled != value)
+                {
+                    _isEnabled = value;
+                    OnPropertyChanged();
+                    EnabledChangedCallback?.Invoke(this);
+                }
+            }
+        }
+
+        public Action<DashboardListItem> EnabledChangedCallback { get; set; }
+
+        public bool Visible
+        {
+            get => _visible;
+            set
+            {
+                if (_visible != value)
+                {
+                    _visible = value;
+                    OnPropertyChanged();
+                }
+            }
+        }
+
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+        }
+
+        public ObservableCollection<DashboardModuleItem> DashboardModuleItems { get; set; } = new ObservableCollection<DashboardModuleItem>();
+    }
+}
diff --git a/src/settings-ui/Settings.UI/ViewModels/DashboardModuleItem.cs b/src/settings-ui/Settings.UI/ViewModels/DashboardModuleItem.cs
new file mode 100644
index 000000000000..5032abe999a4
--- /dev/null
+++ b/src/settings-ui/Settings.UI/ViewModels/DashboardModuleItem.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.UI.Xaml;
+using Windows.UI;
+
+namespace Microsoft.PowerToys.Settings.UI.ViewModels
+{
+#pragma warning disable SA1402 // File may only contain a single type
+#pragma warning disable SA1649 // File name should match first type name
+    public class DashboardModuleTextItem : DashboardModuleItem
+    {
+    }
+
+    public class DashboardModuleButtonItem : DashboardModuleItem
+    {
+        public string ButtonTitle { get; set; }
+
+        public bool IsButtonDescriptionVisible { get; set; }
+
+        public string ButtonDescription { get; set; }
+
+        public string ButtonGlyph { get; set; }
+
+        public RoutedEventHandler ButtonClickHandler { get; set; }
+    }
+
+    public class DashboardModuleShortcutItem : DashboardModuleItem
+    {
+        public List<object> Shortcut { get; set; }
+    }
+
+    public class DashboardModuleKBMItem : DashboardModuleItem
+    {
+        private List<KeysDataModel> _remapKeys = new List<KeysDataModel>();
+
+        public List<KeysDataModel> RemapKeys
+        {
+            get => _remapKeys;
+            set => _remapKeys = value;
+        }
+
+        private List<AppSpecificKeysDataModel> _remapShortcuts = new List<AppSpecificKeysDataModel>();
+
+        public List<AppSpecificKeysDataModel> RemapShortcuts
+        {
+            get => _remapShortcuts;
+            set => _remapShortcuts = value;
+        }
+    }
+
+    public class DashboardModuleItem : INotifyPropertyChanged
+    {
+        public string Label { get; set; }
+
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        internal void NotifyPropertyChanged(string propertyName)
+        {
+            OnPropertyChanged(propertyName);
+        }
+
+        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+        }
+    }
+}
+#pragma warning restore SA1402 // File may only contain a single type
+#pragma warning restore SA1649 // File name should match first type name
diff --git a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs
new file mode 100644
index 000000000000..eedb55760f91
--- /dev/null
+++ b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs
@@ -0,0 +1,803 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO.Abstractions;
+using System.Linq;
+using System.Windows.Threading;
+using global::PowerToys.GPOWrapper;
+using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.PowerToys.Settings.UI.Library.Helpers;
+using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
+using Microsoft.PowerToys.Settings.UI.Services;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Windows.UI;
+
+namespace Microsoft.PowerToys.Settings.UI.ViewModels
+{
+    public class DashboardViewModel : Observable
+    {
+        private const string JsonFileType = ".json";
+        private readonly IFileSystemWatcher _watcher;
+        private DashboardModuleKBMItem _kbmItem;
+        private Dispatcher dispatcher;
+
+        public Func<string, int> SendConfigMSG { get; }
+
+        public ObservableCollection<DashboardListItem> ActiveModules { get; set; } = new ObservableCollection<DashboardListItem>();
+
+        public ObservableCollection<DashboardListItem> DisabledModules { get; set; } = new ObservableCollection<DashboardListItem>();
+
+        public bool UpdateAvailable { get; set; }
+
+        private List<DashboardListItem> _allModules;
+
+        private ISettingsRepository<GeneralSettings> _settingsRepository;
+        private GeneralSettings generalSettingsConfig;
+        private Windows.ApplicationModel.Resources.ResourceLoader resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
+
+        public DashboardViewModel(ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc)
+        {
+            dispatcher = Dispatcher.CurrentDispatcher;
+            _settingsRepository = settingsRepository;
+            generalSettingsConfig = settingsRepository.SettingsConfig;
+            generalSettingsConfig.AddEnabledModuleChangeNotification(ModuleEnabledChangedOnSettingsPage);
+
+            // set the callback functions value to hangle outgoing IPC message.
+            SendConfigMSG = ipcMSGCallBackFunc;
+
+            _allModules = new List<DashboardListItem>();
+
+            GpoRuleConfigured gpo;
+            gpo = GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "AlwaysOnTop",
+                Label = resourceLoader.GetString("AlwaysOnTop/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.AlwaysOnTop),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsAlwaysOnTop.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 74, 196, 242), // #4ac4f2
+                DashboardModuleItems = GetModuleItemsAlwaysOnTop(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredAwakeEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "Awake",
+                Label = resourceLoader.GetString("Awake/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.Awake),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsAwake.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 40, 177, 233), // #28b1e9
+                DashboardModuleItems = GetModuleItemsAwake(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredColorPickerEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "ColorPicker",
+                Label = resourceLoader.GetString("ColorPicker/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.ColorPicker),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsColorPicker.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 7, 129, 211), // #0781d3
+                DashboardModuleItems = GetModuleItemsColorPicker(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredCropAndLockEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "CropAndLock",
+                Label = resourceLoader.GetString("CropAndLock/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.CropAndLock),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsCropAndLock.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 32, 166, 228), // #20a6e4
+                DashboardModuleItems = GetModuleItemsCropAndLock(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredFancyZonesEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "FancyZones",
+                Label = resourceLoader.GetString("FancyZones/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.FancyZones),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsFancyZones.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 65, 209, 247), // #41d1f7
+                DashboardModuleItems = GetModuleItemsFancyZones(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredFileLocksmithEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "FileLocksmith",
+                Label = resourceLoader.GetString("FileLocksmith/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.FileLocksmith),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsFileLocksmith.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 245, 161, 20), // #f5a114
+                DashboardModuleItems = GetModuleItemsFileLocksmith(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredFindMyMouseEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "FindMyMouse",
+                Label = resourceLoader.GetString("MouseUtils_FindMyMouse/Header"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.FindMyMouse),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsFindMyMouse.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 104, 109, 112), // #686d70
+                DashboardModuleItems = GetModuleItemsFindMyMouse(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredHostsFileEditorEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "Hosts",
+                Label = resourceLoader.GetString("Hosts/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.Hosts),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsHosts.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 16, 132, 208), // #1084d0
+                DashboardModuleItems = GetModuleItemsHosts(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredImageResizerEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "ImageResizer",
+                Label = resourceLoader.GetString("ImageResizer/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.ImageResizer),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsImageResizer.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 85, 207, 248), // #55cff8
+                DashboardModuleItems = GetModuleItemsImageResizer(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredKeyboardManagerEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "KeyboardManager",
+                Label = resourceLoader.GetString("KeyboardManager/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.KeyboardManager),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsKeyboardManager.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 224, 231, 238), // #e0e7ee
+                DashboardModuleItems = GetModuleItemsKeyboardManager(),
+            });
+
+            if (gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.KeyboardManager))
+            {
+                KeyboardManagerSettings kbmSettings = GetKBMSettings();
+                _watcher = Library.Utilities.Helper.GetFileWatcher(KeyboardManagerSettings.ModuleName, kbmSettings.Properties.ActiveConfiguration.Value + JsonFileType, () => LoadKBMSettingsFromJson());
+            }
+
+            gpo = GPOWrapper.GetConfiguredMouseHighlighterEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "MouseHighlighter",
+                Label = resourceLoader.GetString("MouseUtils_MouseHighlighter/Header"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.MouseHighlighter),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsMouseHighlighter.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 17, 126, 199), // #117ec7
+                DashboardModuleItems = GetModuleItemsMouseHighlighter(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredMouseJumpEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "MouseJump",
+                Label = resourceLoader.GetString("MouseUtils_MouseJump/Header"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.MouseJump),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsMouseJump.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 240, 240, 239), // #f0f0ef
+                DashboardModuleItems = GetModuleItemsMouseJump(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "MousePointerCrosshairs",
+                Label = resourceLoader.GetString("MouseUtils_MousePointerCrosshairs/Header"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.MousePointerCrosshairs),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsMouseCrosshairs.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 25, 115, 182), // #1973b6
+                DashboardModuleItems = GetModuleItemsMouseCrosshairs(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "MouseWithoutBorders",
+                Label = resourceLoader.GetString("MouseWithoutBorders/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.MouseWithoutBorders),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsMouseWithoutBorders.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 31, 164, 227), // #1fa4e3
+                DashboardModuleItems = GetModuleItemsMouseWithoutBorders(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredPastePlainEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "PastePlain",
+                Label = resourceLoader.GetString("PastePlain/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.PastePlain),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsPastePlain.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 243, 156, 16), // #f39c10
+                DashboardModuleItems = GetModuleItemsPastePlain(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredPeekEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "Peek",
+                Label = resourceLoader.GetString("Peek/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.Peek),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsPeek.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 255, 214, 103), // #ffd667
+                DashboardModuleItems = GetModuleItemsPeek(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredPowerRenameEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "PowerRename",
+                Label = resourceLoader.GetString("PowerRename/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.PowerRename),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsPowerRename.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 43, 186, 243), // #2bbaf3
+                DashboardModuleItems = GetModuleItemsPowerRename(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredPowerLauncherEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "PowerLauncher",
+                Label = resourceLoader.GetString("PowerLauncher/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.PowerLauncher),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsPowerToysRun.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 51, 191, 240), // #33bff0
+                DashboardModuleItems = GetModuleItemsRun(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredQuickAccentEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "PowerAccent",
+                Label = resourceLoader.GetString("QuickAccent/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.PowerAccent),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsPowerAccent.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 84, 89, 92), // #54595c
+                DashboardModuleItems = GetModuleItemsPowerAccent(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredRegistryPreviewEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "RegistryPreview",
+                Label = resourceLoader.GetString("RegistryPreview/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.RegistryPreview),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsRegistryPreview.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 17, 80, 138), // #11508a
+                DashboardModuleItems = GetModuleItemsRegistryPreview(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredScreenRulerEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "MeasureTool",
+                Label = resourceLoader.GetString("MeasureTool/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.MeasureTool),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsScreenRuler.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 135, 144, 153), // #879099
+                DashboardModuleItems = GetModuleItemsScreenRuler(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredShortcutGuideEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "ShortcutGuide",
+                Label = resourceLoader.GetString("ShortcutGuide/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.ShortcutGuide),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsShortcutGuide.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 193, 202, 209), // #c1cad1
+                DashboardModuleItems = GetModuleItemsShortcutGuide(),
+            });
+
+            gpo = GPOWrapper.GetConfiguredTextExtractorEnabledValue();
+            _allModules.Add(new DashboardListItem()
+            {
+                Tag = "PowerOCR",
+                Label = resourceLoader.GetString("TextExtractor/ModuleTitle"),
+                IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && generalSettingsConfig.Enabled.PowerOCR),
+                IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
+                Icon = "ms-appx:///Assets/Settings/FluentIcons/FluentIconsPowerOCR.png",
+                EnabledChangedCallback = EnabledChangedOnUI,
+                AccentColor = Color.FromArgb(255, 24, 153, 224), // #1899e0
+                DashboardModuleItems = GetModuleItemsPowerOCR(),
+            });
+
+            ActiveModules = new ObservableCollection<DashboardListItem>(_allModules.Where(x => x.IsEnabled));
+            DisabledModules = new ObservableCollection<DashboardListItem>(_allModules.Where(x => !x.IsEnabled));
+
+            UpdatingSettings updatingSettingsConfig = UpdatingSettings.LoadSettings();
+            UpdateAvailable = updatingSettingsConfig != null && (updatingSettingsConfig.State == UpdatingSettings.UpdatingState.ReadyToInstall || updatingSettingsConfig.State == UpdatingSettings.UpdatingState.ReadyToDownload);
+        }
+
+        private void LoadKBMSettingsFromJson()
+        {
+            KeyboardManagerProfile kbmProfile = GetKBMProfile();
+            _kbmItem.RemapKeys = kbmProfile?.RemapKeys.InProcessRemapKeys;
+            _kbmItem.RemapShortcuts = KeyboardManagerViewModel.CombineShortcutLists(kbmProfile?.RemapShortcuts.GlobalRemapShortcuts, kbmProfile?.RemapShortcuts.AppSpecificRemapShortcuts);
+            dispatcher.Invoke(new Action(() => UpdateKBMItems()));
+        }
+
+        private void UpdateKBMItems()
+        {
+            _kbmItem.NotifyPropertyChanged(nameof(_kbmItem.RemapKeys));
+            _kbmItem.NotifyPropertyChanged(nameof(_kbmItem.RemapShortcuts));
+        }
+
+        private KeyboardManagerProfile GetKBMProfile()
+        {
+            KeyboardManagerSettings kbmSettings = GetKBMSettings();
+            const string PowerToyName = KeyboardManagerSettings.ModuleName;
+            string fileName = kbmSettings.Properties.ActiveConfiguration.Value + JsonFileType;
+            return new SettingsUtils().GetSettingsOrDefault<KeyboardManagerProfile>(PowerToyName, fileName);
+        }
+
+        private KeyboardManagerSettings GetKBMSettings()
+        {
+            var settingsUtils = new SettingsUtils();
+            ISettingsRepository<KeyboardManagerSettings> moduleSettingsRepository = SettingsRepository<KeyboardManagerSettings>.GetInstance(settingsUtils);
+            return moduleSettingsRepository.SettingsConfig;
+        }
+
+        internal void SettingsButtonClicked(object sender)
+        {
+            Button button = sender as Button;
+            if (button == null)
+            {
+                return;
+            }
+
+            string tag = button.Tag as string;
+            if (tag == null)
+            {
+                return;
+            }
+
+            Type type = null;
+            switch (tag)
+            {
+                case "AlwaysOnTop": type = typeof(AlwaysOnTopPage); break;
+                case "Awake": type = typeof(AwakePage); break;
+                case "ColorPicker": type = typeof(ColorPickerPage); break;
+                case "CropAndLock": type = typeof(CropAndLockPage); break;
+                case "FancyZones": type = typeof(FancyZonesPage); break;
+                case "FileLocksmith": type = typeof(FileLocksmithPage); break;
+                case "FindMyMouse": type = typeof(MouseUtilsPage); break;
+                case "Hosts": type = typeof(HostsPage); break;
+                case "ImageResizer": type = typeof(ImageResizerPage); break;
+                case "KeyboardManager": type = typeof(KeyboardManagerPage); break;
+                case "MouseHighlighter": type = typeof(MouseUtilsPage); break;
+                case "MouseJump": type = typeof(MouseUtilsPage); break;
+                case "MousePointerCrosshairs": type = typeof(MouseUtilsPage); break;
+                case "MouseWithoutBorders": type = typeof(MouseWithoutBordersPage); break;
+                case "PastePlain": type = typeof(PastePlainPage); break;
+                case "Peek": type = typeof(PeekPage); break;
+                case "PowerRename": type = typeof(PowerRenamePage); break;
+                case "PowerLauncher": type = typeof(PowerLauncherPage); break;
+                case "PowerAccent": type = typeof(PowerAccentPage); break;
+                case "RegistryPreview": type = typeof(RegistryPreviewPage); break;
+                case "MeasureTool": type = typeof(MeasureToolPage); break;
+                case "ShortcutGuide": type = typeof(ShortcutGuidePage); break;
+                case "PowerOCR": type = typeof(PowerOcrPage); break;
+                case "VideoConference": type = typeof(VideoConferencePage); break;
+            }
+
+            NavigationService.Navigate(type);
+        }
+
+        private void EnabledChangedOnUI(DashboardListItem dashboardListItem)
+        {
+            Views.ShellPage.UpdateGeneralSettingsCallback(dashboardListItem.Tag, dashboardListItem.IsEnabled);
+        }
+
+        public void ModuleEnabledChangedOnSettingsPage()
+        {
+            ActiveModules.Clear();
+            DisabledModules.Clear();
+            generalSettingsConfig = _settingsRepository.SettingsConfig;
+            foreach (DashboardListItem item in _allModules)
+            {
+                switch (item.Tag)
+                {
+                    case "AlwaysOnTop": item.IsEnabled = generalSettingsConfig.Enabled.AlwaysOnTop; break;
+                    case "Awake": item.IsEnabled = generalSettingsConfig.Enabled.Awake; break;
+                    case "ColorPicker": item.IsEnabled = generalSettingsConfig.Enabled.ColorPicker; break;
+                    case "CropAndLock": item.IsEnabled = generalSettingsConfig.Enabled.CropAndLock; break;
+                    case "FancyZones": item.IsEnabled = generalSettingsConfig.Enabled.FancyZones; break;
+                    case "FileLocksmith": item.IsEnabled = generalSettingsConfig.Enabled.FileLocksmith; break;
+                    case "FindMyMouse": item.IsEnabled = generalSettingsConfig.Enabled.FindMyMouse; break;
+                    case "Hosts": item.IsEnabled = generalSettingsConfig.Enabled.Hosts; break;
+                    case "ImageResizer": item.IsEnabled = generalSettingsConfig.Enabled.ImageResizer; break;
+                    case "KeyboardManager": item.IsEnabled = generalSettingsConfig.Enabled.KeyboardManager; break;
+                    case "MouseHighlighter": item.IsEnabled = generalSettingsConfig.Enabled.MouseHighlighter; break;
+                    case "MouseJump": item.IsEnabled = generalSettingsConfig.Enabled.MouseJump; break;
+                    case "MousePointerCrosshairs": item.IsEnabled = generalSettingsConfig.Enabled.MousePointerCrosshairs; break;
+                    case "MouseWithoutBorders": item.IsEnabled = generalSettingsConfig.Enabled.MouseWithoutBorders; break;
+                    case "PastePlain": item.IsEnabled = generalSettingsConfig.Enabled.PastePlain; break;
+                    case "Peek": item.IsEnabled = generalSettingsConfig.Enabled.Peek; break;
+                    case "PowerRename": item.IsEnabled = generalSettingsConfig.Enabled.PowerRename; break;
+                    case "PowerLauncher": item.IsEnabled = generalSettingsConfig.Enabled.PowerLauncher; break;
+                    case "PowerAccent": item.IsEnabled = generalSettingsConfig.Enabled.PowerAccent; break;
+                    case "RegistryPreview": item.IsEnabled = generalSettingsConfig.Enabled.RegistryPreview; break;
+                    case "MeasureTool": item.IsEnabled = generalSettingsConfig.Enabled.MeasureTool; break;
+                    case "ShortcutGuide": item.IsEnabled = generalSettingsConfig.Enabled.ShortcutGuide; break;
+                    case "PowerOCR": item.IsEnabled = generalSettingsConfig.Enabled.PowerOCR; break;
+                    case "VideoConference": item.IsEnabled = generalSettingsConfig.Enabled.VideoConference; break;
+                }
+
+                if (item.IsEnabled)
+                {
+                    ActiveModules.Add(item);
+                }
+                else
+                {
+                    DisabledModules.Add(item);
+                }
+            }
+
+            OnPropertyChanged(nameof(ActiveModules));
+            OnPropertyChanged(nameof(DisabledModules));
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsAlwaysOnTop()
+        {
+            ISettingsRepository<AlwaysOnTopSettings> moduleSettingsRepository = SettingsRepository<AlwaysOnTopSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("AlwaysOnTop_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.Hotkey.Value.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsAwake()
+        {
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleTextItem() { Label = resourceLoader.GetString("Awake_ShortDescription") },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsColorPicker()
+        {
+            ISettingsRepository<ColorPickerSettings> moduleSettingsRepository = SettingsRepository<ColorPickerSettings>.GetInstance(new SettingsUtils());
+            var settings = moduleSettingsRepository.SettingsConfig;
+            var hotkey = settings.Properties.ActivationShortcut;
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("ColorPicker_ShortDescription"), Shortcut = hotkey.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsCropAndLock()
+        {
+            ISettingsRepository<CropAndLockSettings> moduleSettingsRepository = SettingsRepository<CropAndLockSettings>.GetInstance(new SettingsUtils());
+            var settings = moduleSettingsRepository.SettingsConfig;
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("CropAndLock_Thumbnail"), Shortcut = settings.Properties.ThumbnailHotkey.Value.GetKeysList() },
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("CropAndLock_Reparent"), Shortcut = settings.Properties.ReparentHotkey.Value.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsFancyZones()
+        {
+            ISettingsRepository<FancyZonesSettings> moduleSettingsRepository = SettingsRepository<FancyZonesSettings>.GetInstance(new SettingsUtils());
+            var settings = moduleSettingsRepository.SettingsConfig;
+            string activationMode = $"{resourceLoader.GetString(settings.Properties.FancyzonesShiftDrag.Value ? "FancyZones_ShiftDragCheckBoxControl_Header/Content" : "FancyZones_ActivationNoShiftDrag")}.";
+            if (settings.Properties.FancyzonesMouseSwitch.Value)
+            {
+                activationMode += $" {resourceLoader.GetString("FancyZones_MouseDragCheckBoxControl_Header/Content")}.";
+            }
+
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleTextItem() { Label = activationMode },
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("FancyZones_OpenEditor"), Shortcut = settings.Properties.FancyzonesEditorHotkey.Value.GetKeysList() },
+                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("FancyZones_LaunchEditorButtonControl/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("FancyZones_LaunchEditorButtonControl/Description"), ButtonGlyph = "\uEB3C", ButtonClickHandler = FancyZoneLaunchClicked },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsFileLocksmith()
+        {
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleTextItem() { Label = resourceLoader.GetString("FileLocksmith_ShortDescription") },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsFindMyMouse()
+        {
+            ISettingsRepository<FindMyMouseSettings> moduleSettingsRepository = SettingsRepository<FindMyMouseSettings>.GetInstance(new SettingsUtils());
+            string shortDescription = resourceLoader.GetString("FindMyMouse_ShortDescription");
+            var settings = moduleSettingsRepository.SettingsConfig;
+            var activationMethod = settings.Properties.ActivationMethod.Value;
+            var list = new List<DashboardModuleItem>();
+            if (activationMethod == 3)
+            {
+                var hotkey = settings.Properties.ActivationShortcut;
+                list.Add(new DashboardModuleShortcutItem() { Label = shortDescription, Shortcut = hotkey.GetKeysList() });
+            }
+            else
+            {
+                switch (activationMethod)
+                {
+                    case 2: shortDescription += $". {resourceLoader.GetString("Dashboard_Activation")}: {resourceLoader.GetString("MouseUtils_FindMyMouse_ActivationShakeMouse/Content")}"; break;
+                    case 1: shortDescription += $". {resourceLoader.GetString("Dashboard_Activation")}: {resourceLoader.GetString("MouseUtils_FindMyMouse_ActivationDoubleRightControlPress/Content")}"; break;
+                    case 0:
+                    default: shortDescription += $". {resourceLoader.GetString("Dashboard_Activation")}: {resourceLoader.GetString("MouseUtils_FindMyMouse_ActivationDoubleControlPress/Content")}"; break;
+                }
+
+                list.Add(new DashboardModuleTextItem() { Label = shortDescription });
+            }
+
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsHosts()
+        {
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("Hosts_LaunchButtonControl/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("Hosts_LaunchButtonControl/Description"), ButtonGlyph = "\uEA37", ButtonClickHandler = HostLaunchClicked },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsImageResizer()
+        {
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleTextItem() { Label = resourceLoader.GetString("ImageResizer_ShortDescription") },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsKeyboardManager()
+        {
+            KeyboardManagerProfile kbmProfile = GetKBMProfile();
+            _kbmItem = new DashboardModuleKBMItem() { RemapKeys = kbmProfile?.RemapKeys.InProcessRemapKeys, RemapShortcuts = KeyboardManagerViewModel.CombineShortcutLists(kbmProfile?.RemapShortcuts.GlobalRemapShortcuts, kbmProfile?.RemapShortcuts.AppSpecificRemapShortcuts) };
+            var list = new List<DashboardModuleItem>
+            {
+                _kbmItem,
+                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("KeyboardManager_RemapKeyboardButton/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("KeyboardManager_RemapKeyboardButton/Description"), ButtonGlyph = "\uE92E", ButtonClickHandler = KbmKeyLaunchClicked },
+                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("KeyboardManager_RemapShortcutsButton/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("KeyboardManager_RemapShortcutsButton/Description"), ButtonGlyph = "\uE92E", ButtonClickHandler = KbmShortcutLaunchClicked },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsMouseHighlighter()
+        {
+            ISettingsRepository<MouseHighlighterSettings> moduleSettingsRepository = SettingsRepository<MouseHighlighterSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("MouseHighlighter_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsMouseJump()
+        {
+            ISettingsRepository<MouseJumpSettings> moduleSettingsRepository = SettingsRepository<MouseJumpSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("MouseJump_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsMouseCrosshairs()
+        {
+            ISettingsRepository<MousePointerCrosshairsSettings> moduleSettingsRepository = SettingsRepository<MousePointerCrosshairsSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("MouseCrosshairs_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsMouseWithoutBorders()
+        {
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleTextItem() { Label = resourceLoader.GetString("MouseWithoutBorders_ShortDescription") },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsPastePlain()
+        {
+            ISettingsRepository<PastePlainSettings> moduleSettingsRepository = SettingsRepository<PastePlainSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PastePlain_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsPeek()
+        {
+            ISettingsRepository<PeekSettings> moduleSettingsRepository = SettingsRepository<PeekSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("Peek_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsPowerRename()
+        {
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleTextItem() { Label = resourceLoader.GetString("PowerRename_ShortDescription") },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsRun()
+        {
+            ISettingsRepository<PowerLauncherSettings> moduleSettingsRepository = SettingsRepository<PowerLauncherSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("Run_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.OpenPowerLauncher.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsPowerAccent()
+        {
+            string shortDescription = resourceLoader.GetString("PowerAccent_ShortDescription");
+            var settingsUtils = new SettingsUtils();
+            PowerAccentSettings moduleSettings = settingsUtils.GetSettingsOrDefault<PowerAccentSettings>(PowerAccentSettings.ModuleName);
+            var activationMethod = moduleSettings.Properties.ActivationKey;
+            switch (activationMethod)
+            {
+                case Library.Enumerations.PowerAccentActivationKey.LeftRightArrow: shortDescription += $". {resourceLoader.GetString("Dashboard_Activation")}: {resourceLoader.GetString("QuickAccent_Activation_Key_Arrows/Content")}"; break;
+                case Library.Enumerations.PowerAccentActivationKey.Space: shortDescription += $". {resourceLoader.GetString("Dashboard_Activation")}: {resourceLoader.GetString("QuickAccent_Activation_Key_Space/Content")}"; break;
+                case Library.Enumerations.PowerAccentActivationKey.Both: shortDescription += $". {resourceLoader.GetString("Dashboard_Activation")}: {resourceLoader.GetString("QuickAccent_Activation_Key_Either/Content")}"; break;
+            }
+
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleTextItem() { Label = shortDescription },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsRegistryPreview()
+        {
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("RegistryPreview_LaunchButtonControl/Header"), ButtonGlyph = "\uEA37",  ButtonClickHandler = RegistryPreviewLaunchClicked },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsScreenRuler()
+        {
+            ISettingsRepository<MeasureToolSettings> moduleSettingsRepository = SettingsRepository<MeasureToolSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("ScreenRuler_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsShortcutGuide()
+        {
+            ISettingsRepository<ShortcutGuideSettings> moduleSettingsRepository = SettingsRepository<ShortcutGuideSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("ShortcutGuide_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.OpenShortcutGuide.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        private ObservableCollection<DashboardModuleItem> GetModuleItemsPowerOCR()
+        {
+            ISettingsRepository<PowerOcrSettings> moduleSettingsRepository = SettingsRepository<PowerOcrSettings>.GetInstance(new SettingsUtils());
+            var list = new List<DashboardModuleItem>
+            {
+                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PowerOcr_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
+            };
+            return new ObservableCollection<DashboardModuleItem>(list);
+        }
+
+        internal void SWVersionButtonClicked()
+        {
+            NavigationService.Navigate(typeof(GeneralPage));
+        }
+
+        private void HostLaunchClicked(object sender, RoutedEventArgs e)
+        {
+            var settingsUtils = new SettingsUtils();
+            var hostsViewModel = new HostsViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<HostsSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated);
+            hostsViewModel.Launch();
+        }
+
+        private void FancyZoneLaunchClicked(object sender, RoutedEventArgs e)
+        {
+            // send message to launch the zones editor;
+            SendConfigMSG("{\"action\":{\"FancyZones\":{\"action_name\":\"ToggledFZEditor\", \"value\":\"\"}}}");
+        }
+
+        private void KbmKeyLaunchClicked(object sender, RoutedEventArgs e)
+        {
+            var settingsUtils = new SettingsUtils();
+            var kbmViewModel = new KeyboardManagerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, KeyboardManagerPage.FilterRemapKeysList);
+            kbmViewModel.OnRemapKeyboard();
+        }
+
+        private void KbmShortcutLaunchClicked(object sender, RoutedEventArgs e)
+        {
+            var settingsUtils = new SettingsUtils();
+            var kbmViewModel = new KeyboardManagerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, KeyboardManagerPage.FilterRemapKeysList);
+            kbmViewModel.OnEditShortcut();
+        }
+
+        private void RegistryPreviewLaunchClicked(object sender, RoutedEventArgs e)
+        {
+            var actionName = "Launch";
+            SendConfigMSG("{\"action\":{\"RegistryPreview\":{\"action_name\":\"" + actionName + "\", \"value\":\"\"}}}");
+        }
+    }
+}
diff --git a/src/settings-ui/Settings.UI/ViewModels/KeyboardManagerViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/KeyboardManagerViewModel.cs
index c4e395e99245..15c21eb423d0 100644
--- a/src/settings-ui/Settings.UI/ViewModels/KeyboardManagerViewModel.cs
+++ b/src/settings-ui/Settings.UI/ViewModels/KeyboardManagerViewModel.cs
@@ -220,12 +220,12 @@ public List<AppSpecificKeysDataModel> RemapShortcuts
 
         public ICommand EditShortcutCommand => _editShortcutCommand ?? (_editShortcutCommand = new RelayCommand(OnEditShortcut));
 
-        private void OnRemapKeyboard()
+        public void OnRemapKeyboard()
         {
             OpenEditor((int)KeyboardManagerEditorType.KeyEditor);
         }
 
-        private void OnEditShortcut()
+        public void OnEditShortcut()
         {
             OpenEditor((int)KeyboardManagerEditorType.ShortcutEditor);
         }