mirror of
https://github.com/dscyrescotti/Memola.git
synced 2026-05-17 05:07:11 +02:00
feat: add memo grid view
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user