Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b82d0c3
Fix: Update PotPlayer Website link
memstechtips Jan 27, 2026
2fd6ff5
feat: Add Hungarian translation. Credit to @JohnFowler58 for translation
memstechtips Jan 27, 2026
e780e6a
Update Gitignore
memstechtips Jan 27, 2026
3d19eaa
refactor: Remove redundant OneDrive registry check in AppStatusDiscov…
memstechtips Jan 27, 2026
2f2700e
fix: Portable apps creating shortcuts to wrong executable
memstechtips Jan 28, 2026
7c7b4cd
fix: Fixed an issue where OneDriveRemoval unintentionally caused star…
memstechtips Jan 30, 2026
984c41c
feat: Migrate WinGet from CLI to COM API for improved reliability
memstechtips Jan 30, 2026
0b9a22c
chore: Update license from CC BY-NC-SA 4.0 to MIT
memstechtips Jan 30, 2026
449adfd
chore: Update license from CC BY-NC-SA 4.0 to MIT
memstechtips Jan 30, 2026
49b8a68
First launch after migration
memstechtips Jan 31, 2026
452f271
SettingsPage Finalized
memstechtips Feb 1, 2026
185ebf9
Fix logging & refactor to DataTemplateSelector + ContentControl
memstechtips Feb 1, 2026
7e95e95
Create SettingTemplates & Update Pages
memstechtips Feb 2, 2026
1cad18d
Title Bar Done
memstechtips Feb 2, 2026
8940b5b
Navigation Sidebar Done
memstechtips Feb 2, 2026
bec905f
MoreMenu Flyout Done
memstechtips Feb 2, 2026
48c015f
SettingDefinition Icons Done.
memstechtips Feb 2, 2026
e5b3f97
Add FeatureIcons and Finish Nav Button Icons
memstechtips Feb 2, 2026
ff828cc
CustomizePage Header 50% done
memstechtips Feb 2, 2026
b126a95
CustomizePage Done
memstechtips Feb 2, 2026
ac79ffa
MainWindow, NavBar, MoreMenu & CustomizePage Localization Done
memstechtips Feb 3, 2026
1d7bdd2
Finalize CustomizePage Overview Descriptions & Sub Feature GroupNames
memstechtips Feb 3, 2026
6a5e9e9
Finalize Customize & Sub Features Layout Incl. Badges on SettingsCards
memstechtips Feb 4, 2026
a0e75ee
CustomizePage Search Fixed
memstechtips Feb 4, 2026
02546b4
CustomizePage Localization Done
memstechtips Feb 4, 2026
9729950
Finalize CustomizePage with Content Background
memstechtips Feb 4, 2026
032f515
PowerPlan ComboBox Done
memstechtips Feb 5, 2026
1a4e076
ParentSettingId & AdvancedUnlock Done
memstechtips Feb 5, 2026
37ef084
Remove Badges & Implement InfoBars. Update ComboBox dropdown behaviours
memstechtips Feb 5, 2026
06f974d
SoftwareApps Header & Tabs Done
memstechtips Feb 5, 2026
ff59e57
SoftwareApps DataGrid Styling Fixed
memstechtips Feb 6, 2026
81272ff
Add SoftwareApps View Modes & AutounattendGeneratorPage
memstechtips Feb 6, 2026
4dd8da2
Fix ScrollViewer Padding in WindowsAppsHelpContent
memstechtips Feb 6, 2026
167f57d
Add TaskProgressControl, WindowSize and Position Persistence, Add Upd…
memstechtips Feb 6, 2026
05c8ef3
feat: add Arabic localization
qais-mle7y Feb 7, 2026
48ba81e
Remove duplicate language entry for German
qais-mle7y Feb 7, 2026
0999c0f
Merge pull request #405 from qais-mle7y/feat/add-arabic-localization
memstechtips Feb 8, 2026
ac346c7
Add Arabic Translation @qais-mle7y
memstechtips Feb 9, 2026
c8e4aee
Add Config Import Review Process
memstechtips Feb 9, 2026
bc49147
Clean Up Translations and Fix Missing Usage of Localization Keys
memstechtips Feb 9, 2026
9a646ad
Remove WPF project, fix search bug, and clean up unused converters
memstechtips Feb 9, 2026
8357469
Merge remote-tracking branch 'origin/dev-ui' into dev
memstechtips Feb 9, 2026
4dc441a
Remove CommandService & PowerShellExecutionService & Replace with Nat…
memstechtips Feb 10, 2026
23cb77d
Finalize v26.02.13
memstechtips Feb 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
CustomizePage Done
  • Loading branch information
memstechtips committed Feb 2, 2026
commit b126a9584371ede932a9c44bffa0a59deec90be9
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ public static IServiceCollection AddUIServices(this IServiceCollection services)
services.AddTransient<PowerOptimizationsViewModel>();
services.AddTransient<GamingOptimizationsViewModel>();

