feat: open memo object over dasboardview instead of new window

This commit is contained in:
dscyrescotti
2024-07-07 18:35:10 +07:00
parent ab7d24fb4e
commit aafb2c74a2
10 changed files with 114 additions and 118 deletions

View File

@@ -28,6 +28,7 @@
EC2BEBF82C0F601A005DB0AF /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2BEBF72C0F601A005DB0AF /* Node.swift */; };
EC35655A2BF060D900A4E0BF /* Quad.metal in Sources */ = {isa = PBXBuildFile; fileRef = EC3565592BF060D900A4E0BF /* Quad.metal */; };
EC37FB122C1B2DD90008D976 /* ToolSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC37FB112C1B2DD90008D976 /* ToolSelection.swift */; };
EC3D67CC2C3AAD5E00359400 /* MemoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3D67CB2C3AAD5E00359400 /* MemoManager.swift */; };
EC42F7852C25267000E86E96 /* ElementGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC42F7842C25267000E86E96 /* ElementGroup.swift */; };
EC4538892BEBCAE000A86FEC /* Quad.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC4538882BEBCAE000A86FEC /* Quad.swift */; };
EC5050072BF65CED00B4D86E /* PenDropDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC5050062BF65CED00B4D86E /* PenDropDelegate.swift */; };
@@ -151,6 +152,7 @@
EC2BEBF72C0F601A005DB0AF /* Node.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = "<group>"; };
EC3565592BF060D900A4E0BF /* Quad.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = Quad.metal; sourceTree = "<group>"; };
EC37FB112C1B2DD90008D976 /* ToolSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolSelection.swift; sourceTree = "<group>"; };
EC3D67CB2C3AAD5E00359400 /* MemoManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MemoManager.swift; sourceTree = "<group>"; };
EC42F7842C25267000E86E96 /* ElementGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementGroup.swift; sourceTree = "<group>"; };
EC4538882BEBCAE000A86FEC /* Quad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Quad.swift; sourceTree = "<group>"; };
EC5050062BF65CED00B4D86E /* PenDropDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenDropDelegate.swift; sourceTree = "<group>"; };
@@ -279,6 +281,7 @@
EC01511C2C305C99008A115E /* Dashboard */ = {
isa = PBXGroup;
children = (
EC3D67CB2C3AAD5E00359400 /* MemoManager.swift */,
EC01511D2C305CA9008A115E /* DashboardView.swift */,
);
path = Dashboard;
@@ -1021,6 +1024,7 @@
ECA738A82BE6025900A4542E /* GraphicUniforms.swift in Sources */,
EC01511E2C305CA9008A115E /* DashboardView.swift in Sources */,
EC8F54AE2C2AF5A4001C7C74 /* LineGridVertex.swift in Sources */,
EC3D67CC2C3AAD5E00359400 /* MemoManager.swift in Sources */,
EC5E83902BFDB69C00261D9C /* MovingAverage.swift in Sources */,
ECFA15262BEF224900455818 /* StrokeObject.swift in Sources */,
ECA738FC2BE61C5200A4542E /* Persistence.swift in Sources */,

View File

@@ -29,19 +29,7 @@ struct MemolaApp: App {
.defaultPosition(.center)
.windowResizability(.contentSize)
.defaultSize(width: 1200, height: 800)
#endif
WindowGroup(id: "memo-view", for: URL.self) { url in
if let url = url.wrappedValue, let memo = Persistence.loadMemo(of: url) {
MemoView(memo: memo)
#if os(macOS)
.frame(minWidth: 1000, minHeight: 600)
#endif
}
}
#if os(macOS)
.defaultPosition(.center)
.windowResizability(.contentSize)
.defaultSize(width: 1200, height: 800)
.windowToolbarStyle(.unifiedCompact)
#endif
}
}

View File

