Rewrite as standalone C# WinForms app
Replace the Office Web Add-in with a native Windows application. The web add-in required Exchange/M365 for registration which is not available in all customer environments (standalone Office, POP/IMAP only). The new app: - Uses COM Interop to access Outlook contacts directly - Communicates with Starface REST API (accepts self-signed certs) - Runs as System Tray app with optional auto-sync - Profile-based config stored in %AppData% - No webserver, no certificates, no Exchange, no M365 needed - Inno Setup installer for clean MSI-style deployment - Works with any Outlook version (Classic and New) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using StarfaceOutlookSync.Models;
|
||||
using StarfaceOutlookSync.Services;
|
||||
|
||||
namespace StarfaceOutlookSync.UI
|
||||
{
|
||||
public class SyncProgressForm : Form
|
||||
{
|
||||
private readonly SyncProfile _profile;
|
||||
private readonly SyncEngine _engine = new SyncEngine();
|
||||
private TextBox _txtLog;
|
||||
private ProgressBar _progressBar;
|
||||
private Button _btnClose, _btnStart;
|
||||
private Label _lblResult;
|
||||
|
||||
public SyncProgressForm(SyncProfile profile)
|
||||
{
|
||||
_profile = profile;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
Text = $"Synchronisation - {_profile.Name}";
|
||||
Size = new Size(500, 400);
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
StartPosition = FormStartPosition.CenterParent;
|
||||
Font = new Font("Segoe UI", 9);
|
||||
|
||||
var infoLabel = new Label
|
||||
{
|
||||
Text = $"{_profile.StarfaceConnection.Host} ({_profile.StarfaceAddressBook.Name}) <-> {_profile.OutlookFolderName}",
|
||||
Left = 12, Top = 12, Width = 460, AutoSize = false, Height = 20
|
||||
};
|
||||
|
||||
_progressBar = new ProgressBar
|
||||
{
|
||||
Left = 12, Top = 38, Width = 460, Height = 22,
|
||||
Style = ProgressBarStyle.Marquee
|
||||
};
|
||||
|
||||
_txtLog = new TextBox
|
||||
{
|
||||
Left = 12, Top = 68, Width = 460, Height = 200,
|
||||
Multiline = true, ReadOnly = true, ScrollBars = ScrollBars.Vertical,
|
||||
BackColor = Color.FromArgb(30, 30, 30), ForeColor = Color.FromArgb(212, 212, 212),
|
||||
Font = new Font("Consolas", 9)
|
||||
};
|
||||
|
||||
_lblResult = new Label
|
||||
{
|
||||
Left = 12, Top = 276, Width = 460, Height = 40,
|
||||
AutoSize = false, ForeColor = Color.Gray
|
||||
};
|
||||
|
||||
_btnStart = new Button
|
||||
{
|
||||
Text = "Synchronisation starten", Left = 12, Top = 322, Width = 180, Height = 30
|
||||
};
|
||||
_btnStart.Click += async (s, e) => await RunSync();
|
||||
|
||||
_btnClose = new Button
|
||||
{
|
||||
Text = "Schliessen", Left = 380, Top = 322, Width = 90, Height = 30,
|
||||
DialogResult = DialogResult.Cancel
|
||||
};
|
||||
|
||||
Controls.AddRange(new Control[] { infoLabel, _progressBar, _txtLog, _lblResult, _btnStart, _btnClose });
|
||||
CancelButton = _btnClose;
|
||||
}
|
||||
|
||||
private void AppendLog(string message)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => AppendLog(message)));
|
||||
return;
|
||||
}
|
||||
_txtLog.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\r\n");
|
||||
}
|
||||
|
||||
private async Task RunSync()
|
||||
{
|
||||
_btnStart.Enabled = false;
|
||||
_btnClose.Enabled = false;
|
||||
_progressBar.Style = ProgressBarStyle.Marquee;
|
||||
_lblResult.Text = "";
|
||||
|
||||
_engine.OnProgress += AppendLog;
|
||||
|
||||
try
|
||||
{
|
||||
var result = await Task.Run(() => _engine.SyncProfileAsync(_profile));
|
||||
|
||||
_progressBar.Style = ProgressBarStyle.Blocks;
|
||||
_progressBar.Value = 100;
|
||||
|
||||
var resultText = $"Erstellt: {result.Created} | Aktualisiert: {result.Updated} | Fehler: {result.Errors}";
|
||||
_lblResult.Text = resultText;
|
||||
_lblResult.ForeColor = result.Errors > 0 ? Color.OrangeRed : Color.Green;
|
||||
|
||||
if (result.ErrorMessages.Count > 0)
|
||||
{
|
||||
AppendLog("--- Fehler ---");
|
||||
foreach (var err in result.ErrorMessages)
|
||||
AppendLog(err);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_lblResult.Text = $"Fehler: {ex.Message}";
|
||||
_lblResult.ForeColor = Color.Red;
|
||||
AppendLog($"FEHLER: {ex.Message}");
|
||||
}
|
||||
|
||||
_engine.OnProgress -= AppendLog;
|
||||
_btnStart.Enabled = true;
|
||||
_btnStart.Text = "Erneut synchronisieren";
|
||||
_btnClose.Enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user