deploy backend (ui pending launch)

This commit is contained in:
Belim
2025-05-02 15:30:45 +02:00
parent 0c56188c7d
commit cc58c7ac3c
11 changed files with 719 additions and 12 deletions
+138
View File
@@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Management.Deployment;
namespace Crapfixer
{
public class AppAnalysisResult
{
public string AppName { get; set; }
public string FullName { get; set; }
}
public class AppManagerService
{
private Dictionary<string, string> _appDirectory = new Dictionary<string, string>();
// Loads all apps and stores them in the directory (name -> fullName)
private async Task LoadAppsAsync()
{
_appDirectory.Clear();
var pm = new PackageManager();
var packages = await Task.Run(() =>
pm.FindPackagesForUserWithPackageTypes(string.Empty, PackageTypes.Main));
foreach (var p in packages)
{
string name = p.Id.Name;
string fullName = p.Id.FullName;
if (!_appDirectory.ContainsKey(name))
{
_appDirectory[name] = fullName;
}
}
Logger.Log($"(Checked against {_appDirectory.Count} apps from the system)");
}
// Aanalyzes the apps based on predefined apps (from resources) and returns matching apps
public async Task<List<AppAnalysisResult>> AnalyzeAppsAsync(string[] predefinedApps)
{
Logger.Log("\n🧩 APPS ANALYSIS", LogLevel.Info);
Logger.Log(new string('=', 50), LogLevel.Info);
await LoadAppsAsync(); // Load all apps before analysis
var result = new List<AppAnalysisResult>();
// Check each app's name against predefined patterns
foreach (var app in _appDirectory)
{
foreach (string pattern in predefinedApps)
{
if (app.Key.ToLower().Contains(pattern.ToLower()))
{
result.Add(new AppAnalysisResult
{
AppName = app.Key,
FullName = app.Value // Store the full name
});
break;
}
}
}
return result;
}
// Uninstall an app by its full name
public async Task<bool> UninstallApp(string fullName)
{
try
{
var pm = new PackageManager();
var operation = pm.RemovePackageAsync(fullName);
var resetEvent = new ManualResetEvent(false);
operation.Completed = (o, s) => resetEvent.Set();
await Task.Run(() => resetEvent.WaitOne());
if (operation.Status == AsyncStatus.Completed)
{
Logger.Log($"Successfully uninstalled app: {fullName}");
return true;
}
else
{
Logger.Log($"Failed to uninstall appe: {fullName}", LogLevel.Warning);
return false;
}
}
catch (Exception ex)
{
Logger.Log($"Error during uninstalling app {fullName}: {ex.Message}", LogLevel.Warning);
return false;
}
}
// Uninstall selected apps and log the results
public async Task<List<string>> UninstallSelectedAppsAsync(List<string> selectedApps)
{
List<string> removedApps = new List<string>();
foreach (var fullName in selectedApps)
{
Logger.Log($"🗑️ Removing app: {fullName}...");
// Uninstall the app using its full name
var success = await UninstallApp(fullName);
if (success)
{
removedApps.Add(fullName);
}
}
// Log results for apps that were successfully removed
foreach (var app in removedApps)
{
Logger.Log($"🗑️ Removed Store App: {app}");
}
// Log failed attempts
var failedApps = selectedApps.Except(removedApps).ToList();
foreach (var app in failedApps)
{
Logger.Log($"⚠️ Failed to remove Store App: {app}", LogLevel.Warning);
}
Logger.Log("App cleanup complete.");
return removedApps; // Return removed apps to update the UI
}
}
}
+4 -2
View File
@@ -32,6 +32,9 @@ namespace Features
new FeatureNode(new BSODDetails()),
new FeatureNode(new VerboseStatus()),
new FeatureNode(new SpeedUpShutdown()),
new FeatureNode(new NetworkThrottling()),
new FeatureNode(new SystemResponsiveness()),
new FeatureNode(new MenuShowDelay()),
}
},
@@ -115,8 +118,7 @@ namespace Features
Children =
{
new FeatureNode(new CopilotTaskbar()),
new FeatureNode(new RecallMachine()),
new FeatureNode(new RecallUser()),
new FeatureNode(new Recall()),
}
},
};
+230
View File
@@ -0,0 +1,230 @@
using Features;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Crapfixer
{
/// <summary>
/// Provides operations to load, analyze, fix, restore, and show help for FeatureNodes.
/// </summary>
public static class FeatureNodeManager
{
private static int totalChecked;
private static int issuesFound;
// Public properties to access the analysis results
public static int TotalChecked => totalChecked;
public static int IssuesFound => issuesFound;
public static void ResetAnalysis()
{
totalChecked = 0;
issuesFound = 0;
}
/// <summary>
/// Loads all features into the TreeView.
/// </summary>
public static void LoadFeatures(TreeView tree)
{
var features = FeatureLoader.Load();
tree.Nodes.Clear();
foreach (var feature in features)
AddNode(tree.Nodes, feature);
// root nodes (categories)
foreach (TreeNode root in tree.Nodes)
{
root.NodeFont = new Font(tree.Font, FontStyle.Bold);
root.ForeColor = Color.RoyalBlue; // category color
}
tree.ExpandAll(); // expand all nodes
}
/// <summary>
/// Recursively adds a FeatureNode and its children into the TreeView.
/// </summary>
private static void AddNode(TreeNodeCollection treeNodes, FeatureNode featureNode)
{
string text = featureNode.IsCategory
? " " + featureNode.Name + " " // add extra space to avoid clipping
: featureNode.Name;
TreeNode node = new TreeNode(text)
{
Tag = featureNode,
Checked = true,
};
treeNodes.Add(node);
foreach (var child in featureNode.Children)
AddNode(node.Nodes, child);
}
/// <summary>
/// Analyzes all checked features recursively and logs only issues.
/// </summary>
public static void AnalyzeAll(TreeNodeCollection nodes)
{
ResetAnalysis();
foreach (TreeNode node in nodes)
AnalyzeCheckedRecursive(node);
Logger.Log("🔎 ANALYSIS COMPLETE", LogLevel.Info);
Logger.Log(new string('=', 50), LogLevel.Info);
int ok = totalChecked - issuesFound;
Logger.Log($"Summary: {ok} of {totalChecked} checked settings are OK; {issuesFound} require attention.",
issuesFound > 0 ? LogLevel.Warning : LogLevel.Info);
}
/// Recursively checks all features and logs misconfigurations.
/// </summary>
private static void AnalyzeCheckedRecursive(TreeNode node)
{
if (node.Tag is FeatureNode fn)
{
if (!fn.IsCategory && node.Checked && fn.Feature != null)
{
totalChecked++;
bool isOk = fn.Feature.CheckFeature();
if (!isOk)
{
issuesFound++;
node.ForeColor = Color.Red; // misconfigured
string category = node.Parent?.Text ?? "General";
Logger.Log($"❌ [{category}] {fn.Name} - Not configured as recommended.");
Logger.Log($" ➤ {fn.Feature.GetFeatureDetails()}");
// log a separator when an issue was found
Logger.Log(new string('-', 50), LogLevel.Info);
}
else
{
node.ForeColor = Color.Gray; // properly configured
}
}
foreach (TreeNode child in node.Nodes)
AnalyzeCheckedRecursive(child);
}
}
/// <summary>
/// Analyzes a selected feature and logs its status.
/// </summary>
public static void AnalyzeFeature(TreeNode node)
{
if (node.Tag is FeatureNode fn && !fn.IsCategory && node.Checked && fn.Feature != null)
{
bool isOk = fn.Feature.CheckFeature();
node.ForeColor = isOk ? Color.Gray : Color.Red;
Logger.Log(isOk
? $"✅ Feature: {fn.Name} is properly configured."
: $"❌ Feature: {fn.Name} requires attention.\n ➤ {fn.Feature.GetFeatureDetails()}",
isOk ? LogLevel.Info : LogLevel.Warning);
if (!isOk)
Logger.Log(new string('-', 50), LogLevel.Info);
}
}
/// <summary>
/// Fixes all checked features recursively.
/// </summary>
public static async Task FixChecked(TreeNode node)
{
if (node.Tag is FeatureNode fn)
{
if (!fn.IsCategory && node.Checked && fn.Feature != null)
{
bool result = await fn.Feature.DoFeature();
Logger.Log(result
? $"🔧 {fn.Name} - Fixed"
: $"❌ {fn.Name} - ⚠️ Fix failed (This feature may require admin privileges)",
result ? LogLevel.Info : LogLevel.Error);
}
foreach (TreeNode child in node.Nodes)
await FixChecked(child);
}
}
/// <summary>
/// Restores all checked features recursively.
/// </summary>
public static void RestoreChecked(TreeNode node)
{
if (node.Tag is FeatureNode fn)
{
if (!fn.IsCategory && node.Checked && fn.Feature != null)
{
bool ok = fn.Feature.UndoFeature();
string category = node.Parent?.Text ?? "General";
Logger.Log(ok
? $"↩️ [{category}] {fn.Name} - Restored"
: $"❌ [{category}] {fn.Name} - Restore failed",
ok ? LogLevel.Info : LogLevel.Error);
}
foreach (TreeNode child in node.Nodes)
RestoreChecked(child);
}
}
/// <summary>
/// Attempts to fix the selected feature and logs the result.
/// </summary>
public static async Task FixFeature(TreeNode node)
{
if (node.Tag is FeatureNode fn && !fn.IsCategory && node.Checked && fn.Feature != null)
{
bool result = await fn.Feature.DoFeature();
Logger.Log(result
? $"🔧 {fn.Name} - Fixed"
: $"❌ {fn.Name} - ⚠️ Fix failed (This feature may require admin privileges)",
result ? LogLevel.Info : LogLevel.Error);
}
}
/// <summary>
/// Restores the selected feature to its original state and logs the result.
/// </summary>
public static void RestoreFeature(TreeNode node)
{
if (node.Tag is FeatureNode fn && !fn.IsCategory && node.Checked && fn.Feature != null)
{
bool ok = fn.Feature.UndoFeature();
Logger.Log(ok
? $"↩️ {fn.Name} - Restored"
: $"❌ {fn.Name} - Restore failed",
ok ? LogLevel.Info : LogLevel.Error);
}
}
/// <summary>
/// Displays help information for the selected feature.
/// </summary>
public static void ShowHelp(TreeNode node)
{
if (node.Tag is FeatureNode fn && fn.Feature != null)
{
string info = fn.Feature.Info();
MessageBox.Show(
!string.IsNullOrEmpty(info) ? info : "No additional information available.",
$"Help: {fn.Name}",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
MessageBox.Show("⚠️ No feature selected or feature is invalid.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
+75
View File
@@ -0,0 +1,75 @@
using Microsoft.Win32;
using System;
using Crapfixer;
using System.Threading.Tasks;
namespace Settings.AI
{
internal class Recall : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsAI";
private const string valueName = "AllowRecallEnablement";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended: {recommendedValue} (Recall off – protect your privacy, prevent AI from accessing personal data)";
}
public override string ID()
{
return "Turn off Recall in Windows 11";
}
public override string Info()
{
return "This will remove Recall from Windows 11 24H2";
}
public override bool CheckFeature()
{
// Check if reg key exists
object value = Registry.GetValue(keyName, valueName, null);
if (value == null)
{
// Key does not exist, turn off feature
return false;
}
// Key exists, check if value is desired value
return (int)value != recommendedValue;
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
Logger.Log("You've even disabled system-wide Snapshots for all users now.", LogLevel.Info);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+3 -7
View File
@@ -12,7 +12,7 @@ namespace Settings.Issues
private readonly string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Temp");
private const int cleanupSetNumber = 1;
public override string ID() => "Basic Cleanup";
public override string ID() => "Basic Disk Cleanup";
public override string Info() => "Deletes all temporary files from the user's Temp folder. Then, the built-in Disk Cleanup utility (cleanmgr) is run.";
@@ -23,11 +23,7 @@ namespace Settings.Issues
var totalSize = GetDirectorySize(tempPath);
bool isOk = totalSize <= 50;
if (!isOk)
{
Logger.Log($"Temp folder size is {totalSize} MB (cleanup recommended!) We need also to include cleanup in the next run.", LogLevel.Warning);
}
return isOk;
}
@@ -44,7 +40,7 @@ namespace Settings.Issues
try
{
var totalSize = GetDirectorySize(tempPath);
return $"Temp folder size: {totalSize} MB";
return $"Temp folder size: {totalSize} MB (We need also to include cleanmgr in the next run)";
}
catch (Exception ex)
{
+2 -2
View File
@@ -33,7 +33,7 @@ namespace Settings.Privacy
try
{
Registry.SetValue(dataCollection, "AllowTelemetry", 0, RegistryValueKind.DWord);
Registry.SetValue(diagTrack, "Start", 2, RegistryValueKind.DWord);
Registry.SetValue(diagTrack, "Start", 4, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
@@ -49,7 +49,7 @@ namespace Settings.Privacy
try
{
Registry.SetValue(dataCollection, "AllowTelemetry", 1, RegistryValueKind.DWord);
Registry.SetValue(diagTrack, "Start", 4, RegistryValueKind.DWord);
Registry.SetValue(diagTrack, "Start", 2, RegistryValueKind.DWord);
return true;
}
@@ -0,0 +1,64 @@
using Microsoft.Win32;
using System;
using Crapfixer;
using System.Threading.Tasks;
namespace Settings.System
{
internal class MenuShowDelay : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Control Panel\Desktop";
private const string valueName = "MenuShowDelay";
private const string recommendedValue = "10";
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: \"{recommendedValue}\" (faster menu response)";
}
public override string ID()
{
return "Speed Up Menu Show Delay";
}
public override string Info()
{
return "Speeds up the appearance of menus and submenus by lowering the default delay. This improves the perceived responsiveness of the UI.";
}
public override bool CheckFeature()
{
return Utils.StringEquals(keyName, valueName, recommendedValue);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.String);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, "400", RegistryValueKind.String); // Default is 400 on Windows 11
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,64 @@
using Microsoft.Win32;
using System;
using Crapfixer;
using System.Threading.Tasks;
namespace Settings.System
{
internal class NetworkThrottling : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile";
private const string valueName = "NetworkThrottlingIndex";
private const int recommendedValue = -1; // 0xFFFFFFFF
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: 0xFFFFFFFF (decimal: {uint.MaxValue})";
}
public override string ID()
{
return "Disable Network Throttling";
}
public override string Info()
{
return "Disables the Windows network throttling mechanism to potentially improve performance for streaming, gaming, or real-time applications.";
}
public override bool CheckFeature()
{
return Utils.IntEquals(keyName, valueName, unchecked((int)0xFFFFFFFF));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, unchecked((int)0xFFFFFFFF), RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 10, RegistryValueKind.DWord); // Default is 10
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -18,7 +18,7 @@ namespace Settings.System
public override string ID()
{
return "Speed Up Shutdown Process";
return "Speed Up Shutdown Time";
}
public override string Info()
@@ -0,0 +1,64 @@
using Microsoft.Win32;
using System;
using Crapfixer;
using System.Threading.Tasks;
namespace Settings.System
{
internal class SystemResponsiveness : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile";
private const string valueName = "SystemResponsiveness";
private const int recommendedValue = 10;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Optimize System Responsiveness";
}
public override string Info()
{
return "Enhances system responsiveness by prioritizing CPU resources for foreground tasks, improving performance during active use.";
}
public override bool CheckFeature()
{
return Utils.IntEquals(keyName, valueName, recommendedValue);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 20, RegistryValueKind.DWord); // Default is typically 20 on Windows 11
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+74
View File
@@ -0,0 +1,74 @@
using System.Collections.Generic;
using System.Windows.Forms;
public class NavigationManager
{
private Stack<Control> navigationHistory = new Stack<Control>(); // Holds previous views
private Panel panelContainer; // Reference to the panel container where views are switched
private Control mainPanel; // Reference to the main panel (start page)
public NavigationManager(Panel panel)
{
this.panelContainer = panel;
this.mainPanel = panel.Controls.Count > 0 ? panel.Controls[0] : null;
}
/// <summary>
/// Checks if there are views in the navigation history to go back to.
/// </summary>
public bool CanGoBack()
{
return navigationHistory.Count > 0;
}
/// <summary>
/// Adds the current control to the navigation history.
/// </summary>
private void AddToHistory()
{
if (panelContainer.Controls.Count > 0)
{
// Add the currently visible control to the history stack
navigationHistory.Push(panelContainer.Controls[0]);
}
}
/// <summary>
/// Switches to a new view and adds the current view to the navigation history.
/// </summary>
/// <param name="newView">The new view to display.</param>
public void SwitchView(Control newView)
{
AddToHistory(); // Save the current view before switching
// Clear the container and display the new view
panelContainer.Controls.Clear();
panelContainer.Controls.Add(newView);
newView.Dock = DockStyle.Fill;
newView.BringToFront();
}
/// <summary>
/// Navigates back to the previous view in the history, if available.
/// </summary>
public void GoBack()
{
if (CanGoBack())
{
// Pop the last view from the history stack and display it
Control previousView = navigationHistory.Pop();
panelContainer.Controls.Clear();
panelContainer.Controls.Add(previousView);
previousView.Dock = DockStyle.Fill;
previousView.BringToFront();
}
}
/// <summary>
/// Clears the navigation history.
/// </summary>
public void ClearHistory()
{
navigationHistory.Clear();
}
}