Add cross-client conflict notifications (step 3)
Wird ein echter Feld-Konflikt aufgeloest, erfahren jetzt auch die ANDEREN Arbeitsplaetze davon - nicht nur der aufloesende Client. - ConflictNotice-Modell + ConflictNotifier: schreibt pro Konflikt eine Notiz in <shared>/conflicts/ (nach StarfaceId), liest beim Sync ungesehene Notizen zu eigenen Kontakten, zeigt sie als Tray-Hinweis und merkt sich gezeigte lokal (seen-conflicts.json). Veraltete Notizen (>7 Tage) werden aufgeraeumt. - MainForm: schreibt nach einem Sync mit Konflikten die Notizen und zeigt ausstehende Notizen anderer Clients (gefiltert auf eigene gemappte StarfaceIds). AcquireCrossClientLock nimmt jetzt das gemeinsame Verzeichnis als Parameter. - README/CHANGELOG aktualisiert. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ namespace StarfaceOutlookSync.UI
|
||||
{
|
||||
private readonly ProfileManager _profileManager = new ProfileManager();
|
||||
private readonly SyncEngine _syncEngine = new SyncEngine();
|
||||
private readonly ConflictNotifier _conflictNotifier = new ConflictNotifier();
|
||||
private NotifyIcon _trayIcon;
|
||||
private ContextMenuStrip _trayMenu;
|
||||
private ListView _profileList;
|
||||
@@ -349,10 +350,11 @@ namespace StarfaceOutlookSync.UI
|
||||
}
|
||||
|
||||
SyncLock crossLock = null;
|
||||
var sharedDir = UserSettings.Load().SharedDirectory;
|
||||
try
|
||||
{
|
||||
// Clientuebergreifende Sperre (falls gemeinsames Verzeichnis konfiguriert).
|
||||
crossLock = await AcquireCrossClientLock();
|
||||
crossLock = await AcquireCrossClientLock(sharedDir);
|
||||
if (crossLock == null)
|
||||
{
|
||||
SetStatus("Anderer Arbeitsplatz synchronisiert gerade - uebersprungen.");
|
||||
@@ -381,8 +383,14 @@ namespace StarfaceOutlookSync.UI
|
||||
detail += $"\n... und {result.Conflicts.Count - 5} weitere";
|
||||
_trayIcon.ShowBalloonTip(10000,
|
||||
$"Konflikt bei {result.Conflicts.Count} Kontakt(en)", detail, ToolTipIcon.Warning);
|
||||
|
||||
// Andere Arbeitsplaetze ueber das gemeinsame Verzeichnis informieren.
|
||||
_conflictNotifier.Write(sharedDir, result.Conflicts);
|
||||
}
|
||||
|
||||
// Konflikt-Hinweise von ANDEREN Arbeitsplaetzen (zu meinen Kontakten) anzeigen.
|
||||
ShowRemoteConflictNotices(sharedDir);
|
||||
|
||||
SetStatus(msg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -406,9 +414,8 @@ namespace StarfaceOutlookSync.UI
|
||||
/// Ist kein Verzeichnis konfiguriert oder es ist nicht erreichbar, wird
|
||||
/// ohne clientuebergreifende Sperre fortgefahren (lokaler Schutz bleibt).
|
||||
/// </summary>
|
||||
private async Task<SyncLock> AcquireCrossClientLock()
|
||||
private async Task<SyncLock> AcquireCrossClientLock(string dir)
|
||||
{
|
||||
var dir = UserSettings.Load().SharedDirectory;
|
||||
if (string.IsNullOrWhiteSpace(dir))
|
||||
return SyncLock.NoOp();
|
||||
|
||||
@@ -439,6 +446,43 @@ namespace StarfaceOutlookSync.UI
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zeigt Konflikt-Hinweise an, die andere Arbeitsplaetze ueber das
|
||||
/// gemeinsame Verzeichnis hinterlassen haben und Kontakte betreffen, die
|
||||
/// auch dieser Client gemappt hat.
|
||||
/// </summary>
|
||||
private void ShowRemoteConflictNotices(string sharedDir)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sharedDir)) return;
|
||||
try
|
||||
{
|
||||
var pending = _conflictNotifier.GetPending(sharedDir, AllMappedStarfaceIds());
|
||||
if (pending.Count == 0) return;
|
||||
|
||||
var detail = string.Join("\n", pending.Take(5).Select(p => p.ToString()));
|
||||
if (pending.Count > 5)
|
||||
detail += $"\n... und {pending.Count - 5} weitere";
|
||||
_trayIcon.ShowBalloonTip(10000,
|
||||
$"Konflikt an anderem Arbeitsplatz ({pending.Count})", detail, ToolTipIcon.Warning);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>Alle von diesem Client gemappten StarfaceIds (ueber alle Profile).</summary>
|
||||
private HashSet<string> AllMappedStarfaceIds()
|
||||
{
|
||||
var ids = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
try
|
||||
{
|
||||
foreach (var p in _profileManager.GetProfiles())
|
||||
foreach (var m in _profileManager.GetMappings(p.Id))
|
||||
if (!string.IsNullOrEmpty(m.StarfaceId))
|
||||
ids.Add(m.StarfaceId);
|
||||
}
|
||||
catch { }
|
||||
return ids;
|
||||
}
|
||||
|
||||
private void SetStatus(string text)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
|
||||
Reference in New Issue
Block a user