Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions Networking/NoteSessionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -515,13 +515,13 @@ class NoteSessionManager {
}
}

func update(note: NoteProtocol, completion: SyncCompletionBlock? = nil) {
func update(note: NoteProtocol, updateModified: Bool = true, completion: SyncCompletionBlock? = nil) {
logger.notice("Updating note...")

var incoming = note
incoming.updateNeeded = true
if NoteSessionManager.isOnline {
updateOnServer(incoming) { [weak self] result in
updateOnServer(incoming, updateModified: updateModified) { [weak self] result in
switch result {
case .success( _):
completion?()
Expand All @@ -538,11 +538,14 @@ class NoteSessionManager {
}
}

fileprivate func updateOnServer(_ note: NoteProtocol, handler: @escaping SyncHandler) {
fileprivate func updateOnServer(_ note: NoteProtocol, updateModified: Bool = true, handler: @escaping SyncHandler) {
// Metadata-only changes (e.g. toggling favorite) keep the existing modification date so the note does
// not jump to the top of a date-sorted list and the row is not re-sorted a second time after the sync.
let modified = updateModified ? Date().timeIntervalSince1970 : note.modified
let parameters: Parameters = ["title": note.title as Any,
"content": note.content as Any,
"category": note.category as Any,
"modified": Date().timeIntervalSince1970 as Any,
"modified": modified as Any,
"favorite": note.favorite]
let router = Router.updateNote(id: Int(note.id), paramters: parameters)
session
Expand Down
3 changes: 3 additions & 0 deletions iOCNotes/Views/NotesListModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,15 @@ final class NotesListModel: NSObject, NSFetchedResultsControllerDelegate {
request.predicate = predicate(for: searchText)

if groupByCategory {
// "category" must stay first so it matches the section key path; favorites float to the top within each category.
request.sortDescriptors = [
NSSortDescriptor(key: "category", ascending: true),
NSSortDescriptor(key: "favorite", ascending: false),
NSSortDescriptor(key: "modified", ascending: false)
]
} else {
request.sortDescriptors = [
NSSortDescriptor(key: "favorite", ascending: false),
NSSortDescriptor(key: "modified", ascending: false)
]
}
Expand Down
28 changes: 28 additions & 0 deletions iOCNotes/Views/NotesListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ struct NotesListView: View {
.contextMenu {
contextMenu(for: note)
}
.swipeActions(edge: .leading) {
Button {
toggleFavorite(note)
} label: {
favoriteLabel(for: note)
}
.tint(.yellow)
}
.swipeActions(edge: .trailing) {
Button(role: .destructive) {
delete(note)
Expand Down Expand Up @@ -111,6 +119,12 @@ struct NotesListView: View {
}
}

Button {
toggleFavorite(note)
} label: {
favoriteLabel(for: note)
}

Button {
NotesPresenter.share(note: note, exporter: &exporter)
} label: {
Expand All @@ -131,10 +145,24 @@ struct NotesListView: View {
)
}

@ViewBuilder
private func favoriteLabel(for note: Note) -> some View {
if note.favorite {
Label(String(localized: "Remove from Favorites", comment: "Action to unmark a note as favorite"), systemImage: "star.slash")
} else {
Label(String(localized: "Favorite", comment: "Action to mark a note as favorite"), systemImage: "star")
}
}

private func delete(_ note: Note) {
NoteSessionManager.shared.delete(note: note)
}

private func toggleFavorite(_ note: Note) {
note.favorite.toggle()
NoteSessionManager.shared.update(note: note, updateModified: false, completion: nil)
}

private func commitRename() {
guard let note = noteToRename else { return }
defer { noteToRename = nil }
Expand Down