using CFixer;
using CFixer.Properties;
using CFixer.Views;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CrapFixer
{
public partial class MainForm : Form
{
private NavigationManager _navigationManager;
private NavigationHandler _navigationHandler;
private LogActions _logActions;
private LogActionsController _logActionsController;
private readonly AppManagerService _appManager = new AppManagerService();
public MainForm()
{
InitializeComponent();
IniStateManager.ApplyWindowState(this);
// Set up the main navigation manager and logger
_navigationManager = new NavigationManager(panelContainer);
Logger.OutputBox = rtbLogger;
// Set up log actions controller
_logActions = new LogActions(rtbLogger);
}
private async void MainForm_Shown(object sender, EventArgs e)
{
await InitializeUI(); // _ = InitializeUI();
InitializeAppState();
}
private void InitializeAppState()
{
// Load features and plugins into the tree view
FeatureNodeManager.LoadFeatures(treeFeatures);
PluginManager.LoadPlugins(treeFeatures);
// Load settings from INI file if enabled
IniStateManager.LoadFeaturesIfEnabled(treeFeatures);
}
private async Task InitializeUI()
{
// Initialize the navigation handler with buttons
_navigationHandler = new NavigationHandler(btnFixer, btnRestore, btnTools, btnGitHub);
// Load navigation icons
await _navigationHandler.LoadNavigationIcons();
// Register navigation handler
_navigationHandler.NavigationButtonClicked += NavigationHandler_NavigationButtonClicked;
// Register click handlers for GitHub links
pictureHeader.Click += PictureHeader_Click;
lblHeader.Click += PictureHeader_Click;
// Re-initialize log actions controller (optional if not changed)
_logActionsController = new LogActionsController(comboLogActions, _logActions);
// Set version and OS info
lblVersionInfo.Text = $"v{Program.GetAppVersion()} ";
lblOSInfo.Text = await OSHelper.OSHelper.GetWindowsVersion();
}
// Handles navigation button clicks and switches views accordingly
private void NavigationHandler_NavigationButtonClicked(Button button)
{
if (button == btnFixer)
{
_navigationManager.GoToMain();
}
else if (button == btnTools)
{
_navigationManager.SwitchView(new OptionsView());
}
}
private async void btnAnalyze_Click(object sender, EventArgs e)
{
// Analyze features
await FeatureNodeManager.AnalyzeAll(treeFeatures.Nodes);
// Analyze plugins
await PluginManager.AnalyzeAllPlugins(treeFeatures.Nodes);
// Analyze apps
await AnalyzeApps();
// Show log actions combo box
comboLogActions.Visible = true;
}
///
/// Analyzes the apps and logs the results.
///
private async Task AnalyzeApps()
{
checkedListBoxApps.Items.Clear();
// Try loading patterns from CFEnhancer.txt (located in Plugins folder)
var (bloatwarePatterns, whitelistPatterns, scanAll) = _appManager.LoadExternalBloatwarePatterns();
if (bloatwarePatterns.Length == 0 && !scanAll)
{
// Fallback to internal resource if external file not found or empty and scanAll is not enabled
bloatwarePatterns = Resources.PredefinedApps?
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.Trim().ToLower()).ToArray() ?? Array.Empty();
whitelistPatterns = Array.Empty();
Logger.Log("Using built-in bloatware list.", LogLevel.Info);
}
else
{
Logger.Log("🔎 Plugin ready: CFEnhancer (external bloatware list)", LogLevel.Info);
}
// Analyze installed apps based on patterns and whitelist, and optionally scan all
var apps = await _appManager.AnalyzeAndLogAppsAsync(bloatwarePatterns, whitelistPatterns, scanAll);
foreach (var app in apps)
{
checkedListBoxApps.Items.Add(app.FullName);
}
}
private async void btnFix_Click(object sender, EventArgs e)
{
rtbLogger.Clear();
// Fix all features
foreach (TreeNode node in treeFeatures.Nodes)
await FeatureNodeManager.FixChecked(node);
// Fix all plugins
foreach (TreeNode node in treeFeatures.Nodes)
await PluginManager.FixChecked(node);
// Fix selected Store apps
var selectedApps = checkedListBoxApps.CheckedItems.Cast().ToList();
if (selectedApps.Count == 0)
return;
var appService = new AppManagerService();
var removedApps = await appService.UninstallSelectedAppsAsync(selectedApps);
// Update UI after uninstall
foreach (var app in removedApps)
{
checkedListBoxApps.Items.Remove(app);
}
}
private void btnRestore_Click(object sender, EventArgs e)
{
var result = MessageBox.Show(
"⚠️ This will restore all selected features to their original state.\n" +
"Changes made by previous configurations may be reverted.\n\n" +
"Are you sure you want to proceed?",
"Restore Selected Features",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning);
if (result == DialogResult.Yes)
{
rtbLogger.Clear();
foreach (TreeNode node in treeFeatures.Nodes)
FeatureNodeManager.RestoreChecked(node);
Logger.Log("↩️ All selected features have been restored.", LogLevel.Info);
}
}
///
/// Analyzes all plugins and features starting from the selected node from the context menu.
///
private async void analyzeMarkedFeatureToolStripMenuItem_Click(object sender, EventArgs e)
{
if (treeFeatures.SelectedNode is TreeNode selectedNode)
{
Logger.Log($"🔎 Analyzing Feature: {selectedNode.Text}", LogLevel.Info);
// If a single node is selected (leaf node with no children),
// always analyze this node regardless of its Checked state.
if (selectedNode.Nodes.Count == 0)
{
await PluginManager.AnalyzePlugin(selectedNode);
}
else
{
// If a parent node is selected (has children),
// recursively analyze only the checked plugin nodes.
await PluginManager.AnalyzeAll(selectedNode);
}
// Perform feature-specific analysis (non-plugin)
FeatureNodeManager.AnalyzeFeature(selectedNode);
}
}
///
/// Fixes all checked plugin and feature nodes starting from the selected node from the context menu.
///
private async void fixMarkedFeatureToolStripMenuItem_Click(object sender, EventArgs e)
{
if (treeFeatures.SelectedNode is TreeNode selectedNode)
{
Logger.Log($"🔧 Fixing Feature: {selectedNode.Text}", LogLevel.Info);
// Recursively fix all checked feature nodes (non-plugin)
await FeatureNodeManager.FixFeature(selectedNode);
// Recursively fix all checked plugin nodes starting from the selected node
await PluginManager.FixPlugin(selectedNode);
}
}
///
/// Restores the selected plugin or feature to its previous state from the context menu.
///
private async void restoreMarkedFeatureToolStripMenuItem_Click(object sender, EventArgs e)
{
if (treeFeatures.SelectedNode is TreeNode selectedNode)
{
if (PluginManager.IsPluginNode(selectedNode))
// Restore the plugin using its Undo command if available!
await PluginManager.RestorePlugin(selectedNode);
else
Logger.Log($"↩️ Restoring Feature: {selectedNode.Text}", LogLevel.Info);
// Perform feature-specific restore (non-plugin)
FeatureNodeManager.RestoreFeature(selectedNode);
}
}
private void helpMarkedFeatureToolStripMenuItem_Click(object sender, EventArgs e)
{
if (treeFeatures.SelectedNode is TreeNode selectedNode)
{
FeatureNodeManager.ShowHelp(selectedNode);
}
}
///
/// Checks or unchecks all child nodes when a parent node is checked/unchecked.
///
///
///
private void treeFeatures_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Action != TreeViewAction.Unknown)
{
foreach (TreeNode child in e.Node.Nodes)
child.Checked = e.Node.Checked;
}
}
private void treeFeatures_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
// Get the node under the mouse cursor
TreeNode nodeUnderMouse = treeFeatures.GetNodeAt(e.X, e.Y);
if (nodeUnderMouse != null)
{
treeFeatures.SelectedNode = nodeUnderMouse;
// Show the context menu at the mouse position
contextMenuStrip.Show(treeFeatures, e.Location);
}
}
}
///
/// Handles the link click event for selecting or deselecting all items in the list.
///
///
///
private bool treeChecked = false;
private void linkSelection_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if (tabControl.SelectedTab == Windows)
{
foreach (TreeNode node in treeFeatures.Nodes)
{
node.Checked = treeChecked;
foreach (TreeNode child in node.Nodes)
{
child.Checked = treeChecked;
foreach (TreeNode grandChild in child.Nodes)
grandChild.Checked = treeChecked;
}
}
treeChecked = !treeChecked;
}
else if (tabControl.SelectedTab == Apps)
{
bool shouldCheck = checkedListBoxApps.Items.Cast