From 6208c5d62e8be7a4f960dbac7f61556ed4b389e2 Mon Sep 17 00:00:00 2001 From: dscyrescotti Date: Mon, 20 May 2024 01:11:15 +0700 Subject: [PATCH] feat: add canvas lock button --- Memola/Canvas/Core/Canvas.swift | 1 + .../ViewController/CanvasViewController.swift | 11 +++++ Memola/Features/Memo/Memo/MemoView.swift | 45 ++++++++++--------- Memola/Features/Memo/PenDock/PenDock.swift | 18 +++++--- Memola/Features/Memo/Toolbar/Toolbar.swift | 37 +++++++++++++-- 5 files changed, 81 insertions(+), 31 deletions(-) diff --git a/Memola/Canvas/Core/Canvas.swift b/Memola/Canvas/Core/Canvas.swift index b0fda1c..b2787a0 100644 --- a/Memola/Canvas/Core/Canvas.swift +++ b/Memola/Canvas/Core/Canvas.swift @@ -29,6 +29,7 @@ final class Canvas: ObservableObject, Identifiable, @unchecked Sendable { @Published var state: State = .initial @Published var zoomScale: CGFloat = .zero + @Published var locksCanvas: Bool = false let zoomPublisher = PassthroughSubject() diff --git a/Memola/Canvas/View/Bridge/ViewController/CanvasViewController.swift b/Memola/Canvas/View/Bridge/ViewController/CanvasViewController.swift index 1f255d7..818c762 100644 --- a/Memola/Canvas/View/Bridge/ViewController/CanvasViewController.swift +++ b/Memola/Canvas/View/Bridge/ViewController/CanvasViewController.swift @@ -168,6 +168,12 @@ extension CanvasViewController { } .store(in: &cancellables) + canvas.$locksCanvas + .sink { [weak self] state in + self?.lockModeChanged(state) + } + .store(in: &cancellables) + tool.$selectedPen .sink { [weak self] pen in self?.penChanged(to: pen) @@ -308,6 +314,11 @@ extension CanvasViewController { func zoomChanged(_ zoomScale: CGFloat) { scrollView.setZoomScale(zoomScale, animated: true) } + + func lockModeChanged(_ state: Bool) { + scrollView.isScrollEnabled = !state + scrollView.pinchGestureRecognizer?.isEnabled = !state + } } extension CanvasViewController { diff --git a/Memola/Features/Memo/Memo/MemoView.swift b/Memola/Features/Memo/Memo/MemoView.swift index f1700fe..550b472 100644 --- a/Memola/Features/Memo/Memo/MemoView.swift +++ b/Memola/Features/Memo/Memo/MemoView.swift @@ -61,31 +61,34 @@ struct MemoView: View { let lowerBound: CGFloat = 10 let zoomScale: CGFloat = (((canvas.zoomScale - canvas.minimumZoomScale) * (upperBound - lowerBound) / (canvas.maximumZoomScale - canvas.minimumZoomScale)) + lowerBound).rounded() let zoomScales: [Int] = [400, 200, 100, 75, 50, 25, 10] - Menu { - ForEach(zoomScales, id: \.self) { scale in - Button { - let zoomScale = ((CGFloat(scale) - lowerBound) * (canvas.maximumZoomScale - canvas.minimumZoomScale) / (upperBound - lowerBound)) + canvas.minimumZoomScale - canvas.zoomPublisher.send(zoomScale) - } label: { - Label { - Text(scale, format: .percent) - } icon: { - if CGFloat(scale) == zoomScale { - Image(systemName: "checkmark") + if !canvas.locksCanvas { + Menu { + ForEach(zoomScales, id: \.self) { scale in + Button { + let zoomScale = ((CGFloat(scale) - lowerBound) * (canvas.maximumZoomScale - canvas.minimumZoomScale) / (upperBound - lowerBound)) + canvas.minimumZoomScale + canvas.zoomPublisher.send(zoomScale) + } label: { + Label { + Text(scale, format: .percent) + } icon: { + if CGFloat(scale) == zoomScale { + Image(systemName: "checkmark") + } } + .font(.headline) } - .font(.headline) } + } label: { + Text(zoomScale / 100, format: .percent) + .frame(width: 45) + .font(.subheadline) + .padding(.horizontal, size / 2.5) + .frame(height: size) + .background(.regularMaterial) + .clipShape(.rect(cornerRadius: 8)) + .padding(10) } - } label: { - Text(zoomScale / 100, format: .percent) - .frame(width: 45) - .font(.subheadline) - .padding(.horizontal, size / 2.5) - .frame(height: size) - .background(.regularMaterial) - .clipShape(.rect(cornerRadius: 8)) - .padding(10) + .transition(.move(edge: .bottom).combined(with: .blurReplace)) } } diff --git a/Memola/Features/Memo/PenDock/PenDock.swift b/Memola/Features/Memo/PenDock/PenDock.swift index e58c0ea..1e02b77 100644 --- a/Memola/Features/Memo/PenDock/PenDock.swift +++ b/Memola/Features/Memo/PenDock/PenDock.swift @@ -9,6 +9,7 @@ import SwiftUI struct PenDock: View { @EnvironmentObject var tool: Tool + @EnvironmentObject var canvas: Canvas let width: CGFloat = 90 let height: CGFloat = 30 @@ -18,13 +19,16 @@ struct PenDock: View { @State var opensColorPicker: Bool = false var body: some View { - VStack(alignment: .trailing) { - penPropertyTool - penItemList + if !canvas.locksCanvas { + VStack(alignment: .trailing) { + penPropertyTool + penItemList + } + .fixedSize() + .frame(maxHeight: .infinity) + .padding(10) + .transition(.move(edge: .trailing).combined(with: .blurReplace)) } - .fixedSize() - .frame(maxHeight: .infinity) - .padding(10) } var penItemList: some View { @@ -156,7 +160,7 @@ struct PenDock: View { RoundedRectangle(cornerRadius: 8) .fill(.regularMaterial) } - .transition(.move(edge: .trailing).combined(with: .opacity)) + .transition(.move(edge: .trailing).combined(with: .blurReplace)) } else { Color.clear .frame(width: width * factor - 18, height: 50) diff --git a/Memola/Features/Memo/Toolbar/Toolbar.swift b/Memola/Features/Memo/Toolbar/Toolbar.swift index ba6500b..f7ac714 100644 --- a/Memola/Features/Memo/Toolbar/Toolbar.swift +++ b/Memola/Features/Memo/Toolbar/Toolbar.swift @@ -28,10 +28,15 @@ struct Toolbar: View { var body: some View { HStack(spacing: 5) { - closeButton - titleField + if !canvas.locksCanvas { + closeButton + titleField + } Spacer() - historyControl + if !canvas.locksCanvas { + historyControl + } + lockButton } .font(.subheadline) .padding(10) @@ -49,6 +54,7 @@ struct Toolbar: View { } .hoverEffect(.lift) .disabled(textFieldState) + .transition(.move(edge: .top).combined(with: .blurReplace)) } var titleField: some View { @@ -68,6 +74,7 @@ struct Toolbar: View { } } } + .transition(.move(edge: .top).combined(with: .blurReplace)) } var historyControl: some View { @@ -94,6 +101,30 @@ struct Toolbar: View { .background(.regularMaterial) .clipShape(.rect(cornerRadius: 8)) .disabled(textFieldState) + .transition(.move(edge: .top).combined(with: .blurReplace)) + } + + var lockButton: some View { + Button { + withAnimation { + canvas.locksCanvas.toggle() + } + } label: { + ZStack { + if canvas.locksCanvas { + Image(systemName: "lock.open") + .transition(.move(edge: .trailing).combined(with: .blurReplace)) + } else { + Image(systemName: "lock") + .transition(.move(edge: .leading).combined(with: .blurReplace)) + } + } + .contentShape(.circle) + .frame(width: size, height: size) + .background(.regularMaterial) + .clipShape(.rect(cornerRadius: 8)) + } + .hoverEffect(.lift) } func closeMemo() {