// Customize ViewModels (Transient - created per page)
services.AddTransient<CustomizeViewModel>();
services.AddTransient<ExplorerCustomizationsViewModel>();
services.AddTransient<StartMenuCustomizationsViewModel>();
services.AddTransient<TaskbarCustomizationsViewModel>();
services.AddTransient<WindowsThemeCustomizationsViewModel>();
// Customize ViewModels (Singleton for state preservation during inner navigation)
services.AddSingleton<CustomizeViewModel>();
services.AddSingleton<ExplorerCustomizationsViewModel>();
services.AddSingleton<StartMenuCustomizationsViewModel>();
services.AddSingleton<TaskbarCustomizationsViewModel>();
services.AddSingleton<WindowsThemeCustomizationsViewModel>();

// AdvancedTools ViewModels (Transient - created per page)
services.AddTransient<WimUtilViewModel>();
Expand Down
18 changes: 16 additions & 2 deletions src/Winhance.UI/Features/Common/Resources/FeatureIcons.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,22 @@
<x:String x:Key="PowerIconGlyph">&#xEC0A;</x:String>
<x:String x:Key="GamingIconGlyph">&#xE7FC;</x:String>

<!-- ==================== Customize Section Icons ==================== -->
<!-- Icons for Customize page feature sections -->
<!-- ==================== Customize Section Icons (Material Design - Path Data) ==================== -->
<!-- Icons for Customize page feature sections - matching WPF project's Material Design icons -->

<!-- Brush - Used for Windows Theme -->
<x:String x:Key="WindowsThemeIconPath">M20.71,4.63L19.37,3.29C19,2.9 18.35,2.9 17.96,3.29L9,12.25L11.75,15L20.71,6.04C21.1,5.65 21.1,5 20.71,4.63M7,14A3,3 0 0,0 4,17C4,18.31 2.84,19 2,19C2.92,20.22 4.5,21 6,21A4,4 0 0,0 10,17A3,3 0 0,0 7,14Z</x:String>

<!-- DockBottom - Used for Taskbar -->
<x:String x:Key="TaskbarIconPath">M20,4H4A2,2 0 0,0 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V6A2,2 0 0,0 20,4M20,18H4V14H20V18Z</x:String>

<!-- FileTableBoxOutline - Used for Start Menu -->
<x:String x:Key="StartMenuIconPath">M19 3H5C3.89 3 3 3.89 3 5V19C3 20.11 3.89 21 5 21H19C20.11 21 21 20.11 21 19V5C21 3.89 20.11 3 19 3M19 19H5V5H19V19M9 18H6V16H9V18M13 18H10V16H13V18M9 15H6V13H9V15M13 15H10V13H13V15M9 12H6V10H9V12M13 12H10V10H13V12Z</x:String>

<!-- Folder - Used for Explorer -->
<x:String x:Key="ExplorerIconPath">M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z</x:String>

<!-- Legacy Segoe MDL2 glyphs (kept for backward compatibility) -->
<x:String x:Key="ExplorerIconGlyph">&#xEC50;</x:String>
<x:String x:Key="StartMenuIconGlyph">&#xE737;</x:String>
<x:String x:Key="TaskbarIconGlyph">&#xE700;</x:String>
Expand Down
268 changes: 161 additions & 107 deletions src/Winhance.UI/Features/Customize/CustomizePage.xaml

Large diffs are not rendered by default.

164 changes: 163 additions & 1 deletion src/Winhance.UI/Features/Customize/CustomizePage.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
using Winhance.UI.Features.Customize.Models;
using Winhance.UI.Features.Customize.Pages;
using Winhance.UI.Features.Customize.ViewModels;

namespace Winhance.UI.Features.Customize;

/// <summary>
/// Page for customizing Windows appearance and behavior.
/// Shell page for customizing Windows appearance and behavior.
/// Shows overview cards by default, uses inner Frame for detail pages.
/// </summary>
public sealed partial class CustomizePage : Page
{
private static readonly string LogFile = Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "..", "startup-debug.log");
private static void Log(string msg) { try { File.AppendAllText(LogFile, $"[{DateTime.Now:HH:mm:ss.fff}] [CustomizePage] {msg}{Environment.NewLine}"); } catch { } }

// Map section keys to their icon path resource keys in FeatureIcons.xaml
private static readonly Dictionary<string, string> SectionIconResourceKeys = new()
{
{ "Explorer", "ExplorerIconPath" },
{ "StartMenu", "StartMenuIconPath" },
{ "Taskbar", "TaskbarIconPath" },
{ "WindowsTheme", "WindowsThemeIconPath" }
};

