using ModVersionChecker.enums; using ModVersionChecker.managers.interfaces; using ModVersionChecker.model; using ModVersionChecker.repository.api.dto; using ModVersionChecker.service.interfaces; using ModVersionChecker.utils; namespace ModVersionChecker.ui.forms { public class MainForm : Form { private readonly IAppsManager _appsManager; private readonly IFormFactory _formFactory; private readonly IFlightSimsManager _fsManager; private readonly IApiService _apiService; private readonly IVersionService _versionService; private readonly TableLayoutPanel _mainLayout; private readonly Config _globalConfig; private List _apps = new List(); private ListView _listView; private ImageList _statusImageList = new ImageList(); public event EventHandler OnConfigChanged; public event EventHandler OnRecheck; private EventHandler onAppSavedHandler; private MenuStrip _menuStrip; private List _fsMods; private readonly Dictionary _fsModPathTextBoxes = new Dictionary(); private List _sources = new List(); private List _typesDef = new List(); public MainForm( IConfigManager configManager, IAppsManager appsManager, IFormFactory formFactory, IFlightSimsManager fsManager, IApiService apiService, ITypeManager typeConfigManager, IVersionService versionService) { _appsManager = appsManager ?? throw new ArgumentNullException(nameof(appsManager)); _formFactory = formFactory ?? throw new ArgumentNullException(nameof(formFactory)); _fsManager = fsManager ?? throw new ArgumentNullException(nameof(fsManager)); _apiService = apiService ?? throw new ArgumentNullException(nameof(apiService)); _versionService = versionService ?? throw new ArgumentNullException(nameof(versionService)); _fsMods = _fsManager.Load(); _statusImageList.Images.Add("none", new Icon("Resources/ok-icon.ico")); _statusImageList.Images.Add("update", new Icon("Resources/up-icon.ico")); _statusImageList.Images.Add("error", new Icon("Resources/error-icon.ico")); Text = "Update Checker Configuration"; Size = new Size(600, 800); StartPosition = FormStartPosition.CenterScreen; _globalConfig = configManager.Load() ?? new Config(); _mainLayout = GetMainLayout(); _listView = GetListView(); _listView.SmallImageList = _statusImageList; _mainLayout.Controls.Add(_listView , 0, 0); _mainLayout.Controls.Add(GetButtonsPanel(), 0, 1); onAppSavedHandler = (s2, e) => { var form = s2 as AppDetailsForm; if (form == null || form.SelectedApp == null) return; var app = form.SelectedApp; UpdateCurrentVersion(app); UpdateListView(); OnConfigChanged?.Invoke(this, EventArgs.Empty); }; this.Load += MainForm_LoadAsync; } private void UpdateCurrentVersion(App app) { TypeConfig? typeConfig = _globalConfig.Types.FirstOrDefault(tc => app.Type == tc.ShortName); if (typeConfig == null) return; var versionInDisk = VersionUtils.GetCurrentVersion(app, typeConfig); if (!string.IsNullOrEmpty(versionInDisk)) { app.CurrentVersion = versionInDisk; app.LastCheckedAt = TimeUtils.GetUnixTimeMillis(DateTime.Now); _versionService.CheckApp(app); } } private async void MainForm_LoadAsync(object? sender, EventArgs e) { await _apiService.AuthenticateAsync("user", "user"); _apps = await _apiService.GetAppsByIds([]); _sources = await _apiService.GetSources(); _typesDef = await _apiService.GetTypes(); UpdateListView(); } private TableLayoutPanel GetMainLayout() { // Initialize the main layout panel var mainLayout = new TableLayoutPanel { Dock = DockStyle.Fill, RowCount = 2, ColumnCount = 1 }; // mainLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 150)); // Paths panel height mainLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 70)); // ListView takes remaining space mainLayout.RowStyles.Add(new RowStyle(SizeType.Absolute, 50)); // Button panel height Controls.Add(mainLayout); InitializeMenu(); return mainLayout; } private ListView GetListView() { var listView = new ListView { Dock = DockStyle.Fill, View = View.Details, FullRowSelect = true, MultiSelect = false, Visible = true, Sorting = SortOrder.Ascending }; listView.Columns.Add("Name", 150); listView.Columns.Add("MSFS Versions", 100); listView.Columns.Add("Current", 80); listView.Columns.Add("Latest", 80); listView.Columns.Add("Last Checked", 150); listView.DoubleClick += (s, e) => { if (listView.SelectedItems.Count > 0) { ListViewItem selectedItem = listView.SelectedItems[0]; App? app = selectedItem.Tag as App; if (app == null) return; if (app.Status == AppStatus.UPDATE_AVAILABLE) { if (string.IsNullOrEmpty(app.DownloadUrl)) { MessageBox.Show("No download URL specified for this app."); return; } System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = app.DownloadUrl, UseShellExecute = true }); } else { } } }; return listView; } private FlowLayoutPanel GetButtonsPanel() { var buttonPanel = new FlowLayoutPanel { Dock = DockStyle.Fill }; var addButton = new Button { Text = "Add App" }; var deleteButton = new Button { Text = "Delete App", Enabled = false }; var recheckButton = new Button { Text = "Recheck Versions" }; addButton.Click += (s, e) => { var form = _formFactory.CreateAppDetailsForm(null, true, onAppSavedHandler); // Use factory form.ShowDialog(); }; deleteButton.Click += (s, e) => { if (_listView.SelectedItems.Count > 0 && _listView.SelectedItems[0].Tag != null) { var app = _listView.SelectedItems[0].Tag as App; DeleteApp(app); } }; _listView.SelectedIndexChanged += (s, e) => { deleteButton.Enabled = _listView.SelectedItems.Count > 0; }; // Add recheck logic here recheckButton.Click += async (s, e) => { recheckButton.Enabled = false; await _versionService.CheckAllApps(); UpdateListView(); //OnRecheck.Invoke(this, "User initiated recheck from ConfigForm"); recheckButton.Enabled = true; }; buttonPanel.Controls.AddRange(new[] { addButton, deleteButton, recheckButton }); return buttonPanel; } public void UpdateListView() { _apps = _appsManager.Load(); _listView.Items.Clear(); foreach (var app in _apps) { var item = new ListViewItem(app.Name); try { item.Tag = app; item.SubItems.Add(app.Type); var currentVersion = app.CurrentVersion; var latestVersion = app.LatestVersion; var lastChecked = TimeUtils.ToFriendlyTime(app.LastCheckedAt); item.SubItems.Add(currentVersion); item.SubItems.Add(latestVersion); item.SubItems.Add(lastChecked); } catch (Exception ex) { item.SubItems.Add($"Error: {ex.Message}"); } switch (app.Status) { case AppStatus.UPDATE_AVAILABLE: item.ImageKey = "update"; break; case AppStatus.ERROR: item.ImageKey = "error"; break; default: item.ImageKey = "none"; break; } _listView.Items.Add(item); } } private void DeleteApp(App app) { var result = MessageBox.Show($"Are you sure you want to delete '{app?.Name ?? ""}'?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result == DialogResult.Yes) { _appsManager.Delete((_listView.SelectedItems[0].Tag as App).Id); UpdateListView(); OnConfigChanged?.Invoke(this, EventArgs.Empty); } } private void InitializeMenu() { _menuStrip = new MenuStrip(); // Create top-level menu var configMenu = new ToolStripMenuItem("Configuration"); // Add sub-menu items var settingsItem = new ToolStripMenuItem("Settings"); settingsItem.Click += (s, e) => ShowGlobalConfigDialog(); var typesItem = new ToolStripMenuItem("Types"); typesItem.Click += (s, e) => ShowTypesConfigForm(); //var sourcesConfigItem = new ToolStripMenuItem("Sources"); //sourcesConfigItem.Click += (s, e) => ShowSourcesConfigDialog(); //var FlightSimsConfigItem = new ToolStripMenuItem("Flight Sims"); //FlightSimsConfigItem.Click += (s, e) => MessageBox.Show("Flight Sims configuration dialog would open here."); configMenu.DropDownItems.Add(settingsItem); configMenu.DropDownItems.Add(typesItem); // configMenu.DropDownItems.Add(sourcesConfigItem); // configMenu.DropDownItems.Add(FlightSimsConfigItem); _menuStrip.Items.Add(configMenu); // Add the menu to the form Controls.Add(_menuStrip); MainMenuStrip = _menuStrip; } private void ShowTypesConfigForm() { var typesConfigForm = _formFactory.CreateTypeConfigForm(); typesConfigForm.ShowDialog(); } private void ShowGlobalConfigDialog() { // Show your global config form/dialog here var globalConfigForm = _formFactory.CreateGlobalConfigForm(); globalConfigForm.ShowDialog(); } //private void ShowSourcesConfigDialog() //{ // EventHandler onSourcesChanged = (s, e) => MessageBox.Show("Sources Changed"); // var form = _formFactory.CreateSourcesConfigForm(onSourcesChanged); // form.ShowDialog(); //} } }