diff --git a/Memola.xcodeproj/project.pbxproj b/Memola.xcodeproj/project.pbxproj index f2e3a84..bd344ef 100644 --- a/Memola.xcodeproj/project.pbxproj +++ b/Memola.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ EC0D14282BF7BF20009BFE5F /* ContextMenuViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0D14272BF7BF20009BFE5F /* ContextMenuViewModifier.swift */; }; EC1815082C2D980B00541369 /* Sort.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1815072C2D980B00541369 /* Sort.swift */; }; EC18150A2C2DA09E00541369 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1815092C2DA09E00541369 /* Filter.swift */; }; + EC18150D2C2DAC3700541369 /* Placeholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC18150C2C2DAC3700541369 /* Placeholder.swift */; }; EC1B783D2BFA0AC9005A34E2 /* Toolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1B783C2BFA0AC9005A34E2 /* Toolbar.swift */; }; EC2106AD2C10C2A700FBE27C /* AnyStroke.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2106AC2C10C2A700FBE27C /* AnyStroke.swift */; }; EC2BEBF42C0F5FF7005DB0AF /* RTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2BEBF32C0F5FF7005DB0AF /* RTree.swift */; }; @@ -121,6 +122,7 @@ EC0D14272BF7BF20009BFE5F /* ContextMenuViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuViewModifier.swift; sourceTree = ""; }; EC1815072C2D980B00541369 /* Sort.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sort.swift; sourceTree = ""; }; EC1815092C2DA09E00541369 /* Filter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = ""; }; + EC18150C2C2DAC3700541369 /* Placeholder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Placeholder.swift; sourceTree = ""; }; EC1B783C2BFA0AC9005A34E2 /* Toolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toolbar.swift; sourceTree = ""; }; EC2106AC2C10C2A700FBE27C /* AnyStroke.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyStroke.swift; sourceTree = ""; }; EC2BEBF32C0F5FF7005DB0AF /* RTree.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RTree.swift; sourceTree = ""; }; @@ -251,9 +253,18 @@ path = ViewController; sourceTree = ""; }; + EC18150B2C2DA3AD00541369 /* Placeholder */ = { + isa = PBXGroup; + children = ( + EC18150C2C2DAC3700541369 /* Placeholder.swift */, + ); + path = Placeholder; + sourceTree = ""; + }; EC1B783A2BF9C68C005A34E2 /* Views */ = { isa = PBXGroup; children = ( + EC18150B2C2DA3AD00541369 /* Placeholder */, ECBE529B2C1D94A4006BDB3D /* CameraView */, ECFC51252BF8885000D0D051 /* ColorPicker */, ); @@ -973,6 +984,7 @@ ECA738BC2BE60E0300A4542E /* Tool.swift in Sources */, ECA738972BE6014200A4542E /* Graphic.metal in Sources */, ECA7388A2BE6006A00A4542E /* PipelineStates.swift in Sources */, + EC18150D2C2DAC3700541369 /* Placeholder.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Memola/Components/Views/Placeholder/Placeholder.swift b/Memola/Components/Views/Placeholder/Placeholder.swift new file mode 100644 index 0000000..035f11d --- /dev/null +++ b/Memola/Components/Views/Placeholder/Placeholder.swift @@ -0,0 +1,56 @@ +// +// Placeholder.swift +// Memola +// +// Created by Dscyre Scotti on 6/27/24. +// + +import SwiftUI + +struct Placeholder: View { + let info: Info + + var body: some View { + VStack(spacing: 15) { + Image(systemName: info.icon) + .font(.system(size: 50)) + .frame(width: 55, height: 55) + VStack(spacing: 3) { + Text(info.title) + .font(.title2) + .fontWeight(.bold) + .foregroundStyle(.primary) + Text(info.description) + .font(.callout) + .fontWeight(.regular) + .frame(minHeight: 50, alignment: .top) + } + } + .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + .padding() + .frame(maxWidth: .infinity, maxHeight: .infinity) + } +} + +extension Placeholder { + struct Info { + let title: String + let description: String + let icon: String + + static let memoNotFound: Info = { + let icon: String = "sparkle.magnifyingglass" + let title: String = "No Memos Found" + let description: String = "Explore your other memos or create your own." + return Placeholder.Info(title: title, description: description, icon: icon) + }() + + static let memoEmpty: Info = { + let icon: String = "wand.and.stars" + let title: String = "No Memos" + let description: String = "Create a new memo to jot your thoughts or notes down." + return Placeholder.Info(title: title, description: description, icon: icon) + }() + } +} diff --git a/Memola/Features/Memos/MemosView.swift b/Memola/Features/Memos/MemosView.swift index 53cec28..92964f0 100644 --- a/Memola/Features/Memos/MemosView.swift +++ b/Memola/Features/Memos/MemosView.swift @@ -37,7 +37,7 @@ struct MemosView: View { var body: some View { NavigationStack { memoGrid - .navigationTitle("Memos") + .navigationTitle("Memola") .searchable(text: $query, placement: .toolbar, prompt: Text("Search")) .toolbar { ToolbarItemGroup(placement: .primaryAction) { @@ -98,17 +98,22 @@ struct MemosView: View { } } + @ViewBuilder var memoGrid: some View { - GeometryReader { proxy in - let count = Int(proxy.size.width / cellWidth) - let columns: [GridItem] = .init(repeating: GridItem(.flexible(), spacing: 15), count: count) - ScrollView { - LazyVGrid(columns: columns, spacing: 15) { - ForEach(memoObjects) { memo in - memoCard(memo) + if memoObjects.isEmpty { + Placeholder(info: query.isEmpty ? .memoEmpty : .memoNotFound) + } else { + GeometryReader { proxy in + let count = Int(proxy.size.width / cellWidth) + let columns: [GridItem] = .init(repeating: GridItem(.flexible(), spacing: 15), count: count) + ScrollView { + LazyVGrid(columns: columns, spacing: 15) { + ForEach(memoObjects) { memo in + memoCard(memo) + } } + .padding() } - .padding() } } }