public void KeepPinnedNotesToTheTop() { NoteRepositoryModel serverRepo = new NoteRepositoryModel(); NoteModel note101 = new NoteModel { IsPinned = true }; NoteModel note102 = new NoteModel(); NoteModel note103 = new NoteModel(); NoteModel note104 = new NoteModel(); serverRepo.Notes.Add(note101); serverRepo.Notes.Add(note102); serverRepo.Notes.Add(note103); serverRepo.Notes.Add(note104); NoteRepositoryModel clientRepo = new NoteRepositoryModel(); NoteModel note201 = note101.Clone(); // IsPinned == true NoteModel note202 = note102.Clone(); NoteModel note203 = note103.Clone(); NoteModel note204 = note104.Clone(); note204.IsPinned = true; note204.RefreshModifiedAt(); clientRepo.Notes.Add(note204); // User pinned note so it went to the top clientRepo.Notes.Add(note201); // Was already pinned clientRepo.Notes.Add(note203); // The new order of 202/203 where changed, but the remote repo has a newer order clientRepo.Notes.Add(note202); // Take order of server, but keep pinned to the top NoteRepositoryMerger merger = new NoteRepositoryMerger(); serverRepo.OrderModifiedAt = new DateTime(2000, 01, 02); // newer clientRepo.OrderModifiedAt = new DateTime(2000, 01, 01); NoteRepositoryModel result = merger.Merge(clientRepo, serverRepo); Assert.AreEqual(note204.Id, result.Notes[0].Id); Assert.AreEqual(note201.Id, result.Notes[1].Id); Assert.AreEqual(note202.Id, result.Notes[2].Id); Assert.AreEqual(note203.Id, result.Notes[3].Id); }
/// <inheritdoc/> public override async Task Run() { try { NoteRepositoryModel cloudRepository = StoryBoard.LoadFromSession <NoteRepositoryModel>(PullPushStorySessionKey.CloudRepository); _repositoryStorageService.LoadRepositoryOrDefault(out NoteRepositoryModel localRepository); SettingsModel settings = _settingsService.LoadSettingsOrDefault(); SerializeableCloudStorageCredentials credentials = settings.Credentials; NoteModel cloudNote = cloudRepository.Notes.FindById(_noteId); NoteModel localNote = localRepository.Notes.FindById(_noteId); if (localNote == null) { throw new Exception("PullPushStory is triggered on the note dialog, so the note must exist."); } if (cloudNote == null) { // Note does not yet exist in the cloud, or it was deleted permanently. Both // cases should be rejected. _feedbackService.ShowToast(_languageService["pushpull_error_no_cloud_note"]); return; } if (cloudNote.ModifiedAt == localNote.ModifiedAt) { // Notes are equal, nothing to sync _feedbackService.ShowToast(_languageService["pushpull_success"]); return; } // Merge repositories if (_direction == PullPushDirection.PullFromServer) { cloudNote.CloneTo(localNote); // this can possibly move the note to the recycling bin or reverse AddSafeToOtherRepositoryIfMissing(cloudRepository, localRepository, cloudNote.SafeId); _repositoryStorageService.TrySaveRepository(localRepository); } else { // Uploading explicitely can be seen as a confirmation that this version is the // most current one. So we make sure that the uploaded version is not overwritten // by other devices afterwards. localNote.RefreshModifiedAt(); _repositoryStorageService.TrySaveRepository(localRepository); localNote.CloneTo(cloudNote); // this can possibly move the note to the recycling bin or reverse AddSafeToOtherRepositoryIfMissing(localRepository, cloudRepository, localNote.SafeId); byte[] encryptedRepository = EncryptRepository( cloudRepository, settings.TransferCode, _cryptoRandomService, settings.SelectedEncryptionAlgorithm); ICloudStorageClient cloudStorageClient = _cloudStorageClientFactory.GetOrCreate(credentials.CloudStorageId); await cloudStorageClient.UploadFileAsync(Config.RepositoryFileName, encryptedRepository, credentials); } _feedbackService.ShowToast(_languageService["pushpull_success"]); } catch (Exception ex) { // Keep the current page open and show the error message ShowExceptionMessage(ex, _feedbackService, _languageService); } }