@@ -10,38 +10,54 @@ import SwiftUI
struct DashboardView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
#if os(iOS)
@State var memo: MemoObject?
#endif
@StateObject var memoManager: MemoManager = .shared
@State var sidebarItem: SidebarItem? = .memos
@Namespace var namespace
var body: some View {
#if os(macOS)
NavigationSplitView {
Sidebar(sidebarItem: $sidebarItem, horizontalSizeClass: horizontalSizeClass)
} detail: {
switch sidebarItem {
case .memos:
#if os(macOS)
MemosView()
#else
MemosView(memo: $memo)
#endif
case .trash:
#if os(macOS)
TrashView(sidebarItem: $sidebarItem)
#else
TrashView(memo: $memo, sidebarItem: $sidebarItem)
#endif
default:
#if os(macOS)
MemosView()
#else
MemosView(memo: $memo)
#endif
}
}
#if os(iOS)
.fullScreenCover(item: $memo) { memo in
.toolbar(memoManager.memoObject == nil ? .visible : .hidden, for: .windowToolbar)
.toolbarBackground(memoManager.memoObject == nil ? .clear : Color(nsColor: .windowBackgroundColor), for: .windowToolbar)
.overlay {
if let memo = memoManager.memoObject {
MemoView(memo: memo)
.onDisappear {
withPersistence(\.viewContext) { context in
try context.saveIfNeeded()
context.refreshAllObjects()
}
}
.transition(.move(edge: .bottom))
}
}
#else
NavigationSplitView {
Sidebar(sidebarItem: $sidebarItem, horizontalSizeClass: horizontalSizeClass)
} detail: {
switch sidebarItem {
case .memos:
MemosView()
case .trash:
TrashView(sidebarItem: $sidebarItem)
default:
MemosView()
}
}
.fullScreenCover(item: $memoManager.memo) { memo in
MemoView(memo: memo)
.onDisappear {
withPersistence(\.viewContext) { context in
@@ -50,7 +66,6 @@ struct DashboardView: View {
}
}
}
#else
#endif
}
}

View File

@@ -0,0 +1,37 @@
//
// MemoManager.swift
// Memola
//
// Created by Dscyre Scotti on 7/7/24.
//
import SwiftUI
import Foundation
class MemoManager: ObservableObject {
static let shared: MemoManager = .init()
@Published var memoObject: MemoObject?
private init() { }
func openMemo(_ memoObject: MemoObject?) {
#if os(macOS)
withAnimation(.easeOut) {
self.memoObject = memoObject
}
#else
self.memoObject = memoObject
#endif
}
func closeMemo() {
#if os(macOS)
withAnimation(.easeOut) {
self.memoObject = nil
}
#else
self.memoObject = nil
#endif
}
}

View File

@@ -8,9 +8,6 @@
import SwiftUI
struct MemosView: View {
#if os(macOS)
@Environment(\.openWindow) var openWindow
#endif
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@FetchRequest var memoObjects: FetchedResults<MemoObject>
@@ -18,10 +15,6 @@ struct MemosView: View {
@State var query: String = ""
@State var currentDate: Date = .now
#if os(iOS)
@Binding var memo: MemoObject?
#endif
@AppStorage("memola.memo-objects.memos.sort") var sort: Sort = .recent
@AppStorage("memola.memo-objects.memos.filter") var filter: Filter = .none
@@ -31,7 +24,6 @@ struct MemosView: View {
query.isEmpty ? .memoEmpty : .memoNotFound
}
#if os(macOS)
init() {
let standard = UserDefaults.standard
var descriptors: [SortDescriptor<MemoObject>] = []
@@ -45,22 +37,6 @@ struct MemosView: View {
let predicate = NSCompoundPredicate(type: .and, subpredicates: predicates)
_memoObjects = FetchRequest(sortDescriptors: descriptors, predicate: predicate)
}
#else
init(memo: Binding<MemoObject?>) {
_memo = memo
let standard = UserDefaults.standard
var descriptors: [SortDescriptor<MemoObject>] = []
var predicates: [NSPredicate] = [NSPredicate(format: "isTrash = NO")]
let sort = Sort(rawValue: standard.value(forKey: "memola.memo-objects.memos.sort") as? String ?? "") ?? .recent
let filter = Filter(rawValue: standard.value(forKey: "memola.memo-objects.memos.filter") as? String ?? "") ?? .none
if filter == .favorites {
predicates.append(NSPredicate(format: "isFavorite = YES"))
}
descriptors = sort.memoSortDescriptors
let predicate = NSCompoundPredicate(type: .and, subpredicates: predicates)
_memoObjects = FetchRequest(sortDescriptors: descriptors, predicate: predicate)
}
#endif
var body: some View {
MemoGrid(memoObjects: memoObjects, placeholder: placeholder) { memoObject, cellWidth in
@@ -273,11 +249,7 @@ struct MemosView: View {
}
func openMemo(for memo: MemoObject) {
#if os(macOS)
openWindow(id: "memo-view", value: memo.objectID.uriRepresentation())
#else
self.memo = memo
#endif
MemoManager.shared.openMemo(memo)
}
func updatePredicate() {

View File

@@ -8,9 +8,6 @@
import SwiftUI
struct TrashView: View {
#if os(macOS)
@Environment(\.openWindow) var openWindow
#endif
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@FetchRequest var memoObjects: FetchedResults<MemoObject>
@@ -19,31 +16,18 @@ struct TrashView: View {
@State var restoredMemo: MemoObject?
@State var deletedMemo: MemoObject?
#if os(iOS)
@Binding var memo: MemoObject?
#endif
@Binding var sidebarItem: SidebarItem?
var placeholder: Placeholder.Info {
query.isEmpty ? .trashEmpty : .trashNotFound
}
#if os(macOS)
init(sidebarItem: Binding<SidebarItem?>) {
_sidebarItem = sidebarItem
let descriptors = [SortDescriptor(\MemoObject.deletedAt, order: .reverse)]
let predicate = NSPredicate(format: "isTrash = YES")
_memoObjects = FetchRequest(sortDescriptors: descriptors, predicate: predicate)
}
#else
init(memo: Binding<MemoObject?>, sidebarItem: Binding<SidebarItem?>) {
_memo = memo
_sidebarItem = sidebarItem
let descriptors = [SortDescriptor(\MemoObject.deletedAt, order: .reverse)]
let predicate = NSPredicate(format: "isTrash = YES")
_memoObjects = FetchRequest(sortDescriptors: descriptors, predicate: predicate)
}
#endif
var body: some View {
let restoresMemo = Binding<Bool> {
@@ -161,11 +145,7 @@ struct TrashView: View {
restoreMemo(for: memo)
self.sidebarItem = .memos
if let memo {
#if os(macOS)
openWindow(id: "memo-view", value: memo.objectID.uriRepresentation())
#else
self.memo = memo
#endif
MemoManager.shared.openMemo(memo)
}
}

View File

@@ -156,11 +156,13 @@ struct ElementToolbar: View {
.buttonStyle(.plain)
#endif
.background {
#if os(iOS)
if tool.selection == .photo {
Color.accentColor
.clipShape(.rect(cornerRadius: 8))
.matchedGeometryEffect(id: "element.toolbar.bg", in: namespace)
}
#endif
if tool.selection != .photo {
Color.clear
.matchedGeometryEffect(id: "element.toolbar.photo.options", in: namespace)
@@ -172,13 +174,6 @@ struct ElementToolbar: View {
.transition(.blurReplace.animation(.easeIn(duration: 0.1)))
}
}
// .background {
// if tool.selection == .photo {
// RoundedRectangle(cornerRadius: 8)
// .fill(Color.white.tertiary)
// .transition(.move(edge: .leading).combined(with: .opacity).animation(.easeIn(duration: 0.1)))
// }
// }
}
.background {
RoundedRectangle(cornerRadius: 8)
@@ -228,6 +223,7 @@ struct ElementToolbar: View {
var photoOption: some View {
HStack(spacing: 0) {
#if os(iOS)
Button {
openCamera()
} label: {
@@ -237,9 +233,7 @@ struct ElementToolbar: View {
.clipShape(.rect(cornerRadius: 8))
.contentShape(.rect(cornerRadius: 8))
}
#if os(iOS)
.hoverEffect(.lift)
#else
.buttonStyle(.plain)
#endif
PhotosPicker(selection: $photosPickerItem, matching: .images, preferredItemEncoding: .compatible) {

View File

@@ -15,10 +15,10 @@ struct MemoView: View {
@StateObject var canvas: Canvas
@StateObject var history: History
@State var memo: MemoObject
@State var title: String
@FocusState var textFieldState: Bool
let memo: MemoObject
let size: CGFloat = 32
init(memo: MemoObject) {

View File

@@ -62,35 +62,37 @@ struct PenDock: View {
.transition(.move(edge: .trailing).combined(with: .blurReplace))
}
} else {
ZStack(alignment: .bottomTrailing) {
if !canvas.locksCanvas {
GeometryReader { proxy in
HStack(alignment: .bottom, spacing: 10) {
newPenButton
.frame(height: height * factor - 18)
compactPenItemList
.fixedSize(horizontal: false, vertical: true)
compactPenPropertyTool
GeometryReader { proxy in
ZStack(alignment: .bottomTrailing) {
if !canvas.locksCanvas {
GeometryReader { proxy in
HStack(alignment: .bottom, spacing: 10) {
newPenButton
.frame(height: height * factor - 18)
compactPenItemList
.fixedSize(horizontal: false, vertical: true)
compactPenPropertyTool
}
.padding(.horizontal, 10)
.clipped()
.background(alignment: .bottom) {
RoundedRectangle(cornerRadius: 8)
.fill(.regularMaterial)
.frame(height: height * factor - 18)
}
.padding(.horizontal, 10)
.padding(.bottom, 20)
.frame(maxWidth: min(proxy.size.height, proxy.size.width), maxHeight: .infinity, alignment: .bottom)
.frame(maxWidth: .infinity)
}
.padding(.horizontal, 10)
.clipped()
.background(alignment: .bottom) {
RoundedRectangle(cornerRadius: 8)
.fill(.regularMaterial)
.frame(height: height * factor - 18)
}
.padding(.horizontal, 10)
.padding(.bottom, 20)
.frame(maxWidth: min(proxy.size.height, proxy.size.width), maxHeight: .infinity, alignment: .bottom)
.frame(maxWidth: .infinity)
.transition(.move(edge: .bottom).combined(with: .blurReplace))
}
.transition(.move(edge: .bottom).combined(with: .blurReplace))
lockButton
.frame(maxWidth: .infinity, alignment: .bottomTrailing)
.padding(10)
.offset(y: canvas.locksCanvas || proxy.size.width > proxy.size.height ? 0 : -(height * factor - size + 30))
.transition(.move(edge: .trailing).combined(with: .blurReplace))
}
lockButton
.frame(maxWidth: .infinity, alignment: .bottomTrailing)
.padding(10)
.offset(y: canvas.locksCanvas ? 0 : -(height * factor - size + 30))
.transition(.move(edge: .trailing).combined(with: .blurReplace))
}
}
#endif

View File

@@ -17,11 +17,11 @@ struct Toolbar: View {
@ObservedObject var history: History
@State var title: String
@State var memo: MemoObject
@FocusState var textFieldState: Bool
let size: CGFloat
let memo: MemoObject
init(size: CGFloat, memo: MemoObject, tool: Tool, canvas: Canvas, history: History) {
self.size = size
@@ -190,7 +190,11 @@ struct Toolbar: View {
func closeMemo() {
canvas.save(for: memo) {
#if os(macOS)
MemoManager.shared.closeMemo()
#else
dismiss()
#endif
}
}
}