public CustomizeViewModel ViewModel { get; }

public CustomizePage()
Expand All @@ -38,6 +51,11 @@ protected override async void OnNavigatedTo(NavigationEventArgs e)
{
Log("OnNavigatedTo starting...");
base.OnNavigatedTo(e);

// Ensure we're showing overview on initial navigation
ViewModel.CurrentSectionKey = "Overview";
UpdateContentVisibility();

Log("Calling ViewModel.InitializeAsync...");
await ViewModel.InitializeAsync();
Log("OnNavigatedTo complete");
Expand All @@ -53,4 +71,148 @@ protected override void OnNavigatedFrom(NavigationEventArgs e)
base.OnNavigatedFrom(e);
ViewModel.OnNavigatedFrom();
}

/// <summary>
/// Navigates to a specific section by key.
/// </summary>
public void NavigateToSection(string sectionKey, string? searchText = null)
{
Type pageType = sectionKey switch
{
"Explorer" => typeof(ExplorerCustomizePage),
"StartMenu" => typeof(StartMenuCustomizePage),
"Taskbar" => typeof(TaskbarCustomizePage),
"WindowsTheme" => typeof(WindowsThemeCustomizePage),
_ => null
};

if (pageType != null)
{
InnerContentFrame.Navigate(pageType, searchText);
}
else
{
// Navigate to overview
NavigateToOverview();
}
}

/// <summary>
/// Returns to the overview (hides detail frame, shows overview cards).
/// </summary>
public void NavigateToOverview()
{
ViewModel.CurrentSectionKey = "Overview";
InnerContentFrame.Content = null;
UpdateContentVisibility();
}

private void InnerContentFrame_Navigated(object sender, NavigationEventArgs e)
{
// Update the ViewModel's current section key based on the navigated page
ViewModel.CurrentSectionKey = e.SourcePageType.Name switch
{
nameof(ExplorerCustomizePage) => "Explorer",
nameof(StartMenuCustomizePage) => "StartMenu",
nameof(TaskbarCustomizePage) => "Taskbar",
nameof(WindowsThemeCustomizePage) => "WindowsTheme",
_ => "Overview"
};

UpdateContentVisibility();
}

private void UpdateContentVisibility()
{
var isInDetailPage = ViewModel.IsInDetailPage;

// Toggle between overview and detail frame
OverviewContent.Visibility = isInDetailPage ? Visibility.Collapsed : Visibility.Visible;
InnerContentFrame.Visibility = isInDetailPage ? Visibility.Visible : Visibility.Collapsed;

// Update breadcrumb visibility
BreadcrumbSeparator.Visibility = isInDetailPage ? Visibility.Visible : Visibility.Collapsed;
BreadcrumbSection.Visibility = isInDetailPage ? Visibility.Visible : Visibility.Collapsed;

// Update the section dropdown icon and text
if (isInDetailPage)
{
BreadcrumbSectionText.Text = ViewModel.CurrentSectionName;

// Get the icon path data from application resources (FeatureIcons.xaml)
if (SectionIconResourceKeys.TryGetValue(ViewModel.CurrentSectionKey, out var resourceKey) &&
Application.Current.Resources.TryGetValue(resourceKey, out var pathDataObj) &&
pathDataObj is string pathData)
{
// Parse the path data string into a Geometry
var geometry = (Microsoft.UI.Xaml.Media.Geometry)Microsoft.UI.Xaml.Markup.XamlBindingHelper.ConvertValue(
typeof(Microsoft.UI.Xaml.Media.Geometry), pathData);
BreadcrumbSectionIcon.Data = geometry;
}
}
}

// Overview card click handlers
private void ExplorerCard_Click(object sender, RoutedEventArgs e)
{
NavigateToSection("Explorer");
}

private void StartMenuCard_Click(object sender, RoutedEventArgs e)
{
NavigateToSection("StartMenu");
}

private void TaskbarCard_Click(object sender, RoutedEventArgs e)
{
NavigateToSection("Taskbar");
}

private void WindowsThemeCard_Click(object sender, RoutedEventArgs e)
{
NavigateToSection("WindowsTheme");
}

// Breadcrumb handlers
private void BreadcrumbOverview_Click(object sender, RoutedEventArgs e)
{
NavigateToOverview();
}

private void NavigateExplorer_Click(object sender, RoutedEventArgs e)
{
NavigateToSection("Explorer");
}

private void NavigateStartMenu_Click(object sender, RoutedEventArgs e)
{
NavigateToSection("StartMenu");
}

private void NavigateTaskbar_Click(object sender, RoutedEventArgs e)
{
NavigateToSection("Taskbar");
}

private void NavigateWindowsTheme_Click(object sender, RoutedEventArgs e)
{
NavigateToSection("WindowsTheme");
}

