using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Threading.Tasks; using System.Timers; using System.Windows.Forms; using StarfaceOutlookSync.Models; using StarfaceOutlookSync.Services; using Timer = System.Timers.Timer; namespace StarfaceOutlookSync.UI { public class MainForm : Form { private readonly ProfileManager _profileManager = new ProfileManager(); private readonly SyncEngine _syncEngine = new SyncEngine(); private NotifyIcon _trayIcon; private ContextMenuStrip _trayMenu; private ListView _profileList; private Button _btnNew, _btnEdit, _btnDelete, _btnSync, _btnSettings, _btnInfo; private StatusStrip _statusBar; private ToolStripStatusLabel _statusLabel; private Timer _autoSyncTimer; public MainForm() { InitializeComponent(); SetupTrayIcon(); SetupAutoSync(); RefreshProfileList(); // Minimiert starten falls in Einstellungen aktiviert var settings = UserSettings.Load(); if (settings.StartMinimized) { WindowState = FormWindowState.Minimized; ShowInTaskbar = false; Visible = false; } } protected override void SetVisibleCore(bool value) { // Beim ersten Anzeigen pruefen ob minimiert gestartet werden soll if (!IsHandleCreated) { var settings = UserSettings.Load(); if (settings.StartMinimized) { CreateHandle(); value = false; } } base.SetVisibleCore(value); } private void InitializeComponent() { Text = "Starface Kontakt-Sync"; Size = new Size(620, 450); MinimumSize = new Size(500, 350); StartPosition = FormStartPosition.CenterScreen; Font = new Font("Segoe UI", 9); // Profil-Liste _profileList = new ListView { Dock = DockStyle.Fill, View = View.Details, FullRowSelect = true, GridLines = true, MultiSelect = false }; _profileList.Columns.Add("Profil", 150); _profileList.Columns.Add("Starface", 130); _profileList.Columns.Add("Outlook-Ordner", 130); _profileList.Columns.Add("Richtung", 90); _profileList.Columns.Add("Letzte Sync", 130); _profileList.DoubleClick += (s, e) => EditProfile(); // Button-Panel var buttonPanel = new FlowLayoutPanel { Dock = DockStyle.Bottom, Height = 45, Padding = new Padding(8, 8, 8, 4), FlowDirection = FlowDirection.LeftToRight }; _btnNew = new Button { Text = "Neues Profil", Width = 100, Height = 30 }; _btnNew.Click += (s, e) => NewProfile(); _btnEdit = new Button { Text = "Bearbeiten", Width = 90, Height = 30 }; _btnEdit.Click += (s, e) => EditProfile(); _btnDelete = new Button { Text = "Loeschen", Width = 80, Height = 30 }; _btnDelete.Click += (s, e) => DeleteProfile(); _btnSync = new Button { Text = "Jetzt synchronisieren", Width = 150, Height = 30 }; _btnSync.Click += async (s, e) => await SyncSelectedProfile(); _btnSettings = new Button { Text = "Einstellungen", Width = 100, Height = 30 }; _btnSettings.Click += (s, e) => ShowSettings(); _btnInfo = new Button { Text = "Info", Width = 50, Height = 30 }; _btnInfo.Click += (s, e) => ShowAbout(); buttonPanel.Controls.AddRange(new Control[] { _btnNew, _btnEdit, _btnDelete, _btnSync, _btnSettings, _btnInfo }); // Statusbar _statusBar = new StatusStrip(); _statusLabel = new ToolStripStatusLabel("Bereit"); _statusBar.Items.Add(_statusLabel); Controls.Add(_profileList); Controls.Add(buttonPanel); Controls.Add(_statusBar); } private void SetupTrayIcon() { _trayMenu = new ContextMenuStrip(); _trayMenu.Items.Add("Oeffnen", null, (s, e) => ShowMainWindow()); _trayMenu.Items.Add("-"); // Schnell-Sync fuer jedes Profil var profiles = _profileManager.GetProfiles(); foreach (var p in profiles.Where(p => p.Enabled)) { var profile = p; _trayMenu.Items.Add($"Sync: {profile.Name}", null, async (s, e) => { await RunSync(profile); }); } if (profiles.Any(p => p.Enabled)) _trayMenu.Items.Add("-"); _trayMenu.Items.Add("Beenden", null, (s, e) => ExitApplication()); _trayIcon = new NotifyIcon { Text = "Starface Kontakt-Sync", Icon = SystemIcons.Application, // Placeholder, wird durch eigenes Icon ersetzt ContextMenuStrip = _trayMenu, Visible = true }; _trayIcon.DoubleClick += (s, e) => ShowMainWindow(); } private void SetupAutoSync() { _autoSyncTimer = new Timer(60000); // Jede Minute pruefen _autoSyncTimer.Elapsed += async (s, e) => await CheckAutoSync(); _autoSyncTimer.Start(); } private async Task CheckAutoSync() { var profiles = _profileManager.GetProfiles(); foreach (var profile in profiles.Where(p => p.Enabled && p.AutoSyncIntervalMinutes > 0)) { if (string.IsNullOrEmpty(profile.LastSync)) { await RunSync(profile); continue; } if (DateTime.TryParse(profile.LastSync, out var lastSync)) { if (DateTime.Now - lastSync > TimeSpan.FromMinutes(profile.AutoSyncIntervalMinutes)) { await RunSync(profile); } } } } private void ShowMainWindow() { Show(); WindowState = FormWindowState.Normal; BringToFront(); RefreshProfileList(); } private void RefreshProfileList() { _profileList.Items.Clear(); var profiles = _profileManager.GetProfiles(); foreach (var p in profiles) { var dirText = p.SyncDirection == SyncDirection.Both ? "Bidirektional" : p.SyncDirection == SyncDirection.OutlookToStarface ? "OL -> SF" : "SF -> OL"; var lastSync = string.IsNullOrEmpty(p.LastSync) ? "Noch nie" : DateTime.TryParse(p.LastSync, out var dt) ? dt.ToString("dd.MM.yyyy HH:mm") : p.LastSync; var item = new ListViewItem(new[] { p.Name, $"{p.StarfaceConnection.Host} / {p.StarfaceAddressBook.Name}", p.OutlookFolderName, dirText, lastSync }); item.Tag = p; if (!p.Enabled) item.ForeColor = Color.Gray; _profileList.Items.Add(item); } // Tray-Menu aktualisieren SetupTrayIcon(); } private void NewProfile() { using (var editor = new ProfileEditorForm(null)) { if (editor.ShowDialog(this) == DialogResult.OK) RefreshProfileList(); } } private void EditProfile() { if (_profileList.SelectedItems.Count == 0) return; var profile = _profileList.SelectedItems[0].Tag as SyncProfile; if (profile == null) return; using (var editor = new ProfileEditorForm(profile)) { if (editor.ShowDialog(this) == DialogResult.OK) RefreshProfileList(); } } private void DeleteProfile() { if (_profileList.SelectedItems.Count == 0) return; var profile = _profileList.SelectedItems[0].Tag as SyncProfile; if (profile == null) return; if (MessageBox.Show($"Profil '{profile.Name}' wirklich loeschen?", "Profil loeschen", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { _profileManager.DeleteProfile(profile.Id); RefreshProfileList(); } } private Task SyncSelectedProfile() { if (_profileList.SelectedItems.Count == 0) { MessageBox.Show("Bitte ein Profil auswaehlen.", "Sync", MessageBoxButtons.OK, MessageBoxIcon.Information); return Task.CompletedTask; } var profile = _profileList.SelectedItems[0].Tag as SyncProfile; if (profile == null) return Task.CompletedTask; using (var syncForm = new SyncProgressForm(profile)) { syncForm.ShowDialog(this); } RefreshProfileList(); return Task.CompletedTask; } private async Task RunSync(SyncProfile profile) { try { SetStatus($"Synchronisiere '{profile.Name}'..."); _trayIcon.ShowBalloonTip(2000, "Starface Sync", $"Synchronisiere '{profile.Name}'...", ToolTipIcon.Info); var result = await _syncEngine.SyncProfileAsync(profile); var msg = $"{profile.Name}: {result.Created} erstellt, {result.Updated} aktualisiert"; if (result.Errors > 0) msg += $", {result.Errors} Fehler"; _trayIcon.ShowBalloonTip(3000, "Starface Sync", msg, result.Errors > 0 ? ToolTipIcon.Warning : ToolTipIcon.Info); SetStatus(msg); } catch (Exception ex) { _trayIcon.ShowBalloonTip(3000, "Starface Sync Fehler", ex.Message, ToolTipIcon.Error); SetStatus($"Fehler: {ex.Message}"); } } private void SetStatus(string text) { if (InvokeRequired) Invoke(new Action(() => _statusLabel.Text = text)); else _statusLabel.Text = text; } private void ShowSettings() { using (var settings = new SettingsForm()) { settings.ShowDialog(this); } } private void ShowAbout() { using (var about = new AboutForm()) { about.ShowDialog(this); } } private void ExitApplication() { _autoSyncTimer?.Stop(); _trayIcon.Visible = false; _trayIcon.Dispose(); Application.Exit(); } protected override void OnFormClosing(FormClosingEventArgs e) { if (e.CloseReason == CloseReason.UserClosing) { e.Cancel = true; Hide(); // In den Tray minimieren _trayIcon.ShowBalloonTip(2000, "Starface Kontakt-Sync", "Laeuft im Hintergrund weiter. Rechtsklick auf das Tray-Icon fuer Optionen.", ToolTipIcon.Info); } else { base.OnFormClosing(e); } } protected override void Dispose(bool disposing) { if (disposing) { _autoSyncTimer?.Dispose(); _trayIcon?.Dispose(); _trayMenu?.Dispose(); } base.Dispose(disposing); } } }