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() .Any(item => checkedListBoxApps.GetItemChecked(checkedListBoxApps.Items.IndexOf(item)) == false); for (int i = 0; i < checkedListBoxApps.Items.Count; i++) { checkedListBoxApps.SetItemChecked(i, shouldCheck); } } } private void panelHeader_Paint(object sender, PaintEventArgs e) { var panel = sender as Panel; var g = e.Graphics; // Solid background: #4D4D4D g.Clear(Color.FromArgb(77, 77, 77)); // Inset line effect (3D-like): light line + shadow line Color baseColor = Color.FromArgb(80, 80, 80); // inset base using (var topLine = new Pen(ControlPaint.Light(baseColor, 0.0f))) using (var bottomLine = new Pen(ControlPaint.Dark(baseColor, 0.2f))) { g.SmoothingMode = SmoothingMode.None; g.DrawLine(topLine, 0, panel.Height - 2, panel.Width, panel.Height - 2); g.DrawLine(bottomLine, 0, panel.Height - 1, panel.Width, panel.Height - 1); } } // Handles click on the header image to open the GitHub page private void PictureHeader_Click(object sender, EventArgs e) { Utils.OpenGitHubPage(sender, e); } // Handles link click to check for updates private void linkUpdateCheck_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { var updateUrl = $"https://builtbybel.github.io/CrapFixer/update-check.html?version={Program.GetAppVersion()}"; var psi = new ProcessStartInfo { FileName = updateUrl, UseShellExecute = true }; Process.Start(psi); } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { if (IniStateManager.IsViewSettingEnabled("SETTINGS", "checkSaveToINI")) { IniStateManager.Save(treeFeatures, this); } Logger.OutputBox = null; // Remove reference } private void btnGitHub_Click(object sender, EventArgs e) { _navigationManager.SwitchView(new OptionsView()); } } }