starface-outlook-sync-addin/src/StarfaceOutlookSync/UI/MainForm.cs

405 lines
14 KiB
C#

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, _btnReset, _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);
Icon = AppIcon.GetIcon();
// 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 = "Synchronisieren", Width = 110, Height = 30 };
_btnSync.Click += async (s, e) => await SyncSelectedProfile();
_btnReset = new Button { Text = "Sync Reset", Width = 80, Height = 30 };
_btnReset.Click += (s, e) => ResetSync();
_btnSettings = new Button { Text = "Einstellungen", Width = 95, 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, _btnReset, _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();
_trayIcon = new NotifyIcon
{
Text = "Starface Kontakt-Sync",
Icon = AppIcon.GetSmallIcon(),
ContextMenuStrip = _trayMenu,
Visible = true
};
_trayIcon.DoubleClick += (s, e) => ShowMainWindow();
UpdateTrayMenu();
}
private void UpdateTrayMenu()
{
_trayMenu.Items.Clear();
_trayMenu.Items.Add("Oeffnen", null, (s, e) => ShowMainWindow());
_trayMenu.Items.Add("-");
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());
}
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
UpdateTrayMenu();
}
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 void ResetSync()
{
if (_profileList.SelectedItems.Count == 0)
{
MessageBox.Show("Bitte ein Profil auswaehlen.", "Sync Reset",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
var profile = _profileList.SelectedItems[0].Tag as SyncProfile;
if (profile == null) return;
var msg = $"Sync-Zuordnungen fuer '{profile.Name}' zuruecksetzen?\n\n" +
"Alle Kontakt-Verknuepfungen werden geloescht.\n" +
"Beim naechsten Sync werden die Kontakte neu abgeglichen.\n" +
"Es werden keine Kontakte geloescht.";
if (MessageBox.Show(msg, "Sync Reset",
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
_profileManager.SaveMappings(profile.Id, new List<SyncMapping>());
// LastSync auch zuruecksetzen
profile.LastSync = "";
_profileManager.UpdateProfile(profile);
RefreshProfileList();
MessageBox.Show("Sync-Zuordnungen wurden zurueckgesetzt.",
"Sync Reset", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
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);
}
}
}