|
@@ -21,7 +21,7 @@ private struct NoteCollection: Identifiable, Hashable {
|
|
|
let kind: Kind
|
|
let kind: Kind
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-private struct Note: Identifiable, Equatable, Hashable {
|
|
|
|
|
|
|
+struct Note: Identifiable, Equatable, Hashable, Codable {
|
|
|
let id: UUID
|
|
let id: UUID
|
|
|
var title: String
|
|
var title: String
|
|
|
var body: String
|
|
var body: String
|
|
@@ -45,8 +45,7 @@ struct NotesAppRootView: View {
|
|
|
@State private var selectedNoteID: UUID? = nil
|
|
@State private var selectedNoteID: UUID? = nil
|
|
|
@State private var editorFocus: EditorFocusField? = nil
|
|
@State private var editorFocus: EditorFocusField? = nil
|
|
|
|
|
|
|
|
- // Keep this local for now: the goal is to design/match the UI.
|
|
|
|
|
- @State private var notes: [Note] = []
|
|
|
|
|
|
|
+ @StateObject private var store = NotesStore()
|
|
|
|
|
|
|
|
private var collections: [NoteCollection] = [
|
|
private var collections: [NoteCollection] = [
|
|
|
NoteCollection(id: NotesAppRootView.defaultCollectionID, provider: .iCloud, name: "Notes", kind: .notes),
|
|
NoteCollection(id: NotesAppRootView.defaultCollectionID, provider: .iCloud, name: "Notes", kind: .notes),
|
|
@@ -68,11 +67,11 @@ struct NotesAppRootView: View {
|
|
|
} else {
|
|
} else {
|
|
|
switch selectedCollection.kind {
|
|
switch selectedCollection.kind {
|
|
|
case .notes:
|
|
case .notes:
|
|
|
- scoped = notes.filter { !$0.isDeleted && !$0.isArchived }
|
|
|
|
|
|
|
+ scoped = store.notes.filter { !$0.isDeleted && !$0.isArchived }
|
|
|
case .archive:
|
|
case .archive:
|
|
|
- scoped = notes.filter { !$0.isDeleted && $0.isArchived }
|
|
|
|
|
|
|
+ scoped = store.notes.filter { !$0.isDeleted && $0.isArchived }
|
|
|
case .recentlyDeleted:
|
|
case .recentlyDeleted:
|
|
|
- scoped = notes.filter { $0.isDeleted }
|
|
|
|
|
|
|
+ scoped = store.notes.filter { $0.isDeleted }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -97,46 +96,46 @@ struct NotesAppRootView: View {
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
selectedCollectionID = NotesAppRootView.defaultCollectionID
|
|
selectedCollectionID = NotesAppRootView.defaultCollectionID
|
|
|
- notes.insert(newNote, at: 0)
|
|
|
|
|
|
|
+ store.notes.insert(newNote, at: 0)
|
|
|
selectedNoteID = newNote.id
|
|
selectedNoteID = newNote.id
|
|
|
editorFocus = .title
|
|
editorFocus = .title
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private var canDeleteSelectedNote: Bool {
|
|
private var canDeleteSelectedNote: Bool {
|
|
|
guard let selectedNoteID else { return false }
|
|
guard let selectedNoteID else { return false }
|
|
|
- return notes.contains { $0.id == selectedNoteID }
|
|
|
|
|
|
|
+ return store.notes.contains { $0.id == selectedNoteID }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private var canMoveToRecentlyDeleted: Bool {
|
|
private var canMoveToRecentlyDeleted: Bool {
|
|
|
guard let selectedCollection else { return false }
|
|
guard let selectedCollection else { return false }
|
|
|
guard let selectedNoteID else { return false }
|
|
guard let selectedNoteID else { return false }
|
|
|
- guard let note = notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
|
|
|
|
+ guard let note = store.notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
if note.isDeleted { return false }
|
|
if note.isDeleted { return false }
|
|
|
return selectedCollection.kind == .notes || selectedCollection.kind == .archive
|
|
return selectedCollection.kind == .notes || selectedCollection.kind == .archive
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private func moveSelectedNoteToRecentlyDeleted() {
|
|
private func moveSelectedNoteToRecentlyDeleted() {
|
|
|
guard let selectedNoteID else { return }
|
|
guard let selectedNoteID else { return }
|
|
|
- guard let index = notes.firstIndex(where: { $0.id == selectedNoteID }) else { return }
|
|
|
|
|
|
|
+ guard let index = store.notes.firstIndex(where: { $0.id == selectedNoteID }) else { return }
|
|
|
|
|
|
|
|
- notes[index].isDeleted = true
|
|
|
|
|
- notes[index].deletedAt = Date()
|
|
|
|
|
|
|
+ store.notes[index].isDeleted = true
|
|
|
|
|
+ store.notes[index].deletedAt = Date()
|
|
|
|
|
|
|
|
selectedCollectionID = NotesAppRootView.recentlyDeletedCollectionID
|
|
selectedCollectionID = NotesAppRootView.recentlyDeletedCollectionID
|
|
|
- self.selectedNoteID = notes[index].id
|
|
|
|
|
|
|
+ self.selectedNoteID = store.notes[index].id
|
|
|
editorFocus = nil
|
|
editorFocus = nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private var canPermanentlyDeleteSelectedNote: Bool {
|
|
private var canPermanentlyDeleteSelectedNote: Bool {
|
|
|
guard let selectedCollection else { return false }
|
|
guard let selectedCollection else { return false }
|
|
|
guard let selectedNoteID else { return false }
|
|
guard let selectedNoteID else { return false }
|
|
|
- guard let note = notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
|
|
|
|
+ guard let note = store.notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
return selectedCollection.kind == .recentlyDeleted && note.isDeleted
|
|
return selectedCollection.kind == .recentlyDeleted && note.isDeleted
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private func permanentlyDeleteSelectedNote() {
|
|
private func permanentlyDeleteSelectedNote() {
|
|
|
guard let selectedNoteID else { return }
|
|
guard let selectedNoteID else { return }
|
|
|
- notes.removeAll { $0.id == selectedNoteID }
|
|
|
|
|
|
|
+ store.notes.removeAll { $0.id == selectedNoteID }
|
|
|
self.selectedNoteID = nil
|
|
self.selectedNoteID = nil
|
|
|
editorFocus = nil
|
|
editorFocus = nil
|
|
|
}
|
|
}
|
|
@@ -144,29 +143,29 @@ struct NotesAppRootView: View {
|
|
|
private var canRestoreSelectedNote: Bool {
|
|
private var canRestoreSelectedNote: Bool {
|
|
|
guard let selectedCollection else { return false }
|
|
guard let selectedCollection else { return false }
|
|
|
guard let selectedNoteID else { return false }
|
|
guard let selectedNoteID else { return false }
|
|
|
- guard let note = notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
|
|
|
|
+ guard let note = store.notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
return selectedCollection.kind == .recentlyDeleted && note.isDeleted
|
|
return selectedCollection.kind == .recentlyDeleted && note.isDeleted
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private func restoreSelectedNote() {
|
|
private func restoreSelectedNote() {
|
|
|
guard let selectedNoteID else { return }
|
|
guard let selectedNoteID else { return }
|
|
|
- guard let index = notes.firstIndex(where: { $0.id == selectedNoteID }) else { return }
|
|
|
|
|
|
|
+ guard let index = store.notes.firstIndex(where: { $0.id == selectedNoteID }) else { return }
|
|
|
|
|
|
|
|
- notes[index].isDeleted = false
|
|
|
|
|
- notes[index].deletedAt = nil
|
|
|
|
|
|
|
+ store.notes[index].isDeleted = false
|
|
|
|
|
+ store.notes[index].deletedAt = nil
|
|
|
|
|
|
|
|
- if notes[index].isArchived {
|
|
|
|
|
|
|
+ if store.notes[index].isArchived {
|
|
|
selectedCollectionID = NotesAppRootView.archiveCollectionID
|
|
selectedCollectionID = NotesAppRootView.archiveCollectionID
|
|
|
} else {
|
|
} else {
|
|
|
selectedCollectionID = NotesAppRootView.defaultCollectionID
|
|
selectedCollectionID = NotesAppRootView.defaultCollectionID
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- self.selectedNoteID = notes[index].id
|
|
|
|
|
|
|
+ self.selectedNoteID = store.notes[index].id
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private var canArchiveSelectedNote: Bool {
|
|
private var canArchiveSelectedNote: Bool {
|
|
|
guard let selectedNoteID else { return false }
|
|
guard let selectedNoteID else { return false }
|
|
|
- guard let note = notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
|
|
|
|
+ guard let note = store.notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
guard let selectedCollection else { return false }
|
|
guard let selectedCollection else { return false }
|
|
|
if note.isDeleted { return false }
|
|
if note.isDeleted { return false }
|
|
|
return selectedCollection.kind == .notes && !note.isArchived
|
|
return selectedCollection.kind == .notes && !note.isArchived
|
|
@@ -174,17 +173,17 @@ struct NotesAppRootView: View {
|
|
|
|
|
|
|
|
private func archiveSelectedNote() {
|
|
private func archiveSelectedNote() {
|
|
|
guard let selectedNoteID else { return }
|
|
guard let selectedNoteID else { return }
|
|
|
- guard let index = notes.firstIndex(where: { $0.id == selectedNoteID }) else { return }
|
|
|
|
|
|
|
+ guard let index = store.notes.firstIndex(where: { $0.id == selectedNoteID }) else { return }
|
|
|
|
|
|
|
|
- notes[index].isArchived = true
|
|
|
|
|
|
|
+ store.notes[index].isArchived = true
|
|
|
selectedCollectionID = NotesAppRootView.archiveCollectionID
|
|
selectedCollectionID = NotesAppRootView.archiveCollectionID
|
|
|
- self.selectedNoteID = notes[index].id
|
|
|
|
|
|
|
+ self.selectedNoteID = store.notes[index].id
|
|
|
editorFocus = nil
|
|
editorFocus = nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private var canUnarchiveSelectedNote: Bool {
|
|
private var canUnarchiveSelectedNote: Bool {
|
|
|
guard let selectedNoteID else { return false }
|
|
guard let selectedNoteID else { return false }
|
|
|
- guard let note = notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
|
|
|
|
+ guard let note = store.notes.first(where: { $0.id == selectedNoteID }) else { return false }
|
|
|
guard let selectedCollection else { return false }
|
|
guard let selectedCollection else { return false }
|
|
|
if note.isDeleted { return false }
|
|
if note.isDeleted { return false }
|
|
|
return selectedCollection.kind == .archive && note.isArchived
|
|
return selectedCollection.kind == .archive && note.isArchived
|
|
@@ -192,11 +191,11 @@ struct NotesAppRootView: View {
|
|
|
|
|
|
|
|
private func unarchiveSelectedNote() {
|
|
private func unarchiveSelectedNote() {
|
|
|
guard let selectedNoteID else { return }
|
|
guard let selectedNoteID else { return }
|
|
|
- guard let index = notes.firstIndex(where: { $0.id == selectedNoteID }) else { return }
|
|
|
|
|
|
|
+ guard let index = store.notes.firstIndex(where: { $0.id == selectedNoteID }) else { return }
|
|
|
|
|
|
|
|
- notes[index].isArchived = false
|
|
|
|
|
|
|
+ store.notes[index].isArchived = false
|
|
|
selectedCollectionID = NotesAppRootView.defaultCollectionID
|
|
selectedCollectionID = NotesAppRootView.defaultCollectionID
|
|
|
- self.selectedNoteID = notes[index].id
|
|
|
|
|
|
|
+ self.selectedNoteID = store.notes[index].id
|
|
|
editorFocus = nil
|
|
editorFocus = nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -204,7 +203,7 @@ struct NotesAppRootView: View {
|
|
|
NavigationSplitView {
|
|
NavigationSplitView {
|
|
|
SidebarView(
|
|
SidebarView(
|
|
|
collections: collections,
|
|
collections: collections,
|
|
|
- notes: notes,
|
|
|
|
|
|
|
+ notes: store.notes,
|
|
|
selectedCollectionID: $selectedCollectionID
|
|
selectedCollectionID: $selectedCollectionID
|
|
|
)
|
|
)
|
|
|
} content: {
|
|
} content: {
|
|
@@ -282,7 +281,7 @@ struct NotesAppRootView: View {
|
|
|
.background(Color(nsColor: .textBackgroundColor))
|
|
.background(Color(nsColor: .textBackgroundColor))
|
|
|
} detail: {
|
|
} detail: {
|
|
|
NoteEditorView(
|
|
NoteEditorView(
|
|
|
- notes: $notes,
|
|
|
|
|
|
|
+ notes: $store.notes,
|
|
|
selectedNoteID: selectedNoteID,
|
|
selectedNoteID: selectedNoteID,
|
|
|
focusField: $editorFocus
|
|
focusField: $editorFocus
|
|
|
)
|
|
)
|