// Search handlers
private void SearchBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
{
if (args.SelectedItem is SearchSuggestionItem suggestion)
{
NavigateToSection(suggestion.SectionKey, suggestion.SettingName);
}
}

private void SearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
if (args.ChosenSuggestion is SearchSuggestionItem suggestion)
{
NavigateToSection(suggestion.SectionKey, suggestion.SettingName);
}
}
}
41 changes: 41 additions & 0 deletions src/Winhance.UI/Features/Customize/Models/CustomizeSectionInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace Winhance.UI.Features.Customize.Models;

/// <summary>
/// Contains metadata for a customization section.
/// </summary>
public class CustomizeSectionInfo
{
/// <summary>
/// Gets the unique key for the section (e.g., "Explorer", "StartMenu").
/// </summary>
public string Key { get; }

/// <summary>
/// Gets the icon glyph resource key for the section.
/// </summary>
public string IconGlyphKey { get; }

/// <summary>
/// Gets the display name of the section.
/// </summary>
public string DisplayName { get; }

/// <summary>
/// Gets the page type for navigation.
/// </summary>
public Type PageType { get; }

/// <summary>
/// Gets the description of the section.
/// </summary>
public string Description { get; }

public CustomizeSectionInfo(string key, string iconGlyphKey, string displayName, string description, Type pageType)
{
Key = key;
IconGlyphKey = iconGlyphKey;
DisplayName = displayName;
Description = description;
PageType = pageType;
}
}
44 changes: 44 additions & 0 deletions src/Winhance.UI/Features/Customize/Models/SearchSuggestionItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
namespace Winhance.UI.Features.Customize.Models;

/// <summary>
/// Represents a search suggestion item for cross-section searching.
/// </summary>
public class SearchSuggestionItem
{
/// <summary>
/// Gets or sets the setting name that matched the search.
/// </summary>
public string SettingName { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the section key where this setting is found.
/// </summary>
public string SectionKey { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the display name of the section.
/// </summary>
public string SectionDisplayName { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the icon glyph for the section.
/// </summary>
public string SectionIconGlyph { get; set; } = string.Empty;

/// <summary>
/// Gets the display text for the suggestion.
/// </summary>
public string DisplayText => $"{SettingName} ({SectionDisplayName})";

public SearchSuggestionItem()
{
}

public SearchSuggestionItem(string settingName, string sectionKey, string sectionDisplayName, string sectionIconGlyph)
{
SettingName = settingName;
SectionKey = sectionKey;
SectionDisplayName = sectionDisplayName;
SectionIconGlyph = sectionIconGlyph;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<Page
x:Class="Winhance.UI.Features.Customize.Pages.ExplorerCustomizePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Winhance.UI.Features.Customize.Pages"
xmlns:viewModels="using:Winhance.UI.Features.Optimize.ViewModels"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:commonControls="using:Winhance.UI.Features.Common.Controls"
x:DefaultBindMode="OneWay"
NavigationCacheMode="Disabled">

<Page.Resources>
<!-- ItemTemplate: SettingsCard wraps the shared SettingsCardItem control -->
<DataTemplate x:Key="SettingItemTemplate" x:DataType="viewModels:SettingItemViewModel">
<controls:SettingsCard
Header="{x:Bind Name}"
Description="{x:Bind Description}"
IsEnabled="{x:Bind EffectiveIsEnabled}"
Visibility="{x:Bind IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"
HeaderIcon="{x:Bind Converter={StaticResource SettingIconConverter}}"
Padding="16,12,16,12">
<commonControls:SettingsCardItem Setting="{x:Bind}"/>
</controls:SettingsCard>
</DataTemplate>
</Page.Resources>

<Grid>
<!-- Loading State -->
<ProgressRing
IsActive="{x:Bind ViewModel.IsLoading}"
Visibility="{x:Bind ViewModel.IsLoading}"
Width="48"
Height="48"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>

<!-- Main Content -->
<ScrollView Visibility="{x:Bind ViewModel.IsNotLoading}">
<StackPanel Spacing="8" MaxWidth="{StaticResource SettingsContentMaxWidth}" Margin="{StaticResource SettingsContentMargin}" HorizontalAlignment="Stretch">
<ItemsRepeater
ItemsSource="{x:Bind ViewModel.ExplorerViewModel.Settings}"
ItemTemplate="{StaticResource SettingItemTemplate}"/>

<!-- No Results Message -->
<TextBlock
Text="No settings match your search."
Style="{StaticResource BodyTextBlockStyle}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
HorizontalAlignment="Center"
Margin="0,40,0,0"
Visibility="{x:Bind ViewModel.HasNoSearchResults, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</StackPanel>
</ScrollView>
</Grid>
</Page>
Loading