feat: add memo grid view

This commit is contained in:
dscyrescotti
2024-05-07 13:20:21 +07:00
parent bad8d40f65
commit 8fb98f4f76
4 changed files with 113 additions and 30 deletions

View File

@@ -11,8 +11,7 @@ import SwiftUI
struct MemolaApp: App { struct MemolaApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
MemoView() MemosView()
.environmentObject(Canvas())
.environment(\.managedObjectContext, Persistence.shared.viewContext) .environment(\.managedObjectContext, Persistence.shared.viewContext)
} }
} }

View File

@@ -58,16 +58,16 @@ final class Canvas: NSObject, ObservableObject, Identifiable, Codable, GraphicCo
// MARK: - Actions // MARK: - Actions
extension Canvas { extension Canvas {
func load() { func load() {
// guard let graphicLoader else { return } guard let graphicLoader else { return }
Task(priority: .high) { [unowned self, graphicLoader] in Task(priority: .high) { [unowned self, graphicLoader] in
await MainActor.run { await MainActor.run {
self.state = .loading self.state = .loading
} }
do { do {
// let graphicContext = try graphicLoader() let graphicContext = try graphicLoader()
graphicContext.delegate = self graphicContext.delegate = self
await MainActor.run { await MainActor.run {
// self.graphicContext = graphicContext self.graphicContext = graphicContext
self.state = .loaded self.state = .loaded
} }
} catch { } catch {
@@ -91,11 +91,11 @@ extension Canvas {
} }
func listen(on managedObjectContext: NSManagedObjectContext) { func listen(on managedObjectContext: NSManagedObjectContext) {
Task(priority: .background) { [unowned self] in // Task(priority: .utility) { [unowned self] in
for await _ in didUpdate.values { // for await _ in didUpdate.throttle(for: 500, scheduler: DispatchQueue.global(qos: .utility), latest: false).values {
await save(on: managedObjectContext) // await save(on: managedObjectContext)
} // }
} // }
} }
} }

View File

@@ -29,7 +29,7 @@ struct MemoView: View {
} }
.overlay(alignment: .topLeading) { .overlay(alignment: .topLeading) {
Button { Button {
dismiss() closeMemo()
} label: { } label: {
Image(systemName: "xmark") Image(systemName: "xmark")
.padding(15) .padding(15)
@@ -39,16 +39,15 @@ struct MemoView: View {
.hoverEffect(.lift) .hoverEffect(.lift)
.padding() .padding()
} }
.disabled(canvas.state == .loading) .disabled(canvas.state == .loading || canvas.state == .closing)
.overlay { .overlay {
if canvas.state == .loading { switch canvas.state {
ProgressView { case .loading:
Text("Loading memo...") progressView("Loading memo...")
} case .closing:
.progressViewStyle(.circular) progressView("Saving memo...")
.padding(20) default:
.background(.regularMaterial) EmptyView()
.clipShape(RoundedRectangle(cornerRadius: 20))
} }
} }
.environmentObject(tool) .environmentObject(tool)
@@ -80,4 +79,27 @@ struct MemoView: View {
.background(.regularMaterial) .background(.regularMaterial)
.clipShape(RoundedRectangle(cornerRadius: 20)) .clipShape(RoundedRectangle(cornerRadius: 20))
} }
func progressView(_ title: String) -> some View {
ProgressView {
Text(title)
}
.progressViewStyle(.circular)
.padding(20)
.background(.regularMaterial)
.clipShape(RoundedRectangle(cornerRadius: 20))
}
func closeMemo() {
Task(priority: .high) {
await MainActor.run {
canvas.state = .closing
}
await canvas.save(on: managedObjectContext)
await MainActor.run {
canvas.state = .closed
dismiss()
}
}
}
} }

View File

@@ -8,18 +8,80 @@
import SwiftUI import SwiftUI
struct MemosView: View { struct MemosView: View {
@State var isPresented: Bool = false @Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(sortDescriptors: []) var memos: FetchedResults<Memo>
@State var canvas: Canvas?
var body: some View { var body: some View {
VStack { NavigationStack {
Text("Memos View") memoGrid
Button { .navigationTitle("Memos")
isPresented.toggle() .toolbar {
} label: { ToolbarItem(placement: .primaryAction) {
Text("Open Memo") Button {
} createMemo(title: "Untitled")
.fullScreenCover(isPresented: $isPresented) { } label: {
MemoView() Image(systemName: "plus")
}
.hoverEffect()
}
}
}
.fullScreenCover(item: $canvas) { canvas in
MemoView()
.environmentObject(canvas)
}
}
var memoGrid: some View {
ScrollView {
LazyVGrid(columns: .init(repeating: GridItem(.flexible()), count: 3)) {
ForEach(memos) { memo in
memoCard(memo)
}
} }
.padding()
}
}
func memoCard(_ memo: Memo) -> some View {
VStack(alignment: .leading) {
Rectangle()
.frame(height: 150)
Text(memo.title)
}
.onTapGesture {
openMemo(for: memo)
}
}
func createMemo(title: String) {
do {
let data = try JSONEncoder().encode(Canvas())
let memo = Memo(context: managedObjectContext)
memo.id = UUID()
memo.title = title
memo.data = data
memo.createdAt = .now
memo.updatedAt = .now
try managedObjectContext.save()
openMemo(for: memo)
} catch {
NSLog("[SketchNote] - \(error.localizedDescription)")
}
}
func openMemo(for memo: Memo) {
do {
let data = memo.data
let canvas = try JSONDecoder().decode(Canvas.self, from: data)
canvas.memo = memo
self.canvas = canvas
} catch {
NSLog("[SketchNote] - \(error.localizedDescription)")
} }
} }
} }