chore: refactor

This commit is contained in:
dscyrescotti
2024-07-14 16:44:21 +07:00
parent ca93472cd4
commit 9b9ccf2a86
55 changed files with 341 additions and 244 deletions
+3 -3
View File
@@ -409,7 +409,7 @@
children = ( children = (
EC2002D32C416002002EBD5F /* Commands */, EC2002D32C416002002EBD5F /* Commands */,
EC2002DF2C416466002EBD5F /* Core */, EC2002DF2C416466002EBD5F /* Core */,
EC2002E72C4167B1002EBD5F /* EnvironmentKeys */, EC2002E72C4167B1002EBD5F /* EnvironmentValues */,
); );
path = Shortcut; path = Shortcut;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -423,12 +423,12 @@
path = Core; path = Core;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
EC2002E72C4167B1002EBD5F /* EnvironmentKeys */ = { EC2002E72C4167B1002EBD5F /* EnvironmentValues */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
EC2002E82C4167C5002EBD5F /* ShortcutKey.swift */, EC2002E82C4167C5002EBD5F /* ShortcutKey.swift */,
); );
path = EnvironmentKeys; path = EnvironmentValues;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
EC2002EE2C417BBF002EBD5F /* AppScene */ = { EC2002EE2C417BBF002EBD5F /* AppScene */ = {
+14 -1
View File
@@ -8,8 +8,21 @@
import Combine import Combine
import SwiftUI import SwiftUI
class Application: NSObject, ObservableObject { final class Application: NSObject, ObservableObject {
}
extension Application {
func activateSearchBar() {
#if os(macOS)
guard let toolbar = NSApp.keyWindow?.toolbar else { return }
if let search = toolbar.items.first(where: { $0.itemIdentifier.rawValue == "com.apple.SwiftUI.search" }) as? NSSearchToolbarItem {
search.beginSearchInteraction()
}
#else
#warning("TODO: implement for ipad")
#endif
}
} }
#if os(macOS) #if os(macOS)
+4 -3
View File
@@ -10,9 +10,9 @@ import SwiftUI
@main @main
struct MemolaApp: App { struct MemolaApp: App {
#if os(macOS) #if os(macOS)
@NSApplicationDelegateAdaptor(Application.self) var application @NSApplicationDelegateAdaptor(Application.self) private var application
#else #else
@UIApplicationDelegateAdaptor(Application.self) var application @UIApplicationDelegateAdaptor(Application.self) private var application
#endif #endif
var body: some Scene { var body: some Scene {
@@ -30,6 +30,7 @@ struct MemolaApp: App {
#if os(macOS) #if os(macOS)
.frame(minWidth: 1000, minHeight: 600) .frame(minWidth: 1000, minHeight: 600)
#endif #endif
.environmentObject(application)
} }
#if os(macOS) #if os(macOS)
.defaultPosition(.center) .defaultPosition(.center)
@@ -41,7 +42,7 @@ struct MemolaApp: App {
AppCommands() AppCommands()
FileCommands() FileCommands()
EditCommands() EditCommands()
ViewCommands() ViewCommands(application: application)
} }
} }
} }
+1 -1
View File
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class LineGridContext { final class LineGridContext {
var vertices: [LineGridVertex] = [] var vertices: [LineGridVertex] = []
var vertexCount: Int = 0 var vertexCount: Int = 0
var vertexBuffer: MTLBuffer? var vertexBuffer: MTLBuffer?
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class PointGridContext { final class PointGridContext {
var vertices: [PointGridVertex] = [] var vertices: [PointGridVertex] = []
var vertexCount: Int = 0 var vertexCount: Int = 0
var vertexBuffer: MTLBuffer? var vertexBuffer: MTLBuffer?
+1 -1
View File
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class ViewPortContext { final class ViewPortContext {
var vertices: [ViewPortVertex] = [] var vertices: [ViewPortVertex] = []
let vertexCount: Int = 4 let vertexCount: Int = 4
var vertexBuffer: MTLBuffer? var vertexBuffer: MTLBuffer?
+1 -1
View File
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
struct PipelineStates { enum PipelineStates {
static func createPointGridPipelineState(from renderer: Renderer, pixelFormat: MTLPixelFormat? = nil) -> MTLRenderPipelineState? { static func createPointGridPipelineState(from renderer: Renderer, pixelFormat: MTLPixelFormat? = nil) -> MTLRenderPipelineState? {
let device = renderer.device let device = renderer.device
let library = renderer.library let library = renderer.library
@@ -7,7 +7,7 @@
import Foundation import Foundation
class ElementGroup { final class ElementGroup {
var elements: [Element] = [] var elements: [Element] = []
var type: ElementGroupType var type: ElementGroupType
@@ -7,7 +7,7 @@
import Foundation import Foundation
class MovingAverage { final class MovingAverage {
private var sum: CGPoint private var sum: CGPoint
private var points: [CGPoint] private var points: [CGPoint]
private var windowSize: Int private var windowSize: Int
+1 -1
View File
@@ -8,7 +8,7 @@
import Combine import Combine
import Foundation import Foundation
class History: ObservableObject { final class History: ObservableObject {
var memo: MemoObject? var memo: MemoObject?
init(memo: MemoObject?) { init(memo: MemoObject?) {
+1 -1
View File
@@ -7,7 +7,7 @@
import Foundation import Foundation
class Node<T> where T: Equatable & Comparable { final class Node<T> where T: Equatable & Comparable {
var box: Box var box: Box
var value: T? var value: T?
var isLeaf: Bool var isLeaf: Bool
+1 -1
View File
@@ -7,7 +7,7 @@
import Foundation import Foundation
class RTree<T> where T: Equatable & Comparable { final class RTree<T> where T: Equatable & Comparable {
private var root: Node<T> private var root: Node<T>
private let maxEntries: Int private let maxEntries: Int
private let minEntries: Int private let minEntries: Int
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class CacheRenderPass: RenderPass { final class CacheRenderPass: RenderPass {
var label: String = "Cache Render Pass" var label: String = "Cache Render Pass"
var descriptor: MTLRenderPassDescriptor? var descriptor: MTLRenderPassDescriptor?
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class EraserRenderPass: RenderPass { final class EraserRenderPass: RenderPass {
var label: String = "Eraser Render Pass" var label: String = "Eraser Render Pass"
var descriptor: MTLRenderPassDescriptor? var descriptor: MTLRenderPassDescriptor?
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class GraphicRenderPass: RenderPass { final class GraphicRenderPass: RenderPass {
var label: String { "Graphic Render Pass" } var label: String { "Graphic Render Pass" }
var descriptor: MTLRenderPassDescriptor? var descriptor: MTLRenderPassDescriptor?
var graphicTexture: MTLTexture? var graphicTexture: MTLTexture?
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class PhotoBackgroundRenderPass: RenderPass { final class PhotoBackgroundRenderPass: RenderPass {
var label: String = "Photo Background Render Pass" var label: String = "Photo Background Render Pass"
var descriptor: MTLRenderPassDescriptor? var descriptor: MTLRenderPassDescriptor?
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class PhotoRenderPass: RenderPass { final class PhotoRenderPass: RenderPass {
var label: String = "Photo Render Pass" var label: String = "Photo Render Pass"
var descriptor: MTLRenderPassDescriptor? var descriptor: MTLRenderPassDescriptor?
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class StrokeRenderPass: RenderPass { final class StrokeRenderPass: RenderPass {
var label: String = "Stroke Render Pass" var label: String = "Stroke Render Pass"
var descriptor: MTLRenderPassDescriptor? var descriptor: MTLRenderPassDescriptor?
@@ -8,7 +8,7 @@
import MetalKit import MetalKit
import Foundation import Foundation
class ViewPortRenderPass: RenderPass { final class ViewPortRenderPass: RenderPass {
var label: String { "View Port Render Pass"} var label: String { "View Port Render Pass"}
var descriptor: MTLRenderPassDescriptor? var descriptor: MTLRenderPassDescriptor?
+2 -2
View File
@@ -10,8 +10,8 @@ import SwiftUI
import CoreData import CoreData
import Foundation import Foundation
public class Tool: NSObject, ObservableObject { final class Tool: NSObject, ObservableObject {
let object: ToolObject private let object: ToolObject
@Published var pens: [Pen] = [] @Published var pens: [Pen] = []
@@ -10,21 +10,21 @@ import SwiftUI
import MetalKit import MetalKit
import Foundation import Foundation
class CanvasViewController: Platform.ViewController { final class CanvasViewController: Platform.ViewController {
let drawingView: DrawingView private let drawingView: DrawingView
let scrollView: Platform.ScrollView = Platform.ScrollView() private let scrollView: Platform.ScrollView = Platform.ScrollView()
var renderView: MTKView { private var renderView: MTKView {
drawingView.renderView drawingView.renderView
} }
var photoInsertGesture: Platform.TapGestureRecognizer? private var photoInsertGesture: Platform.TapGestureRecognizer?
let tool: Tool private let tool: Tool
let canvas: Canvas private let canvas: Canvas
let history: History private let history: History
let renderer: Renderer private let renderer: Renderer
var cancellables: Set<AnyCancellable> = [] private var cancellables: Set<AnyCancellable> = []
init(tool: Tool, canvas: Canvas, history: History) { init(tool: Tool, canvas: Canvas, history: History) {
self.tool = tool self.tool = tool
@@ -94,7 +94,7 @@ class CanvasViewController: Platform.ViewController {
} }
extension CanvasViewController { extension CanvasViewController {
func configureViews() { private func configureViews() {
#if os(macOS) #if os(macOS)
view.wantsLayer = true view.wantsLayer = true
view.layer?.backgroundColor = NSColor.white.cgColor view.layer?.backgroundColor = NSColor.white.cgColor
@@ -153,7 +153,7 @@ extension CanvasViewController {
#endif #endif
} }
func resizeDocumentView(to newSize: CGSize? = nil) { private func resizeDocumentView(to newSize: CGSize? = nil) {
#if os(macOS) #if os(macOS)
scrollView.layoutSubtreeIfNeeded() scrollView.layoutSubtreeIfNeeded()
#else #else
@@ -193,7 +193,7 @@ extension CanvasViewController {
} }
#if os(iOS) #if os(iOS)
func centerDocumentView(to newSize: CGSize? = nil) { private func centerDocumentView(to newSize: CGSize? = nil) {
let documentViewSize = drawingView.frame.size let documentViewSize = drawingView.frame.size
let scrollViewSize = newSize ?? view.frame.size let scrollViewSize = newSize ?? view.frame.size
let verticalPadding = documentViewSize.height < scrollViewSize.height ? (scrollViewSize.height - documentViewSize.height) / 2 : 0 let verticalPadding = documentViewSize.height < scrollViewSize.height ? (scrollViewSize.height - documentViewSize.height) / 2 : 0
@@ -202,7 +202,7 @@ extension CanvasViewController {
} }
#endif #endif
func updateDocumentBounds() { private func updateDocumentBounds() {
#if os(macOS) #if os(macOS)
let ratio = drawingView.ratio let ratio = drawingView.ratio
var bounds = scrollView.convert(scrollView.bounds, to: drawingView) var bounds = scrollView.convert(scrollView.bounds, to: drawingView)
@@ -225,7 +225,7 @@ extension CanvasViewController {
} }
extension CanvasViewController { extension CanvasViewController {
func configureListeners() { private func configureListeners() {
#if os(macOS) #if os(macOS)
NotificationCenter.default.publisher(for: NSScrollView.didEndLiveMagnifyNotification, object: scrollView) NotificationCenter.default.publisher(for: NSScrollView.didEndLiveMagnifyNotification, object: scrollView)
.sink { [weak self] _ in .sink { [weak self] _ in
@@ -292,12 +292,12 @@ extension CanvasViewController {
} }
extension CanvasViewController { extension CanvasViewController {
func loadMemo() { private func loadMemo() {
tool.load() tool.load()
canvas.load() canvas.load()
} }
func canvasStateChanged(_ state: Canvas.State) { private func canvasStateChanged(_ state: Canvas.State) {
guard state == .loaded else { return } guard state == .loaded else { return }
renderView.delegate = self renderView.delegate = self
renderer.resize(on: renderView, to: renderView.drawableSize) renderer.resize(on: renderView, to: renderView.drawableSize)
@@ -318,7 +318,7 @@ extension CanvasViewController: MTKViewDelegate {
} }
extension CanvasViewController { extension CanvasViewController {
func configureGestures() { private func configureGestures() {
let photoInsertGesture = Platform.TapGestureRecognizer(target: self, action: #selector(recognizeTapGesture)) let photoInsertGesture = Platform.TapGestureRecognizer(target: self, action: #selector(recognizeTapGesture))
#if os(macOS) #if os(macOS)
photoInsertGesture.numberOfClicksRequired = 1 photoInsertGesture.numberOfClicksRequired = 1
@@ -329,7 +329,7 @@ extension CanvasViewController {
scrollView.addGestureRecognizer(photoInsertGesture) scrollView.addGestureRecognizer(photoInsertGesture)
} }
@objc func recognizeTapGesture(_ gesture: Platform.TapGestureRecognizer) { @objc private func recognizeTapGesture(_ gesture: Platform.TapGestureRecognizer) {
guard let photoItem = tool.selectedPhotoItem else { return } guard let photoItem = tool.selectedPhotoItem else { return }
withAnimation { withAnimation {
tool.selectedPhotoItem = nil tool.selectedPhotoItem = nil
@@ -406,7 +406,7 @@ extension CanvasViewController: UIScrollViewDelegate {
#endif #endif
extension CanvasViewController { extension CanvasViewController {
func magnificationStarted() { private func magnificationStarted() {
guard !renderer.updatesViewPort else { return } guard !renderer.updatesViewPort else { return }
drawingView.touchCancelled() drawingView.touchCancelled()
canvas.updateClipBounds(scrollView, on: drawingView) canvas.updateClipBounds(scrollView, on: drawingView)
@@ -414,21 +414,21 @@ extension CanvasViewController {
renderer.setUpdatesViewPort(true) renderer.setUpdatesViewPort(true)
} }
func magnificationEnded() { private func magnificationEnded() {
renderer.setUpdatesViewPort(false) renderer.setUpdatesViewPort(false)
renderer.setRedrawsGraphicRender() renderer.setRedrawsGraphicRender()
renderView.draw() renderView.draw()
drawingView.enableUserInteraction() drawingView.enableUserInteraction()
} }
func draggingStarted() { private func draggingStarted() {
guard !renderer.updatesViewPort else { return } guard !renderer.updatesViewPort else { return }
canvas.updateClipBounds(scrollView, on: drawingView) canvas.updateClipBounds(scrollView, on: drawingView)
drawingView.disableUserInteraction() drawingView.disableUserInteraction()
renderer.setUpdatesViewPort(true) renderer.setUpdatesViewPort(true)
} }
func draggingEnded() { private func draggingEnded() {
renderer.setUpdatesViewPort(false) renderer.setUpdatesViewPort(false)
renderer.setRedrawsGraphicRender() renderer.setRedrawsGraphicRender()
renderView.draw() renderView.draw()
@@ -437,13 +437,13 @@ extension CanvasViewController {
} }
extension CanvasViewController { extension CanvasViewController {
func penChanged(to pen: Pen?) { private func penChanged(to pen: Pen?) {
if let pen, let device = drawingView.renderView.device { if let pen, let device = drawingView.renderView.device {
pen.style.loadTexture(on: device) pen.style.loadTexture(on: device)
} }
} }
func toolSelectionChanged(to selection: ToolSelection) { private func toolSelectionChanged(to selection: ToolSelection) {
let enablesScrolling: Bool let enablesScrolling: Bool
let enablesDrawing: Bool let enablesDrawing: Bool
let enablesPhotoInsertion: Bool let enablesPhotoInsertion: Bool
@@ -474,7 +474,7 @@ extension CanvasViewController {
} }
extension CanvasViewController { extension CanvasViewController {
func zoomChanged(_ zoomScale: CGFloat) { private func zoomChanged(_ zoomScale: CGFloat) {
#if os(macOS) #if os(macOS)
let rect = scrollView.documentVisibleRect let rect = scrollView.documentVisibleRect
scrollView.setMagnification(zoomScale, centeredAt: CGPoint(x: rect.midX, y: rect.midY)) scrollView.setMagnification(zoomScale, centeredAt: CGPoint(x: rect.midX, y: rect.midY))
@@ -483,7 +483,7 @@ extension CanvasViewController {
#endif #endif
} }
func lockModeChanged(_ state: Bool) { private func lockModeChanged(_ state: Bool) {
#if os(macOS) #if os(macOS)
#warning("TODO: implement for macos") #warning("TODO: implement for macos")
#else #else
@@ -491,7 +491,7 @@ extension CanvasViewController {
#endif #endif
} }
func gridModeChanged(_ mode: GridMode) { private func gridModeChanged(_ mode: GridMode) {
drawingView.disableUserInteraction() drawingView.disableUserInteraction()
renderer.setRedrawsGraphicRender() renderer.setRedrawsGraphicRender()
renderView.draw() renderView.draw()
@@ -500,7 +500,7 @@ extension CanvasViewController {
} }
extension CanvasViewController { extension CanvasViewController {
func historyUndid() { private func historyUndid() {
guard let event = history.undo() else { return } guard let event = history.undo() else { return }
drawingView.disableUserInteraction() drawingView.disableUserInteraction()
canvas.graphicContext.undoGraphic(for: event) canvas.graphicContext.undoGraphic(for: event)
@@ -509,7 +509,7 @@ extension CanvasViewController {
drawingView.enableUserInteraction() drawingView.enableUserInteraction()
} }
func historyRedid() { private func historyRedid() {
guard let event = history.redo() else { return } guard let event = history.redo() else { return }
drawingView.disableUserInteraction() drawingView.disableUserInteraction()
canvas.graphicContext.redoGraphic(for: event) canvas.graphicContext.redoGraphic(for: event)
@@ -8,7 +8,7 @@
#if canImport(AppKit) #if canImport(AppKit)
import AppKit import AppKit
class NSCenterClipView: NSClipView { final class NSCenterClipView: NSClipView {
override func constrainBoundsRect(_ proposedBounds: NSRect) -> NSRect { override func constrainBoundsRect(_ proposedBounds: NSRect) -> NSRect {
var rect = super.constrainBoundsRect(proposedBounds) var rect = super.constrainBoundsRect(proposedBounds)
if let containerView = self.documentView { if let containerView = self.documentView {
@@ -13,7 +13,7 @@ protocol NSSyncScrollViewDelegate: AnyObject {
func scrollViewDidScroll(_ scrollView: NSSyncScrollView) func scrollViewDidScroll(_ scrollView: NSSyncScrollView)
} }
class NSSyncScrollView: NSScrollView { final class NSSyncScrollView: NSScrollView {
weak var delegate: NSSyncScrollViewDelegate? weak var delegate: NSSyncScrollViewDelegate?
override func magnify(with event: NSEvent) { override func magnify(with event: NSEvent) {
@@ -9,10 +9,10 @@ import SwiftUI
import MetalKit import MetalKit
import Foundation import Foundation
class DrawingView: Platform.View { final class DrawingView: Platform.View {
let tool: Tool private let tool: Tool
let canvas: Canvas private let canvas: Canvas
let history: History private let history: History
let renderView: MTKView let renderView: MTKView
var ratio: CGFloat { canvas.size.width / bounds.width } var ratio: CGFloat { canvas.size.width / bounds.width }
+9 -3
View File
@@ -8,9 +8,15 @@
import SwiftUI import SwiftUI
struct CanvasView: Platform.ViewControllerRepresentable { struct CanvasView: Platform.ViewControllerRepresentable {
@ObservedObject var tool: Tool @ObservedObject private var tool: Tool
@ObservedObject var canvas: Canvas @ObservedObject private var canvas: Canvas
@ObservedObject var history: History @ObservedObject private var history: History
init(tool: Tool, canvas: Canvas, history: History) {
self.tool = tool
self.canvas = canvas
self.history = history
}
#if os(macOS) #if os(macOS)
func makeNSViewController(context: Context) -> CanvasViewController { func makeNSViewController(context: Context) -> CanvasViewController {
@@ -9,9 +9,15 @@ import SwiftUI
import Foundation import Foundation
private struct ContextMenuViewModifier<MenuContent: View, Preview: View>: ViewModifier { private struct ContextMenuViewModifier<MenuContent: View, Preview: View>: ViewModifier {
let condition: Bool private let condition: Bool
let menuItems: () -> MenuContent private let menuItems: () -> MenuContent
let preview: () -> Preview private let preview: () -> Preview
init(condition: Bool, @ViewBuilder menuItems: @escaping () -> MenuContent, @ViewBuilder preview: @escaping () -> Preview) {
self.condition = condition
self.menuItems = menuItems
self.preview = preview
}
@ViewBuilder @ViewBuilder
func body(content: Content) -> some View { func body(content: Content) -> some View {
@@ -8,9 +8,13 @@
import SwiftUI import SwiftUI
private struct OnDismissSearchViewModifier: ViewModifier { private struct OnDismissSearchViewModifier: ViewModifier {
@Environment(\.dismissSearch) var dismissSearch @Environment(\.dismissSearch) private var dismissSearch
@Binding var isActive: Bool @Binding private var isActive: Bool
init(isActive: Binding<Bool>) {
self._isActive = isActive
}
func body(content: Content) -> some View { func body(content: Content) -> some View {
content content
@@ -9,9 +9,15 @@ import SwiftUI
import Foundation import Foundation
private struct OnDragViewModifier<Preview: View>: ViewModifier { private struct OnDragViewModifier<Preview: View>: ViewModifier {
let condition: Bool private let condition: Bool
let data: () -> NSItemProvider private let data: () -> NSItemProvider
let preview: () -> Preview private let preview: () -> Preview
init(condition: Bool, data: @escaping () -> NSItemProvider, @ViewBuilder preview: @escaping () -> Preview) {
self.condition = condition
self.data = data
self.preview = preview
}
@ViewBuilder @ViewBuilder
func body(content: Content) -> some View { func body(content: Content) -> some View {
@@ -9,12 +9,17 @@ import SwiftUI
#if os(iOS) #if os(iOS)
struct CameraView: UIViewControllerRepresentable { struct CameraView: UIViewControllerRepresentable {
@Binding var image: UIImage? @Binding private var image: UIImage?
@ObservedObject var canvas: Canvas @ObservedObject private var canvas: Canvas
@Environment(\.dismiss) private var dismiss @Environment(\.dismiss) private var dismiss
init(image: Binding<UIImage?>, canvas: Canvas) {
self._image = image
self.canvas = canvas
}
func makeUIViewController(context: Context) -> UIImagePickerController { func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController() let picker = UIImagePickerController()
picker.sourceType = .camera picker.sourceType = .camera
@@ -9,14 +9,18 @@ import SwiftUI
import Foundation import Foundation
struct ColorPicker: View { struct ColorPicker: View {
@State var hue: Double = 1 @State private var hue: Double = 1
@State var saturation: Double = 0 @State private var saturation: Double = 0
@State var brightness: Double = 1 @State private var brightness: Double = 1
@State var alpha: Double = 1 @State private var alpha: Double = 1
@Binding var color: Color @Binding private var color: Color
let size: CGFloat = 20 private let size: CGFloat = 20
init(color: Binding<Color>) {
self._color = color
}
var body: some View { var body: some View {
VStack(spacing: 10) { VStack(spacing: 10) {
@@ -43,7 +47,7 @@ struct ColorPicker: View {
} }
@ViewBuilder @ViewBuilder
var colorPicker: some View { private var colorPicker: some View {
GeometryReader { proxy in GeometryReader { proxy in
ZStack { ZStack {
Color(hue: hue, saturation: 1, brightness: 1) Color(hue: hue, saturation: 1, brightness: 1)
@@ -92,7 +96,7 @@ struct ColorPicker: View {
} }
@ViewBuilder @ViewBuilder
var hueSlider: some View { private var hueSlider: some View {
GeometryReader { proxy in GeometryReader { proxy in
ZStack(alignment: .leading) { ZStack(alignment: .leading) {
LinearGradient( LinearGradient(
@@ -138,7 +142,7 @@ struct ColorPicker: View {
} }
@ViewBuilder @ViewBuilder
var alphaSlider: some View { private var alphaSlider: some View {
GeometryReader { proxy in GeometryReader { proxy in
let color = Color(hue: hue, saturation: saturation, brightness: brightness) let color = Color(hue: hue, saturation: saturation, brightness: brightness)
ZStack(alignment: .leading) { ZStack(alignment: .leading) {
@@ -190,7 +194,7 @@ struct ColorPicker: View {
.frame(height: size) .frame(height: size)
} }
func updateColor() { private func updateColor() {
color = Color(hue: hue, saturation: saturation, brightness: brightness).opacity(0.7 * alpha + 0.3) color = Color(hue: hue, saturation: saturation, brightness: brightness).opacity(0.7 * alpha + 0.3)
} }
} }
@@ -8,9 +8,13 @@
import SwiftUI import SwiftUI
struct Placeholder: View { struct Placeholder: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
let info: Info private let info: Info
init(info: Info) {
self.info = info
}
var body: some View { var body: some View {
VStack(spacing: 15) { VStack(spacing: 15) {
@@ -8,14 +8,14 @@
import SwiftUI import SwiftUI
struct DashboardView: View { struct DashboardView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
@StateObject var memoManager: MemoManager = .shared @StateObject private var memoManager: MemoManager = .shared
@State var sidebarItem: SidebarItem? = .memos @State private var sidebarItem: SidebarItem? = .memos
@AppStorage("memola.app.scene.side-bar.column-visibility") var columnVisibility: NavigationSplitViewVisibility = .all @AppStorage("memola.app.scene.side-bar.column-visibility") private var columnVisibility: NavigationSplitViewVisibility = .all
@Namespace var namespace @Namespace private var namespace
var body: some View { var body: some View {
#if os(macOS) #if os(macOS)
@@ -8,21 +8,21 @@
import SwiftUI import SwiftUI
struct MemosView: View { struct MemosView: View {
@Environment(\.shortcut) var shortcut @Environment(\.shortcut) private var shortcut
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
@FetchRequest var memoObjects: FetchedResults<MemoObject> @FetchRequest private var memoObjects: FetchedResults<MemoObject>
@State var query: String = "" @State private var query: String = ""
@State var currentDate: Date = .now @State private var currentDate: Date = .now
@State var isActiveSearch: Bool = false @State private var isActiveSearch: Bool = false
@AppStorage("memola.memo-objects.memos.sort") var sort: Sort = .recent @AppStorage("memola.memo-objects.memos.sort") private var sort: Sort = .recent
@AppStorage("memola.memo-objects.memos.filter") var filter: Filter = .none @AppStorage("memola.memo-objects.memos.filter") private var filter: Filter = .none
let timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect() private let timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect()
var placeholder: Placeholder.Info { private var placeholder: Placeholder.Info {
query.isEmpty ? .memoEmpty : .memoNotFound query.isEmpty ? .memoEmpty : .memoNotFound
} }
@@ -157,12 +157,12 @@ struct MemosView: View {
.onReceive(timer) { date in .onReceive(timer) { date in
currentDate = date currentDate = date
} }
.onReceive(shortcut.publisher()) { shortcut in .onReceive(shortcut.publisher) { shortcut in
handleShortcut(for: shortcut) handleShortcut(for: shortcut)
} }
} }
func memoCard(_ memoObject: MemoObject, _ cellWidth: CGFloat) -> some View { private func memoCard(_ memoObject: MemoObject, _ cellWidth: CGFloat) -> some View {
MemoCard(memoObject: memoObject, cellWidth: cellWidth) { card in MemoCard(memoObject: memoObject, cellWidth: cellWidth) { card in
card card
.contextMenu { .contextMenu {
@@ -208,7 +208,7 @@ struct MemosView: View {
} }
} }
func createMemo(title: String) { private func createMemo(title: String) {
let memoObject = MemoObject(\.viewContext) let memoObject = MemoObject(\.viewContext)
memoObject.title = title memoObject.title = title
memoObject.createdAt = .now memoObject.createdAt = .now
@@ -258,11 +258,11 @@ struct MemosView: View {
} }
} }
func openMemo(for memo: MemoObject) { private func openMemo(for memo: MemoObject) {
MemoManager.shared.openMemo(memo) MemoManager.shared.openMemo(memo)
} }
func updatePredicate() { private func updatePredicate() {
var predicates: [NSPredicate] = [NSPredicate(format: "isTrash = NO")] var predicates: [NSPredicate] = [NSPredicate(format: "isTrash = NO")]
if !query.isEmpty { if !query.isEmpty {
predicates.append(NSPredicate(format: "title contains[c] %@", query)) predicates.append(NSPredicate(format: "title contains[c] %@", query))
@@ -273,14 +273,14 @@ struct MemosView: View {
memoObjects.nsPredicate = NSCompoundPredicate(type: .and, subpredicates: predicates) memoObjects.nsPredicate = NSCompoundPredicate(type: .and, subpredicates: predicates)
} }
func toggleFavorite(for memo: MemoObject) { private func toggleFavorite(for memo: MemoObject) {
memo.isFavorite.toggle() memo.isFavorite.toggle()
withPersistence(\.viewContext) { context in withPersistence(\.viewContext) { context in
try context.saveIfNeeded() try context.saveIfNeeded()
} }
} }
func markAsTrash(for memo: MemoObject) { private func markAsTrash(for memo: MemoObject) {
memo.isTrash = true memo.isTrash = true
memo.deletedAt = .now memo.deletedAt = .now
withPersistence(\.viewContext) { context in withPersistence(\.viewContext) { context in
@@ -288,7 +288,7 @@ struct MemosView: View {
} }
} }
func handleShortcut(for shortcut: Shortcuts) { private func handleShortcut(for shortcut: Shortcuts) {
switch shortcut { switch shortcut {
case .newMemo: case .newMemo:
if MemoManager.shared.memoObject == nil { if MemoManager.shared.memoObject == nil {
@@ -8,12 +8,12 @@
import SwiftUI import SwiftUI
struct MemoCard<Preview: View, Detail: View>: View { struct MemoCard<Preview: View, Detail: View>: View {
let memoObject: MemoObject private let memoObject: MemoObject
let cellWidth: CGFloat private let cellWidth: CGFloat
let modifyPreview: ((MemoPreview) -> Preview)? private let modifyPreview: ((MemoPreview) -> Preview)?
let details: () -> Detail private let details: () -> Detail
init(memoObject: MemoObject, cellWidth: CGFloat, @ViewBuilder modifyPreview: @escaping (MemoPreview) -> Preview, @ViewBuilder details: @escaping () -> Detail) { init(memoObject: MemoObject, cellWidth: CGFloat, modifyPreview: ((MemoPreview) -> Preview)?, @ViewBuilder details: @escaping () -> Detail) {
self.memoObject = memoObject self.memoObject = memoObject
self.cellWidth = cellWidth self.cellWidth = cellWidth
self.modifyPreview = modifyPreview self.modifyPreview = modifyPreview
@@ -8,12 +8,18 @@
import SwiftUI import SwiftUI
struct MemoGrid<Card: View>: View { struct MemoGrid<Card: View>: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
let memoObjects: FetchedResults<MemoObject> private let memoObjects: FetchedResults<MemoObject>
let placeholder: Placeholder.Info private let placeholder: Placeholder.Info
@ViewBuilder let card: (MemoObject, CGFloat) -> Card @ViewBuilder private let card: (MemoObject, CGFloat) -> Card
var maxCellWidth: CGFloat { init(memoObjects: FetchedResults<MemoObject>, placeholder: Placeholder.Info, @ViewBuilder card: @escaping (MemoObject, CGFloat) -> Card) {
self.memoObjects = memoObjects
self.placeholder = placeholder
self.card = card
}
private var maxCellWidth: CGFloat {
if horizontalSizeClass == .compact { if horizontalSizeClass == .compact {
return 180 return 180
} }
@@ -8,11 +8,17 @@
import SwiftUI import SwiftUI
struct MemoPreview: View { struct MemoPreview: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
let preview: Data? private let preview: Data?
let cellWidth: CGFloat private let cellWidth: CGFloat
var cellHeight: CGFloat {
init(preview: Data?, cellWidth: CGFloat) {
self.preview = preview
self.cellWidth = cellWidth
}
private var cellHeight: CGFloat {
if horizontalSizeClass == .compact { if horizontalSizeClass == .compact {
return 120 return 120
} }
@@ -8,19 +8,19 @@
import SwiftUI import SwiftUI
struct TrashView: View { struct TrashView: View {
@Environment(\.shortcut) var shortcut @Environment(\.shortcut) private var shortcut
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
@FetchRequest var memoObjects: FetchedResults<MemoObject> @FetchRequest private var memoObjects: FetchedResults<MemoObject>
@State var query: String = "" @State private var query: String = ""
@State var restoredMemo: MemoObject? @State private var restoredMemo: MemoObject?
@State var deletedMemo: MemoObject? @State private var deletedMemo: MemoObject?
@State var isActiveSearch: Bool = false @State private var isActiveSearch: Bool = false
@Binding var sidebarItem: SidebarItem? @Binding private var sidebarItem: SidebarItem?
var placeholder: Placeholder.Info { private var placeholder: Placeholder.Info {
query.isEmpty ? .trashEmpty : .trashNotFound query.isEmpty ? .trashEmpty : .trashNotFound
} }
@@ -102,7 +102,7 @@ struct TrashView: View {
} }
} }
func memoCard(_ memoObject: MemoObject, _ cellWidth: CGFloat) -> some View { private func memoCard(_ memoObject: MemoObject, _ cellWidth: CGFloat) -> some View {
MemoCard(memoObject: memoObject, cellWidth: cellWidth) { card in MemoCard(memoObject: memoObject, cellWidth: cellWidth) { card in
card card
.contextMenu { .contextMenu {
@@ -131,7 +131,7 @@ struct TrashView: View {
} }
} }
func updatePredicate() { private func updatePredicate() {
var predicates: [NSPredicate] = [NSPredicate(format: "isTrash = YES")] var predicates: [NSPredicate] = [NSPredicate(format: "isTrash = YES")]
if !query.isEmpty { if !query.isEmpty {
predicates.append(NSPredicate(format: "title contains[c] %@", query)) predicates.append(NSPredicate(format: "title contains[c] %@", query))
@@ -139,7 +139,7 @@ struct TrashView: View {
memoObjects.nsPredicate = NSCompoundPredicate(type: .and, subpredicates: predicates) memoObjects.nsPredicate = NSCompoundPredicate(type: .and, subpredicates: predicates)
} }
func restoreMemo(for memo: MemoObject?) { private func restoreMemo(for memo: MemoObject?) {
guard let memo else { return } guard let memo else { return }
memo.isTrash = false memo.isTrash = false
memo.deletedAt = nil memo.deletedAt = nil
@@ -148,7 +148,7 @@ struct TrashView: View {
} }
} }
func restoreAndOpenMemo(for memo: MemoObject?) { private func restoreAndOpenMemo(for memo: MemoObject?) {
restoreMemo(for: memo) restoreMemo(for: memo)
self.sidebarItem = .memos self.sidebarItem = .memos
if let memo { if let memo {
@@ -156,7 +156,7 @@ struct TrashView: View {
} }
} }
func deleteMemo(for memo: MemoObject?) { private func deleteMemo(for memo: MemoObject?) {
guard let memo else { return } guard let memo else { return }
withPersistenceSync(\.viewContext) { context in withPersistenceSync(\.viewContext) { context in
context.delete(memo) context.delete(memo)
@@ -8,10 +8,15 @@
import SwiftUI import SwiftUI
struct Sidebar: View { struct Sidebar: View {
let sidebarItems: [SidebarItem] = [.memos, .trash] private let sidebarItems: [SidebarItem] = [.memos, .trash]
@Binding var sidebarItem: SidebarItem? @Binding private var sidebarItem: SidebarItem?
let horizontalSizeClass: UserInterfaceSizeClass? private let horizontalSizeClass: UserInterfaceSizeClass?
init(sidebarItem: Binding<SidebarItem?>, horizontalSizeClass: UserInterfaceSizeClass?) {
self._sidebarItem = sidebarItem
self.horizontalSizeClass = horizontalSizeClass
}
var body: some View { var body: some View {
List(selection: $sidebarItem) { List(selection: $sidebarItem) {
@@ -51,7 +56,7 @@ struct Sidebar: View {
} }
extension Sidebar { extension Sidebar {
struct SidebarItemButtonStyle: ButtonStyle { fileprivate struct SidebarItemButtonStyle: ButtonStyle {
let state: State let state: State
func makeBody(configuration: Configuration) -> some View { func makeBody(configuration: Configuration) -> some View {
@@ -10,12 +10,17 @@ import PhotosUI
import AVFoundation import AVFoundation
struct ElementToolbar: View { struct ElementToolbar: View {
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) private var colorScheme
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
let size: CGFloat = 40 private let size: CGFloat = 40
@ObservedObject var tool: Tool @ObservedObject private var tool: Tool
@ObservedObject var canvas: Canvas @ObservedObject private var canvas: Canvas
init(tool: Tool, canvas: Canvas) {
self.tool = tool
self.canvas = canvas
}
var body: some View { var body: some View {
Group { Group {
@@ -41,7 +46,7 @@ struct ElementToolbar: View {
.foregroundStyle(Color.accentColor) .foregroundStyle(Color.accentColor)
} }
var regularToolbar: some View { private var regularToolbar: some View {
HStack(spacing: 0) { HStack(spacing: 0) {
Button { Button {
withAnimation { withAnimation {
@@ -124,7 +129,7 @@ struct ElementToolbar: View {
.transition(.move(edge: .top).combined(with: .blurReplace)) .transition(.move(edge: .top).combined(with: .blurReplace))
} }
var compactToolbar: some View { private var compactToolbar: some View {
HStack(spacing: 0) { HStack(spacing: 0) {
Button { Button {
withAnimation { withAnimation {
+12 -12
View File
@@ -9,17 +9,17 @@ import SwiftUI
import CoreData import CoreData
struct MemoView: View { struct MemoView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
@StateObject var tool: Tool @StateObject private var tool: Tool
@StateObject var canvas: Canvas @StateObject private var canvas: Canvas
@StateObject var history: History @StateObject private var history: History
@State var title: String @State private var title: String
@FocusState var textFieldState: Bool @FocusState private var textFieldState: Bool
let memo: MemoObject private let memo: MemoObject
let size: CGFloat = 40 private let size: CGFloat = 40
init(memo: MemoObject) { init(memo: MemoObject) {
self.memo = memo self.memo = memo
@@ -63,7 +63,7 @@ struct MemoView: View {
} }
} }
var canvasView: some View { private var canvasView: some View {
CanvasView(tool: tool, canvas: canvas, history: history) CanvasView(tool: tool, canvas: canvas, history: history)
.ignoresSafeArea() .ignoresSafeArea()
.overlay(alignment: .trailing) { .overlay(alignment: .trailing) {
@@ -88,7 +88,7 @@ struct MemoView: View {
} }
} }
var compactCanvasView: some View { private var compactCanvasView: some View {
CanvasView(tool: tool, canvas: canvas, history: history) CanvasView(tool: tool, canvas: canvas, history: history)
.ignoresSafeArea() .ignoresSafeArea()
.overlay(alignment: .bottom) { .overlay(alignment: .bottom) {
@@ -115,7 +115,7 @@ struct MemoView: View {
} }
@ViewBuilder @ViewBuilder
var zoomControl: some View { private var zoomControl: some View {
let upperBound: CGFloat = 400 let upperBound: CGFloat = 400
let lowerBound: CGFloat = 10 let lowerBound: CGFloat = 10
let zoomScale: CGFloat = (((canvas.zoomScale - canvas.minimumZoomScale) * (upperBound - lowerBound) / (canvas.maximumZoomScale - canvas.minimumZoomScale)) + lowerBound).rounded() let zoomScale: CGFloat = (((canvas.zoomScale - canvas.minimumZoomScale) * (upperBound - lowerBound) / (canvas.maximumZoomScale - canvas.minimumZoomScale)) + lowerBound).rounded()
@@ -187,7 +187,7 @@ struct MemoView: View {
#endif #endif
} }
func loadingIndicator(_ title: String) -> some View { private func loadingIndicator(_ title: String) -> some View {
ProgressView { ProgressView {
Text(title) Text(title)
} }
+29 -24
View File
@@ -8,25 +8,30 @@
import SwiftUI import SwiftUI
struct PenDock: View { struct PenDock: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
@ObservedObject var tool: Tool @ObservedObject private var tool: Tool
@ObservedObject var canvas: Canvas @ObservedObject private var canvas: Canvas
let size: CGFloat = 40 private let size: CGFloat = 40
let penPropertySize: CGFloat = 32 private let penPropertySize: CGFloat = 32
var width: CGFloat { private var width: CGFloat {
horizontalSizeClass == .compact ? size / 2 : size horizontalSizeClass == .compact ? size / 2 : size
} }
var height: CGFloat { private var height: CGFloat {
horizontalSizeClass == .compact ? size : size / 2 horizontalSizeClass == .compact ? size : size / 2
} }
@State var refreshScrollId: UUID = UUID() @State private var refreshScrollId: UUID = UUID()
@State var opensColorPicker: Bool = false @State private var opensColorPicker: Bool = false
#if os(macOS) #if os(macOS)
@State var showsThinknessPicker: Bool = false @State private var showsThinknessPicker: Bool = false
#endif #endif
init(tool: Tool, canvas: Canvas) {
self.tool = tool
self.canvas = canvas
}
var body: some View { var body: some View {
#if os(macOS) #if os(macOS)
GeometryReader { proxy in GeometryReader { proxy in
@@ -101,7 +106,7 @@ struct PenDock: View {
} }
@ViewBuilder @ViewBuilder
var penItemList: some View { private var penItemList: some View {
VStack(alignment: .trailing, spacing: 0) { VStack(alignment: .trailing, spacing: 0) {
ScrollViewReader { proxy in ScrollViewReader { proxy in
ScrollView(.vertical, showsIndicators: false) { ScrollView(.vertical, showsIndicators: false) {
@@ -139,7 +144,7 @@ struct PenDock: View {
} }
@ViewBuilder @ViewBuilder
var compactPenItemList: some View { private var compactPenItemList: some View {
ScrollViewReader { proxy in ScrollViewReader { proxy in
ScrollView(.horizontal, showsIndicators: false) { ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 0) { LazyHStack(spacing: 0) {
@@ -165,7 +170,7 @@ struct PenDock: View {
} }
} }
func penItem(_ pen: Pen) -> some View { private func penItem(_ pen: Pen) -> some View {
ZStack { ZStack {
penShadow(pen) penShadow(pen)
if let tip = pen.style.icon.tip { if let tip = pen.style.icon.tip {
@@ -242,7 +247,7 @@ struct PenDock: View {
} }
} }
func compactPenItem(_ pen: Pen) -> some View { private func compactPenItem(_ pen: Pen) -> some View {
ZStack { ZStack {
compactPenShadow(pen) compactPenShadow(pen)
if let tip = pen.style.compactIcon.tip { if let tip = pen.style.compactIcon.tip {
@@ -319,7 +324,7 @@ struct PenDock: View {
} }
@ViewBuilder @ViewBuilder
var penPropertyTool: some View { private var penPropertyTool: some View {
if let pen = tool.selectedPen { if let pen = tool.selectedPen {
VStack(spacing: 5) { VStack(spacing: 5) {
if pen.strokeStyle == .marker { if pen.strokeStyle == .marker {
@@ -340,7 +345,7 @@ struct PenDock: View {
} }
@ViewBuilder @ViewBuilder
var compactPenPropertyTool: some View { private var compactPenPropertyTool: some View {
if let pen = tool.selectedPen { if let pen = tool.selectedPen {
HStack(spacing: 8) { HStack(spacing: 8) {
penThicknessPicker(pen) penThicknessPicker(pen)
@@ -356,7 +361,7 @@ struct PenDock: View {
} }
} }
func penColorPicker(_ pen: Pen) -> some View { private func penColorPicker(_ pen: Pen) -> some View {
Button { Button {
opensColorPicker = true opensColorPicker = true
} label: { } label: {
@@ -409,7 +414,7 @@ struct PenDock: View {
} }
@ViewBuilder @ViewBuilder
func penThicknessPicker(_ pen: Pen) -> some View { private func penThicknessPicker(_ pen: Pen) -> some View {
let minimum: CGFloat = pen.style.thickness.min let minimum: CGFloat = pen.style.thickness.min
let maximum: CGFloat = pen.style.thickness.max let maximum: CGFloat = pen.style.thickness.max
let start: CGFloat = 4 let start: CGFloat = 4
@@ -453,7 +458,7 @@ struct PenDock: View {
} }
} }
var newPenButton: some View { private var newPenButton: some View {
Button { Button {
createNewPen() createNewPen()
} label: { } label: {
@@ -474,7 +479,7 @@ struct PenDock: View {
#endif #endif
} }
func penPreview(_ pen: Pen) -> some View { private func penPreview(_ pen: Pen) -> some View {
ZStack { ZStack {
if let tip = pen.style.icon.tip { if let tip = pen.style.icon.tip {
Image(tip) Image(tip)
@@ -490,7 +495,7 @@ struct PenDock: View {
.padding(.leading, 10) .padding(.leading, 10)
} }
func compactPenPreview(_ pen: Pen) -> some View { private func compactPenPreview(_ pen: Pen) -> some View {
ZStack { ZStack {
if let tip = pen.style.compactIcon.tip { if let tip = pen.style.compactIcon.tip {
Image(tip) Image(tip)
@@ -506,7 +511,7 @@ struct PenDock: View {
.padding(.horizontal, 5) .padding(.horizontal, 5)
} }
func penShadow(_ pen: Pen) -> some View { private func penShadow(_ pen: Pen) -> some View {
ZStack { ZStack {
Group { Group {
if let tip = pen.style.icon.tip { if let tip = pen.style.icon.tip {
@@ -530,7 +535,7 @@ struct PenDock: View {
} }
} }
func compactPenShadow(_ pen: Pen) -> some View { private func compactPenShadow(_ pen: Pen) -> some View {
ZStack { ZStack {
Group { Group {
if let tip = pen.style.compactIcon.tip { if let tip = pen.style.compactIcon.tip {
@@ -554,7 +559,7 @@ struct PenDock: View {
} }
} }
func createNewPen() { private func createNewPen() {
let pen = PenObject.createObject(\.viewContext, penStyle: .marker) let pen = PenObject.createObject(\.viewContext, penStyle: .marker)
var selectedPen = tool.selectedPen var selectedPen = tool.selectedPen
selectedPen = (selectedPen?.strokeStyle == .marker ? (selectedPen ?? tool.pens.last) : tool.pens.last) selectedPen = (selectedPen?.strokeStyle == .marker ? (selectedPen ?? tool.pens.last) : tool.pens.last)
@@ -9,9 +9,15 @@ import SwiftUI
import Foundation import Foundation
struct PenDropDelegate: DropDelegate { struct PenDropDelegate: DropDelegate {
let id: String private let id: String
@ObservedObject var tool: Tool @ObservedObject private var tool: Tool
let action: () -> Void private let action: () -> Void
init(id: String, tool: Tool, action: @escaping () -> Void) {
self.id = id
self.tool = tool
self.action = action
}
func performDrop(info: DropInfo) -> Bool { func performDrop(info: DropInfo) -> Bool {
tool.draggedPen = nil tool.draggedPen = nil
+16 -11
View File
@@ -9,16 +9,21 @@ import SwiftUI
import PhotosUI import PhotosUI
struct PhotoDock: View { struct PhotoDock: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
let size: CGFloat = 40
@ObservedObject var tool: Tool private let size: CGFloat = 40
@ObservedObject var canvas: Canvas
@State var opensCamera: Bool = false @ObservedObject private var tool: Tool
@State var isCameraAccessDenied: Bool = false @ObservedObject private var canvas: Canvas
@State var photosPickerItem: PhotosPickerItem?
@State private var opensCamera: Bool = false
@State private var isCameraAccessDenied: Bool = false
@State private var photosPickerItem: PhotosPickerItem?
init(tool: Tool, canvas: Canvas) {
self.tool = tool
self.canvas = canvas
}
var body: some View { var body: some View {
Group { Group {
@@ -71,7 +76,7 @@ struct PhotoDock: View {
} }
} }
var photoOption: some View { private var photoOption: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
#if os(iOS) #if os(iOS)
Button { Button {
@@ -126,7 +131,7 @@ struct PhotoDock: View {
.transition(.move(edge: .trailing).combined(with: .blurReplace)) .transition(.move(edge: .trailing).combined(with: .blurReplace))
} }
var compactPhotoOption: some View { private var compactPhotoOption: some View {
HStack(spacing: 0) { HStack(spacing: 0) {
#if os(iOS) #if os(iOS)
Button { Button {
@@ -181,7 +186,7 @@ struct PhotoDock: View {
.transition(.move(edge: .bottom).combined(with: .blurReplace)) .transition(.move(edge: .bottom).combined(with: .blurReplace))
} }
func openCamera() { private func openCamera() {
let status = AVCaptureDevice.authorizationStatus(for: .video) let status = AVCaptureDevice.authorizationStatus(for: .video)
switch status { switch status {
case .notDetermined: case .notDetermined:
@@ -8,10 +8,15 @@
import SwiftUI import SwiftUI
struct PhotoPreview: View { struct PhotoPreview: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
let photoItem: PhotoItem private let photoItem: PhotoItem
@ObservedObject var tool: Tool @ObservedObject private var tool: Tool
init(photoItem: PhotoItem, tool: Tool) {
self.photoItem = photoItem
self.tool = tool
}
var body: some View { var body: some View {
Image(image: photoItem.previewImage) Image(image: photoItem.previewImage)
+14 -14
View File
@@ -9,19 +9,19 @@ import SwiftUI
import Foundation import Foundation
struct Toolbar: View { struct Toolbar: View {
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) private var dismiss
@Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
@ObservedObject var tool: Tool @ObservedObject private var tool: Tool
@ObservedObject var canvas: Canvas @ObservedObject private var canvas: Canvas
@ObservedObject var history: History @ObservedObject private var history: History
@State var title: String @State private var title: String
@FocusState var textFieldState: Bool @FocusState private var textFieldState: Bool
let size: CGFloat = 40 private let size: CGFloat = 40
let memo: MemoObject private let memo: MemoObject
init(memo: MemoObject, tool: Tool, canvas: Canvas, history: History) { init(memo: MemoObject, tool: Tool, canvas: Canvas, history: History) {
self.memo = memo self.memo = memo
@@ -57,7 +57,7 @@ struct Toolbar: View {
.foregroundStyle(Color.accentColor) .foregroundStyle(Color.accentColor)
} }
var closeButton: some View { private var closeButton: some View {
Button { Button {
closeMemo() closeMemo()
} label: { } label: {
@@ -76,7 +76,7 @@ struct Toolbar: View {
.transition(.move(edge: .top).combined(with: .blurReplace)) .transition(.move(edge: .top).combined(with: .blurReplace))
} }
var titleField: some View { private var titleField: some View {
TextField("", text: $title) TextField("", text: $title)
.focused($textFieldState) .focused($textFieldState)
.textFieldStyle(.plain) .textFieldStyle(.plain)
@@ -100,7 +100,7 @@ struct Toolbar: View {
.transition(.move(edge: .top).combined(with: .blurReplace)) .transition(.move(edge: .top).combined(with: .blurReplace))
} }
var historyControl: some View { private var historyControl: some View {
HStack(spacing: 0) { HStack(spacing: 0) {
Button { Button {
history.historyPublisher.send(.undo) history.historyPublisher.send(.undo)
@@ -135,7 +135,7 @@ struct Toolbar: View {
.transition(.move(edge: .top).combined(with: .blurReplace)) .transition(.move(edge: .top).combined(with: .blurReplace))
} }
var gridModeControl: some View { private var gridModeControl: some View {
#if os(macOS) #if os(macOS)
Button { Button {
switch canvas.gridMode { switch canvas.gridMode {
@@ -183,7 +183,7 @@ struct Toolbar: View {
#endif #endif
} }
func closeMemo() { private func closeMemo() {
canvas.save(for: memo) { canvas.save(for: memo) {
#if os(macOS) #if os(macOS)
MemoManager.shared.closeMemo() MemoManager.shared.closeMemo()
@@ -77,14 +77,6 @@ final class Persistence {
fatalError("[Memola]: \(error.localizedDescription)") fatalError("[Memola]: \(error.localizedDescription)")
} }
}() }()
static func loadMemo(of url: URL) -> MemoObject? {
let viewContext = shared.viewContext
guard let objectID = viewContext.persistentStoreCoordinator?.managedObjectID(forURIRepresentation: url) else {
return nil
}
return viewContext.object(with: objectID) as? MemoObject
}
} }
// MARK: - Global Method // MARK: - Global Method
+1 -1
View File
@@ -9,7 +9,7 @@ import CoreData
import Foundation import Foundation
@objc(PenObject) @objc(PenObject)
class PenObject: NSManagedObject { final class PenObject: NSManagedObject {
@NSManaged var color: [CGFloat] @NSManaged var color: [CGFloat]
@NSManaged var style: Int16 @NSManaged var style: Int16
@NSManaged var thickness: CGFloat @NSManaged var thickness: CGFloat
+1 -1
View File
@@ -9,7 +9,7 @@ import CoreData
import Foundation import Foundation
@objc(PhotoObject) @objc(PhotoObject)
class PhotoObject: NSManagedObject { final class PhotoObject: NSManagedObject {
@NSManaged var width: CGFloat @NSManaged var width: CGFloat
@NSManaged var originY: CGFloat @NSManaged var originY: CGFloat
@NSManaged var originX: CGFloat @NSManaged var originX: CGFloat
+1 -1
View File
@@ -9,7 +9,7 @@ import CoreData
import Foundation import Foundation
@objc(ToolObject) @objc(ToolObject)
class ToolObject: NSManagedObject { final class ToolObject: NSManagedObject {
@NSManaged var selection: Int16 @NSManaged var selection: Int16
@NSManaged var pens: NSMutableSet @NSManaged var pens: NSMutableSet
@NSManaged var memo: MemoObject? @NSManaged var memo: MemoObject?
+2 -2
View File
@@ -8,8 +8,8 @@
import SwiftUI import SwiftUI
struct FileCommands: Commands { struct FileCommands: Commands {
@Environment(\.shortcut) var shortcut @Environment(\.shortcut) private var shortcut
@FocusedValue(\.activeSceneKey) var appScene @FocusedValue(\.activeSceneKey) private var appScene
var body: some Commands { var body: some Commands {
CommandGroup(replacing: .newItem) { CommandGroup(replacing: .newItem) {
+7 -7
View File
@@ -8,18 +8,18 @@
import SwiftUI import SwiftUI
struct ViewCommands: Commands { struct ViewCommands: Commands {
@FocusedValue(\.activeSceneKey) var appScene @ObservedObject private var application: Application
@FocusedValue(\.activeSceneKey) private var appScene
init(application: Application) {
self.application = application
}
var body: some Commands { var body: some Commands {
CommandGroup(replacing: .toolbar) { CommandGroup(replacing: .toolbar) {
if appScene == .trash || appScene == .memos { if appScene == .trash || appScene == .memos {
Button { Button {
#if os(macOS) application.activateSearchBar()
guard let toolbar = NSApp.keyWindow?.toolbar else { return }
if let search = toolbar.items.first(where: { $0.itemIdentifier.rawValue == "com.apple.SwiftUI.search" }) as? NSSearchToolbarItem {
search.beginSearchInteraction()
}
#endif
} label: { } label: {
Text("Find Memo") Text("Find Memo")
} }
+7 -7
View File
@@ -8,18 +8,18 @@
import Combine import Combine
import Foundation import Foundation
class Shortcut { final class Shortcut {
static let shared: Shortcut = .init() static let shared: Shortcut = .init()
private let shortcutPublisher = PassthroughSubject<Shortcuts, Never>() private let _publisher = PassthroughSubject<Shortcuts, Never>()
lazy var publisher: AnyPublisher<Shortcuts, Never> = {
_publisher.eraseToAnyPublisher()
}()
private init() { } private init() { }
func trigger(_ shortcut: Shortcuts) { func trigger(_ shortcut: Shortcuts) {
shortcutPublisher.send(shortcut) _publisher.send(shortcut)
}
func publisher() -> AnyPublisher<Shortcuts, Never> {
shortcutPublisher.eraseToAnyPublisher()
} }
} }
@@ -7,7 +7,7 @@
import SwiftUI import SwiftUI
struct ShortcutKey: EnvironmentKey { private struct ShortcutKey: EnvironmentKey {
static var defaultValue: Shortcut = .shared static var defaultValue: Shortcut = .shared
} }
+1 -1
View File
@@ -7,7 +7,7 @@
import SwiftUI import SwiftUI
struct ActiveSceneKey: FocusedValueKey { private struct ActiveSceneKey: FocusedValueKey {
typealias Value = AppScene typealias Value = AppScene
} }
@@ -0,0 +1,13 @@
//
// SidebarVisibility.swift
// Memola
//
// Created by Dscyre Scotti on 7/14/24.
//
import Foundation
enum SidebarVisibility {
case shown
case hidden
}