/// <param name="realnote">The real note in the repository (owned by UI Thread)</param> /// <param name="clonenote">The new note data</param> /// <param name="conflictnote">The conflicting note</param> private void ResolveUploadConflict(INote realnote, INote clonenote, INote conflictnote) { switch (conflictStrategy) { case ConflictResolutionStrategy.UseClientVersion: dispatcher.Invoke(() => { if (realnote.IsLocalSaved) { realnote.OnAfterUpload(clonenote); realnote.ResetRemoteDirty(); repo.SaveNote(realnote); _log.Warn("Sync", "Resolve conflict: UseClientVersion"); } else { _log.Warn("Sync", "Resolve conflict: UseClientVersion (do nothing cause note changed locally)"); } }); break; case ConflictResolutionStrategy.UseServerVersion: dispatcher.Invoke(() => { realnote.ApplyUpdatedData(clonenote); realnote.TriggerOnChanged(true); realnote.SetLocalDirty(); realnote.ResetRemoteDirty(); repo.SaveNote(realnote); _log.Warn("Sync", "Resolve conflict: UseServerVersion"); }); break; case ConflictResolutionStrategy.UseClientCreateConflictFile: dispatcher.Invoke(() => { if (realnote.IsLocalSaved) { realnote.OnAfterUpload(clonenote); realnote.ResetRemoteDirty(); repo.SaveNote(realnote); } else { _log.Warn("Sync", "Resolve conflict: UseClientCreateConflictFile (do not [OnAfterUpload] cause note changed locally)"); } var conflict = repo.CreateNewNote(conflictnote.Path); conflict.Title = string.Format("{0}_conflict-{1:yyyy-MM-dd_HH:mm:ss}", conflictnote.Title, DateTime.Now); conflict.Text = conflictnote.Text; conflict.Tags.Synchronize(conflictnote.Tags); conflict.IsConflictNote = true; repo.SaveNote(conflict); _log.Warn("Sync", "Resolve conflict: UseClientCreateConflictFile (conflictnote: " + conflict.UniqueName + ")"); }); break; case ConflictResolutionStrategy.UseServerCreateConflictFile: dispatcher.Invoke(() => { realnote.ApplyUpdatedData(clonenote); realnote.TriggerOnChanged(true); realnote.SetLocalDirty(); realnote.ResetRemoteDirty(); repo.SaveNote(realnote); var conflict = repo.CreateNewNote(conflictnote.Path); conflict.Title = string.Format("{0}_conflict-{1:yyyy-MM-dd_HH:mm:ss}", conflictnote.Title, DateTime.Now); conflict.Text = conflictnote.Text; conflict.Tags.Synchronize(conflictnote.Tags); conflict.IsConflictNote = true; repo.SaveNote(conflict); _log.Warn("Sync", "Resolve conflict: UseServerCreateConflictFile (conflictnote: " + conflict.UniqueName + ")"); }); break; case ConflictResolutionStrategy.ManualMerge: dispatcher.Invoke(() => { if (realnote.IsLocalSaved) { realnote.OnAfterUpload(clonenote); realnote.ResetRemoteDirty(); repo.SaveNote(realnote); } else { _log.Warn("Sync", "Resolve conflict: ManualMerge (do not [OnAfterUpload] cause note changed locally)"); } var txt0 = clonenote.Text; var txt1 = conflictnote.Text; var ttl0 = clonenote.Title; var ttl1 = conflictnote.Title; var tgs0 = clonenote.Tags.OrderBy(p => p).ToList(); var tgs1 = conflictnote.Tags.OrderBy(p => p).ToList(); var ndp0 = clonenote.Path; var ndp1 = conflictnote.Path; if (txt0 != txt1 || ttl0 != ttl1 || !tgs0.CollectionEquals(tgs1) || ndp0 != ndp1) { _log.Info( "Sync", "Resolve conflict: ManualMerge :: Show dialog", $"======== Title 1 ========\n{ttl0}\n\n======== Title 2 ========\n{ttl1}\n\n" + $"======== Text 1 ========\n{txt0}\n\n======== Text 2 ========\n{txt1}\n\n" + $"======== Tags 1 ========\n{string.Join(" | ", tgs0)}\n\n======== Tags 2 ========\n{string.Join(" | ", tgs1)}\n\n"); dispatcher.BeginInvoke(() => { repo.ShowConflictResolutionDialog(clonenote.UniqueName, txt0, ttl0, tgs0, ndp0, txt1, ttl1, tgs1, ndp1); }); } else { _log.Info("Sync", "Resolve conflict: ManualMerge not executed cause conflict==real"); } }); break; default: throw new ArgumentOutOfRangeException(); } }