From 2e90a5c8eb49f728a78ef66912f7df5013f8c52d Mon Sep 17 00:00:00 2001 From: dscyrescotti Date: Sun, 19 May 2024 17:28:35 +0700 Subject: [PATCH] feat: redesign memo tool bar --- Memola.xcodeproj/project.pbxproj | 12 +++ Memola/Features/Memo/Memo/MemoView.swift | 57 ++---------- Memola/Features/Memo/Toolbar/Toolbar.swift | 101 +++++++++++++++++++++ 3 files changed, 120 insertions(+), 50 deletions(-) create mode 100644 Memola/Features/Memo/Toolbar/Toolbar.swift diff --git a/Memola.xcodeproj/project.pbxproj b/Memola.xcodeproj/project.pbxproj index 6f98d97..dbdbf40 100644 --- a/Memola.xcodeproj/project.pbxproj +++ b/Memola.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ EC0D14242BF79C98009BFE5F /* MemolaModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14222BF79C98009BFE5F /* MemolaModel.xcdatamodeld */; }; EC0D14262BF7A8C9009BFE5F /* PenObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14252BF7A8C9009BFE5F /* PenObject.swift */; }; EC0D14282BF7BF20009BFE5F /* ContextMenuViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14272BF7BF20009BFE5F /* ContextMenuViewModifier.swift */; }; + EC1B783D2BFA0AC9005A34E2 /* Toolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1B783C2BFA0AC9005A34E2 /* Toolbar.swift */; }; EC3565522BEFC65F00A4E0BF /* NSManagedObjectContext++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3565512BEFC65F00A4E0BF /* NSManagedObjectContext++.swift */; }; EC3565542BEFC6AD00A4E0BF /* View++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3565532BEFC6AD00A4E0BF /* View++.swift */; }; EC3565562BEFC7B300A4E0BF /* NSManagedObject++.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3565552BEFC7B300A4E0BF /* NSManagedObject++.swift */; }; @@ -89,6 +90,7 @@ EC0D14232BF79C98009BFE5F /* MemolaModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MemolaModel.xcdatamodel; sourceTree = ""; }; EC0D14252BF7A8C9009BFE5F /* PenObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenObject.swift; sourceTree = ""; }; EC0D14272BF7BF20009BFE5F /* ContextMenuViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuViewModifier.swift; sourceTree = ""; }; + EC1B783C2BFA0AC9005A34E2 /* Toolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toolbar.swift; sourceTree = ""; }; EC3565512BEFC65F00A4E0BF /* NSManagedObjectContext++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext++.swift"; sourceTree = ""; }; EC3565532BEFC6AD00A4E0BF /* View++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View++.swift"; sourceTree = ""; }; EC3565552BEFC7B300A4E0BF /* NSManagedObject++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObject++.swift"; sourceTree = ""; }; @@ -199,6 +201,14 @@ path = Views; sourceTree = ""; }; + EC1B783B2BFA0AAC005A34E2 /* Toolbar */ = { + isa = PBXGroup; + children = ( + EC1B783C2BFA0AC9005A34E2 /* Toolbar.swift */, + ); + path = Toolbar; + sourceTree = ""; + }; EC5050042BF65CBC00B4D86E /* Core */ = { isa = PBXGroup; children = ( @@ -326,6 +336,7 @@ ECA7387B2BE5EF3500A4542E /* Memo */ = { isa = PBXGroup; children = ( + EC1B783B2BFA0AAC005A34E2 /* Toolbar */, EC5050082BF65D0500B4D86E /* Memo */, EC5050052BF65CCD00B4D86E /* PenDock */, ); @@ -691,6 +702,7 @@ ECA738B02BE60D0B00A4542E /* CanvasViewController.swift in Sources */, ECA738E42BE6110800A4542E /* Drawable.swift in Sources */, ECA738AD2BE60CC600A4542E /* DrawingView.swift in Sources */, + EC1B783D2BFA0AC9005A34E2 /* Toolbar.swift in Sources */, ECA738E02BE610B900A4542E /* EraserRenderPass.swift in Sources */, EC35655A2BF060D900A4E0BF /* Quad.metal in Sources */, ECA738912BE600F500A4542E /* Cache.metal in Sources */, diff --git a/Memola/Features/Memo/Memo/MemoView.swift b/Memola/Features/Memo/Memo/MemoView.swift index 53c2591..17edf02 100644 --- a/Memola/Features/Memo/Memo/MemoView.swift +++ b/Memola/Features/Memo/Memo/MemoView.swift @@ -9,16 +9,17 @@ import SwiftUI import CoreData struct MemoView: View { - @Environment(\.dismiss) var dismiss - @StateObject var tool: Tool @StateObject var canvas: Canvas @StateObject var history = History() - let memo: MemoObject + @State var memo: MemoObject + @State var title: String + @FocusState var textFieldState: Bool init(memo: MemoObject) { self.memo = memo + self.title = memo.title self._tool = StateObject(wrappedValue: Tool(object: memo.tool)) self._canvas = StateObject(wrappedValue: Canvas(size: memo.canvas.size, canvasID: memo.canvas.objectID)) } @@ -26,27 +27,14 @@ struct MemoView: View { var body: some View { CanvasView() .ignoresSafeArea() - .overlay(alignment: .topTrailing) { - historyTool - .padding() - } .overlay(alignment: .trailing) { PenDockView() .frame(maxHeight: .infinity) .padding() } - .overlay(alignment: .topLeading) { - Button { - closeMemo() - } label: { - Image(systemName: "xmark") - .contentShape(.circle) - .padding(15) - .background(.regularMaterial) - .clipShape(RoundedRectangle(cornerRadius: 20)) - } - .hoverEffect(.lift) - .padding() + .disabled(textFieldState) + .overlay(alignment: .top) { + Toolbar(memo: memo) } .disabled(canvas.state == .loading || canvas.state == .closing) .overlay { @@ -64,30 +52,6 @@ struct MemoView: View { .environmentObject(history) } - var historyTool: some View { - HStack { - Button { - history.historyPublisher.send(.undo) - } label: { - Image(systemName: "arrow.uturn.backward.circle") - .contentShape(.circle) - } - .hoverEffect(.lift) - .disabled(history.undoDisabled) - Button { - history.historyPublisher.send(.redo) - } label: { - Image(systemName: "arrow.uturn.forward.circle") - .contentShape(.circle) - } - .hoverEffect(.lift) - .disabled(history.redoDisabled) - } - .padding(15) - .background(.regularMaterial) - .clipShape(RoundedRectangle(cornerRadius: 20)) - } - func progressView(_ title: String) -> some View { ProgressView { Text(title) @@ -97,11 +61,4 @@ struct MemoView: View { .background(.regularMaterial) .clipShape(RoundedRectangle(cornerRadius: 20)) } - - func closeMemo() { - withPersistenceSync(\.viewContext) { context in - try context.saveIfNeeded() - } - dismiss() - } } diff --git a/Memola/Features/Memo/Toolbar/Toolbar.swift b/Memola/Features/Memo/Toolbar/Toolbar.swift new file mode 100644 index 0000000..80a82de --- /dev/null +++ b/Memola/Features/Memo/Toolbar/Toolbar.swift @@ -0,0 +1,101 @@ +// +// Toolbar.swift +// Memola +// +// Created by Dscyre Scotti on 5/19/24. +// + +import SwiftUI +import Foundation + +struct Toolbar: View { + @Environment(\.dismiss) var dismiss + + @EnvironmentObject var history: History + + @State var memo: MemoObject + @State var title: String + @FocusState var textFieldState: Bool + + init(memo: MemoObject) { + self.memo = memo + self.title = memo.title + } + + var body: some View { + HStack(spacing: 5) { + closeButton + titleField + Spacer() + historyTool + } + .font(.subheadline) + .padding(10) + } + + var closeButton: some View { + Button { + closeMemo() + } label: { + Image(systemName: "xmark") + .contentShape(.circle) + .padding(10) + .background(.regularMaterial) + .clipShape(.rect(cornerRadius: 8)) + } + .hoverEffect(.lift) + .disabled(textFieldState) + } + + var titleField: some View { + TextField("", text: $title) + .focused($textFieldState) + .textFieldStyle(.plain) + .padding(.vertical, 5) + .padding(.horizontal, 10) + .frame(width: 120) + .background(.regularMaterial) + .clipShape(.rect(cornerRadius: 8)) + .onChange(of: textFieldState) { oldValue, newValue in + if !newValue { + if !title.isEmpty { + memo.title = title + } else { + title = memo.title + } + } + } + } + + var historyTool: some View { + HStack { + Button { + history.historyPublisher.send(.undo) + } label: { + Image(systemName: "arrow.uturn.backward.circle") + .contentShape(.circle) + } + .hoverEffect(.lift) + .disabled(history.undoDisabled) + Button { + history.historyPublisher.send(.redo) + } label: { + Image(systemName: "arrow.uturn.forward.circle") + .contentShape(.circle) + } + .hoverEffect(.lift) + .disabled(history.redoDisabled) + } + .padding(10) + .background(.regularMaterial) + .clipShape(.rect(cornerRadius: 8)) + .disabled(textFieldState) + } + + func closeMemo() { + withPersistenceSync(\.viewContext) { context in + try context.saveIfNeeded() + } + dismiss() + } +}