feat: add restore and delete actions

This commit is contained in:
dscyrescotti
2024-06-30 01:02:37 +07:00
parent 63a619edf9
commit 542d3ea9d6
4 changed files with 92 additions and 22 deletions

View File

@@ -10,6 +10,7 @@ import SwiftUI
struct DashboardView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@State var memo: MemoObject?
@State var sidebarItem: SidebarItem? = .memos
var body: some View {
@@ -18,12 +19,21 @@ struct DashboardView: View {
} detail: {
switch sidebarItem {
case .memos:
MemosView()
MemosView(memo: $memo)
case .trash:
TrashView()
TrashView(memo: $memo, sidebarItem: $sidebarItem)
default:
MemosView()
MemosView(memo: $memo)
}
}
.fullScreenCover(item: $memo) { memo in
MemoView(memo: memo)
.onDisappear {
withPersistence(\.viewContext) { context in
try context.saveIfNeeded()
context.refreshAllObjects()
}
}
}
}
}

View File

@@ -12,10 +12,11 @@ struct MemosView: View {
@FetchRequest var memoObjects: FetchedResults<MemoObject>
@State var memo: MemoObject?
@State var query: String = ""
@State var currentDate: Date = .now
@Binding var memo: MemoObject?
@AppStorage("memola.memo-objects.memos.sort") var sort: Sort = .recent
@AppStorage("memola.memo-objects.memos.filter") var filter: Filter = .none
@@ -25,7 +26,8 @@ struct MemosView: View {
query.isEmpty ? .memoEmpty : .memoNotFound
}
init() {
init(memo: Binding<MemoObject?>) {
_memo = memo
let standard = UserDefaults.standard
var descriptors: [SortDescriptor<MemoObject>] = []
var predicates: [NSPredicate] = [NSPredicate(format: "isTrash = NO")]
@@ -115,15 +117,6 @@ struct MemosView: View {
}
}
}
.fullScreenCover(item: $memo) { memo in
MemoView(memo: memo)
.onDisappear {
withPersistence(\.viewContext) { context in
try context.saveIfNeeded()
context.refreshAllObjects()
}
}
}
.onChange(of: sort) { oldValue, newValue in
memoObjects.sortDescriptors = newValue.memoSortDescriptors
}

View File

@@ -13,18 +13,35 @@ struct TrashView: View {
@FetchRequest var memoObjects: FetchedResults<MemoObject>
@State var query: String = ""
@State var restoredMemo: MemoObject?
@State var deletedMemo: MemoObject?
@Binding var memo: MemoObject?
@Binding var sidebarItem: SidebarItem?
var placeholder: Placeholder.Info {
query.isEmpty ? .trashEmpty : .trashNotFound
}
init() {
init(memo: Binding<MemoObject?>, sidebarItem: Binding<SidebarItem?>) {
_memo = memo
_sidebarItem = sidebarItem
let descriptors = [SortDescriptor(\MemoObject.deletedAt, order: .reverse)]
let predicate = NSPredicate(format: "isTrash = YES")
_memoObjects = FetchRequest(sortDescriptors: descriptors, predicate: predicate)
}
var body: some View {
let restoresMemo = Binding<Bool> {
restoredMemo != nil
} set: { _ in
restoredMemo = nil
}
let deletesMemo = Binding<Bool> {
deletedMemo != nil
} set: { _ in
deletedMemo = nil
}
MemoGrid(memoObjects: memoObjects, placeholder: placeholder) { memoObject in
memoCard(memoObject)
}
@@ -48,6 +65,31 @@ struct TrashView: View {
.onChange(of: query) { oldValue, newValue in
updatePredicate()
}
.alert("Restore Memo", isPresented: restoresMemo) {
Button {
restoreMemo(for: restoredMemo)
} label: {
Text("Restore")
}
Button {
restoreAndOpenMemo(for: restoredMemo)
} label: {
Text("Restore and Open")
}
Button("Cancel", role: .cancel) { }
} message: {
Text("Would you like to restore this memo or restore and open it?")
}
.alert("Delete Memo Permanently", isPresented: deletesMemo) {
Button(role: .destructive) {
deleteMemo(for: deletedMemo)
} label: {
Text("Delete")
}
Button("Cancel", role: .cancel) { }
} message: {
Text("Are you sure you want to permanently delete this memo? This action cannot be undone.")
}
}
func memoCard(_ memoObject: MemoObject) -> some View {
@@ -55,23 +97,25 @@ struct TrashView: View {
card
.contextMenu {
Button {
restoreMemo(for: memoObject)
} label: {
Label("Restore", systemImage: "square.and.arrow.down")
}
Button(role: .destructive) {
deletedMemo = memoObject
} label: {
Label("Delete Permanently", systemImage: "trash")
}
}
} details: {
Text("Deleted on \(memoObject.deletedAt.formatted(date: .abbreviated, time: .standard))")
.font(.caption)
.foregroundStyle(.secondary)
if let deletedAt = memoObject.deletedAt {
Text("Deleted on \(deletedAt.formatted(date: .abbreviated, time: .standard))")
.font(.caption)
.foregroundStyle(.secondary)
}
}
.onTapGesture {
restoredMemo = memoObject
}
}
@@ -82,4 +126,27 @@ struct TrashView: View {
}
memoObjects.nsPredicate = NSCompoundPredicate(type: .and, subpredicates: predicates)
}
func restoreMemo(for memo: MemoObject?) {
guard let memo else { return }
memo.isTrash = false
memo.deletedAt = nil
withPersistence(\.viewContext) { context in
try context.saveIfNeeded()
}
}
func restoreAndOpenMemo(for memo: MemoObject?) {
restoreMemo(for: memo)
self.sidebarItem = .memos
self.memo = memo
}
func deleteMemo(for memo: MemoObject?) {
guard let memo else { return }
withPersistenceSync(\.viewContext) { context in
context.delete(memo)
try context.saveIfNeeded()
}
}
}

View File

@@ -14,7 +14,7 @@ final class MemoObject: NSManagedObject, Identifiable {
@NSManaged var title: String
@NSManaged var createdAt: Date
@NSManaged var updatedAt: Date
@NSManaged var deletedAt: Date
@NSManaged var deletedAt: Date?
@NSManaged var isFavorite: Bool
@NSManaged var isTrash: Bool
@NSManaged var tool: ToolObject