From 0f8a0c8fb24f551d262570a15b0802ab42f6b44b Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sat, 5 Oct 2024 10:40:14 +0200 Subject: [PATCH 01/12] Removed the UnitTests boilerplate from the unit tests target. --- Piper.xcodeproj/project.pbxproj | 2 -- Tests/UnitTests/UnitTests.swift | 17 ----------------- 2 files changed, 19 deletions(-) delete mode 100644 Tests/UnitTests/UnitTests.swift diff --git a/Piper.xcodeproj/project.pbxproj b/Piper.xcodeproj/project.pbxproj index 55a9a07..e7e90a1 100644 --- a/Piper.xcodeproj/project.pbxproj +++ b/Piper.xcodeproj/project.pbxproj @@ -36,7 +36,6 @@ UITests/UITests.swift, UITests/UITestsLaunchTests.swift, UnitTests/Tests/UseCases/RunProcessUseCaseTests.swift, - UnitTests/UnitTests.swift, ); target = 46D4BE762CB06ED300FCFB84 /* Piper */; }; @@ -44,7 +43,6 @@ isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( UnitTests/Tests/UseCases/RunProcessUseCaseTests.swift, - UnitTests/UnitTests.swift, ); target = 46D4BED32CB07C7A00FCFB84 /* UnitTests */; }; diff --git a/Tests/UnitTests/UnitTests.swift b/Tests/UnitTests/UnitTests.swift deleted file mode 100644 index c329a8f..0000000 --- a/Tests/UnitTests/UnitTests.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// UnitTests.swift -// UnitTests -// -// Created by Javier Cicchelli on 04/10/2024. -// Copyright © 2024 Röck+Cöde. All rights reserved. -// - -import Testing - -struct UnitTests { - - @Test func example() async throws { - // Write your test here and use APIs like `#expect(...)` to check expected conditions. - } - -} -- 2.47.1 From 5bbd8dedbc462b1765c7cb3167dd4ce0be38ed05 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 00:03:22 +0200 Subject: [PATCH 02/12] Implemented the "entities" static constant for the Scheme+Constants extension in the app target. --- .../Logic/Extensions/Schema+Constants.swift | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Piper/Sources/Logic/Extensions/Schema+Constants.swift diff --git a/Piper/Sources/Logic/Extensions/Schema+Constants.swift b/Piper/Sources/Logic/Extensions/Schema+Constants.swift new file mode 100644 index 0000000..934a1c5 --- /dev/null +++ b/Piper/Sources/Logic/Extensions/Schema+Constants.swift @@ -0,0 +1,20 @@ +// +// Schema+Constants.swift +// Piper ~ App +// +// Created by Javier Cicchelli on 05/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import SwiftData + +extension Schema { + + // MARK: Constants + + static let entities = Schema([ + Repository.self + ]) + + +} -- 2.47.1 From e00c7f810fa7eac247c56dfaead0561bedf9bc9c Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 00:04:33 +0200 Subject: [PATCH 03/12] Implemented the "init(_: schema: url: )" initialiser function for the ModelConfiguration+Inits extension in the app target. --- .../Extensions/ModelConfiguration+Inits.swift | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Piper/Sources/Logic/Extensions/ModelConfiguration+Inits.swift diff --git a/Piper/Sources/Logic/Extensions/ModelConfiguration+Inits.swift b/Piper/Sources/Logic/Extensions/ModelConfiguration+Inits.swift new file mode 100644 index 0000000..8ddcba2 --- /dev/null +++ b/Piper/Sources/Logic/Extensions/ModelConfiguration+Inits.swift @@ -0,0 +1,30 @@ +// +// ModelConfiguration+Inits.swift +// Piper ~ App +// +// Created by Javier Cicchelli on 05/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import Foundation +import SwiftData + +extension ModelConfiguration { + + // MARK: Initialisers + + init( + _ name: String? = nil, + schema: Schema = .entities, + url: URL = .applicationSupportDirectory.appending(component: "piper.db") + ) { + self.init( + name, + schema: schema, + url: url, + allowsSave: true, + cloudKitDatabase: .none + ) + } + +} -- 2.47.1 From 37da8449388fce53dfb50b8138f5017950824c4f Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 00:20:31 +0200 Subject: [PATCH 04/12] Implemented the "container" property for the PiperApp app in the app target. --- Piper/Sources/App/PiperApp.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Piper/Sources/App/PiperApp.swift b/Piper/Sources/App/PiperApp.swift index b08661e..6999af0 100644 --- a/Piper/Sources/App/PiperApp.swift +++ b/Piper/Sources/App/PiperApp.swift @@ -14,16 +14,14 @@ struct PiperApp: App { // MARK: Properties - var sharedModelContainer: ModelContainer = { - let schema = Schema([ - Item.self, - ]) - let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) - + private var container = { do { - return try ModelContainer(for: schema, configurations: [modelConfiguration]) + return try ModelContainer( + for: .entities, + configurations: [ModelConfiguration()] + ) } catch { - fatalError("Could not create ModelContainer: \(error)") + fatalError("ERROR: ModelContainer has not been created => \(error)") } }() -- 2.47.1 From 62b569637887f53a90c0f6d72d66504f2577d4fa Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 00:21:37 +0200 Subject: [PATCH 05/12] Implemented the Repository model in the app target. --- Piper/Sources/Logic/Models/Repository.swift | 38 +++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Piper/Sources/Logic/Models/Repository.swift diff --git a/Piper/Sources/Logic/Models/Repository.swift b/Piper/Sources/Logic/Models/Repository.swift new file mode 100644 index 0000000..ba64914 --- /dev/null +++ b/Piper/Sources/Logic/Models/Repository.swift @@ -0,0 +1,38 @@ +// +// Repository.swift +// Piper ~ App +// +// Created by Javier Cicchelli on 05/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import Foundation +import SwiftData + +@Model +final class Repository { + + // MARK: Properties + + @Attribute(.unique) var path: URL + + var addedAt: Date + var sortOrder: Int + + // MARK: Initialisers + + init( + _ path: URL, + sortOrder: Int, + addedAt: Date = .now + ) { + self.path = path + self.addedAt = addedAt + self.sortOrder = sortOrder + } + + // MARK: Computed + + @Transient var name: String { path.lastPathComponent } + +} -- 2.47.1 From a12354d6134ce082b6f1add0a2683b6dfbc3fbcd Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 11:12:16 +0200 Subject: [PATCH 06/12] Implemented the ListHeader component in the app target. --- Piper/Sources/UI/Components/ListHeader.swift | 77 ++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Piper/Sources/UI/Components/ListHeader.swift diff --git a/Piper/Sources/UI/Components/ListHeader.swift b/Piper/Sources/UI/Components/ListHeader.swift new file mode 100644 index 0000000..2223432 --- /dev/null +++ b/Piper/Sources/UI/Components/ListHeader.swift @@ -0,0 +1,77 @@ +// +// ListHeader.swift +// Piper ~ App +// +// Created by Javier Cicchelli on 06/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +struct ListHeader: View { + + // MARK: Properties + + let title: LocalizedStringKey + let button: LocalizedStringKey + let showButton: Bool + let onAction: () -> Void + + // MARK: Body + + var body: some View { + HStack { + Text(title) + .font(.headline) + .foregroundStyle(.primary) + + if showButton { + Spacer() + + Button( + button, + action: onAction + ) + .buttonStyle(.borderless) + } + } + .padding(.vertical) + } + +} + +// MARK: - Previews + +#Preview("List Section component with title") { + List { + Section { + EmptyView() + } header: { + ListHeader( + title: "Some title goes here...", + button: "Some button goes here...", + showButton: false + ) { + // ... + } + } + } + .frame(width: 400, height: 100) +} + +#Preview("List Section component with title and button") { + List { + Section { + EmptyView() + } header: { + ListHeader( + title: "Some title goes here...", + button: "Some button goes here...", + showButton: true + ) { + // ... + } + } + } + .frame(width: 400, height: 100) +} -- 2.47.1 From 364fa4f3d5464b196c6696b190207cdfae2d988d Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 12:08:06 +0200 Subject: [PATCH 07/12] Implemented the ListItemEmpty component in the app target. --- .../Sources/UI/Components/ListItemEmpty.swift | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 Piper/Sources/UI/Components/ListItemEmpty.swift diff --git a/Piper/Sources/UI/Components/ListItemEmpty.swift b/Piper/Sources/UI/Components/ListItemEmpty.swift new file mode 100644 index 0000000..66e4b91 --- /dev/null +++ b/Piper/Sources/UI/Components/ListItemEmpty.swift @@ -0,0 +1,61 @@ +// +// ListItemEmpty.swift +// Piper ~ App +// +// Created by Javier Cicchelli on 06/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +struct ListItemEmpty: View { + + // MARK: Properties + + let title: LocalizedStringKey + let button: LocalizedStringKey + let onAction: () -> Void + + // MARK: Body + + var body: some View { + GeometryReader { proxy in + Color.clear + .overlay { + VStack(spacing: 16) { + Text(title) + .font(.title) + .foregroundStyle(.secondary) + .frame(maxWidth: .infinity) + .multilineTextAlignment(.center) + + Button(action: onAction) { + Text(button) + .font(.body) + .fontWeight(.semibold) + .multilineTextAlignment(.center) + } + .buttonStyle(.link) + .foregroundStyle(.primary) + } + } + .padding(.horizontal, proxy.size.width * 0.2) + } + } + +} + +// MARK: - Previews + +#Preview("List Item Empty component with title and button") { + List { + ListItemEmpty( + title: "Some title text goes here...", + button: "Some button text goes here..." + ) { + // ... + } + .frame(height: 300) + } + .frame(width: 400, height: 300) +} -- 2.47.1 From 0d43a148db30307eee35b7d8177e4be9b3487ae6 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 13:10:50 +0200 Subject: [PATCH 08/12] Implemented the ListItem component in the app target. --- Piper/Sources/UI/Components/ListItem.swift | 85 ++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Piper/Sources/UI/Components/ListItem.swift diff --git a/Piper/Sources/UI/Components/ListItem.swift b/Piper/Sources/UI/Components/ListItem.swift new file mode 100644 index 0000000..0b97888 --- /dev/null +++ b/Piper/Sources/UI/Components/ListItem.swift @@ -0,0 +1,85 @@ +// +// ListItem.swift +// Piper ~ App +// +// Created by Javier Cicchelli on 06/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +struct ListItem: View { + + // MARK: Properties + + let repository: Repository + + // MARK: Body + + var body: some View { + Label { + VStack( + alignment: .leading, + spacing: 4 + ) { + Text(repository.name) + .font(.title) + .fontWeight(.semibold) + .foregroundStyle(.primary) + + Text(repository.path.relativePath) + .font(.subheadline) + .foregroundStyle(.secondary) + } + } icon: { + Image(systemName: "folder") + .resizable() + } + .labelStyle(ItemLabelStyle()) + .padding(.vertical, 8) + } + +} + +// MARK: - Label Styles + +struct ItemLabelStyle: LabelStyle { + func makeBody(configuration: Configuration) -> some View { + HStack( + alignment: .center, + spacing: 16 + ) { + configuration.icon + .frame(width: 44) + + configuration.title + .frame(maxWidth: .infinity, alignment: .leading) + } + } +} + +// MARK: - Previews + +#Preview("List Item component") { + List { + ListItem( + repository: .init( + .init(filePath: "/full/path/to/repository/name.git")!, + sortOrder: 0 + ) + ) + ListItem( + repository: .init( + .init(filePath: "/full/path/to/repository/name.git")!, + sortOrder: 0 + ) + ) + ListItem( + repository: .init( + .init(filePath: "/full/path/to/repository/name.git")!, + sortOrder: 0 + ) + ) + } + .frame(width: 400, height: 220) +} -- 2.47.1 From cd9bd975b427b65523777452e9427a997d9ccf17 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 13:35:03 +0200 Subject: [PATCH 09/12] Implemented the "samples(in: )" static function for the Repository+Samples extension in the app target. --- Piper.xcodeproj/project.pbxproj | 4 +-- .../Extensions/Repository+Samples.swift | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 Piper/Sources/Previews/Extensions/Repository+Samples.swift diff --git a/Piper.xcodeproj/project.pbxproj b/Piper.xcodeproj/project.pbxproj index e7e90a1..102f43f 100644 --- a/Piper.xcodeproj/project.pbxproj +++ b/Piper.xcodeproj/project.pbxproj @@ -429,7 +429,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = Piper/Resources/Catalogs/Previews.xcassets; + DEVELOPMENT_ASSET_PATHS = "Piper/Sources/Previews/Extensions/Repository+Samples.swift Piper/Resources/Catalogs/Previews.xcassets"; DEVELOPMENT_TEAM = 7FMNM89WKG; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; @@ -461,7 +461,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = Piper/Resources/Catalogs/Previews.xcassets; + DEVELOPMENT_ASSET_PATHS = "Piper/Sources/Previews/Extensions/Repository+Samples.swift Piper/Resources/Catalogs/Previews.xcassets"; DEVELOPMENT_TEAM = 7FMNM89WKG; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; diff --git a/Piper/Sources/Previews/Extensions/Repository+Samples.swift b/Piper/Sources/Previews/Extensions/Repository+Samples.swift new file mode 100644 index 0000000..9264b5b --- /dev/null +++ b/Piper/Sources/Previews/Extensions/Repository+Samples.swift @@ -0,0 +1,36 @@ +// +// Repository+Samples.swift +// Piper +// +// Created by Javier Cicchelli on 06/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import Foundation +import SwiftData + +extension Repository { + + // MARK: Functions + + @MainActor + static func samples(in container: ModelContainer) { + let context = container.mainContext + + context.insert(Repository( + URL(filePath: "/full/path/to/repository/name-0.git"), + sortOrder: 0 + )) + + context.insert(Repository( + URL(filePath: "/full/path/to/repository/name-1.git"), + sortOrder: 1 + )) + + context.insert(Repository( + URL(filePath: "/full/path/to/repository/name-2.git"), + sortOrder: 2 + )) + } + +} -- 2.47.1 From b4a6491db76cb1a3a11cb5bb15f0a0c02c2d93d2 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 13:41:30 +0200 Subject: [PATCH 10/12] Implemented the "preview" constant for the ModelContainer+Constants extension in the app target. --- Piper.xcodeproj/project.pbxproj | 4 +-- .../Extensions/ModelContainer+Constants.swift | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 Piper/Sources/Previews/Extensions/ModelContainer+Constants.swift diff --git a/Piper.xcodeproj/project.pbxproj b/Piper.xcodeproj/project.pbxproj index 102f43f..fc590bd 100644 --- a/Piper.xcodeproj/project.pbxproj +++ b/Piper.xcodeproj/project.pbxproj @@ -429,7 +429,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "Piper/Sources/Previews/Extensions/Repository+Samples.swift Piper/Resources/Catalogs/Previews.xcassets"; + DEVELOPMENT_ASSET_PATHS = "Piper/Sources/Previews/Extensions/Repository+Samples.swift Piper/Sources/Previews/Extensions/ModelContainer+Constants.swift Piper/Resources/Catalogs/Previews.xcassets"; DEVELOPMENT_TEAM = 7FMNM89WKG; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; @@ -461,7 +461,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "Piper/Sources/Previews/Extensions/Repository+Samples.swift Piper/Resources/Catalogs/Previews.xcassets"; + DEVELOPMENT_ASSET_PATHS = "Piper/Sources/Previews/Extensions/Repository+Samples.swift Piper/Sources/Previews/Extensions/ModelContainer+Constants.swift Piper/Resources/Catalogs/Previews.xcassets"; DEVELOPMENT_TEAM = 7FMNM89WKG; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; diff --git a/Piper/Sources/Previews/Extensions/ModelContainer+Constants.swift b/Piper/Sources/Previews/Extensions/ModelContainer+Constants.swift new file mode 100644 index 0000000..21d51a5 --- /dev/null +++ b/Piper/Sources/Previews/Extensions/ModelContainer+Constants.swift @@ -0,0 +1,26 @@ +// +// ModelContainer+Constants.swift +// Piper +// +// Created by Javier Cicchelli on 06/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import SwiftData + +extension ModelContainer { + + // MARK: Constants + + static let preview: ModelContainer = { + do { + return try ModelContainer( + for: .entities, + configurations: ModelConfiguration(isStoredInMemoryOnly: true) + ) + } catch { + fatalError("Model Container should have been created.") + } + }() + +} -- 2.47.1 From 3ed1cc92f70d1fa7d4c4c8484725fa3148eed76c Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 13:44:15 +0200 Subject: [PATCH 11/12] Implemented the list layout for the repositories for the MenuBarView view in the app target. --- Piper.xcodeproj/project.pbxproj | 2 + .../Resources/Catalogs/Localizable.xcstrings | 56 +++++++++++++ .../Logic/ViewModels/MenuBarViewModel.swift | 20 +++++ Piper/Sources/UI/Views/MenuBarView.swift | 81 +++++++++++++++++++ 4 files changed, 159 insertions(+) create mode 100644 Piper/Resources/Catalogs/Localizable.xcstrings create mode 100644 Piper/Sources/Logic/ViewModels/MenuBarViewModel.swift create mode 100644 Piper/Sources/UI/Views/MenuBarView.swift diff --git a/Piper.xcodeproj/project.pbxproj b/Piper.xcodeproj/project.pbxproj index fc590bd..e9c7c3f 100644 --- a/Piper.xcodeproj/project.pbxproj +++ b/Piper.xcodeproj/project.pbxproj @@ -361,6 +361,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; @@ -417,6 +418,7 @@ MTL_FAST_MATH = YES; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; }; name = Release; }; diff --git a/Piper/Resources/Catalogs/Localizable.xcstrings b/Piper/Resources/Catalogs/Localizable.xcstrings new file mode 100644 index 0000000..f26d581 --- /dev/null +++ b/Piper/Resources/Catalogs/Localizable.xcstrings @@ -0,0 +1,56 @@ +{ + "sourceLanguage" : "en", + "strings" : { + "Add Item" : { + + }, + "Item at %@" : { + + }, + "menu-bar.item.empty.button.text" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add a repository to the list" + } + } + } + }, + "menu-bar.item.empty.title.text" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No repositories have been defined yet." + } + } + } + }, + "menu-bar.section.repositories.button.text" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add" + } + } + } + }, + "menu-bar.section.repositories.title.text" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Repositories" + } + } + } + }, + "Select an item" : { + + } + }, + "version" : "1.0" +} \ No newline at end of file diff --git a/Piper/Sources/Logic/ViewModels/MenuBarViewModel.swift b/Piper/Sources/Logic/ViewModels/MenuBarViewModel.swift new file mode 100644 index 0000000..cb04301 --- /dev/null +++ b/Piper/Sources/Logic/ViewModels/MenuBarViewModel.swift @@ -0,0 +1,20 @@ +// +// MenuBarViewModel.swift +// Piper ~ App +// +// Created by Javier Cicchelli on 06/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import Observation + +@Observable +final class MenuBarViewModel { + + // MARK: Initialisers + + init () { + + } + +} diff --git a/Piper/Sources/UI/Views/MenuBarView.swift b/Piper/Sources/UI/Views/MenuBarView.swift new file mode 100644 index 0000000..9040121 --- /dev/null +++ b/Piper/Sources/UI/Views/MenuBarView.swift @@ -0,0 +1,81 @@ +// +// MenuBarView.swift +// Piper ~ App +// +// Created by Javier Cicchelli on 06/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import SwiftUI +import SwiftData + +struct MenuBarView: View { + + // MARK: Properties + + @Query(sort: \Repository.sortOrder) + private var repositories: [Repository] + + @State private var viewMode = MenuBarViewModel() + + // MARK: Body + + var body: some View { + List { + Section { + if repositories.isEmpty { + ListItemEmpty( + title: "menu-bar.item.empty.title.text", + button: "menu-bar.item.empty.button.text" + ) { + // ... + } + .frame(height: Layout.heightEmpty) + } else { + ForEach(repositories) { + ListItem(repository: $0) + } + } + } header: { + ListHeader( + title: "menu-bar.section.repositories.title.text", + button: "menu-bar.section.repositories.button.text", + showButton: !repositories.isEmpty + ) { + // ... + } + } + } + .frame( + width: Layout.widthView, + height: Layout.heightView + ) + } + +} + +// MARK: - Layout + +private extension MenuBarView { + enum Layout { + static let heightEmpty = CGFloat(200) + static let heightView = CGFloat(260) + static let widthView = CGFloat(400) + } +} + +// MARK: - Previews + +#Preview("Menu Bar view when no repositories found") { + MenuBarView() + .modelContainer(.preview) +} + +#Preview("Menu Bar view when some repositories found") { + let container = ModelContainer.preview + + Repository.samples(in: container) + + return MenuBarView() + .modelContainer(container) +} -- 2.47.1 From 77bb0e7bbbf666e9332429863ba5426345224a95 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 6 Oct 2024 13:44:56 +0200 Subject: [PATCH 12/12] Integrated the MenuBarView view into the MenuBarExtra component for the PiperApp app in the app target. --- Piper/Sources/App/PiperApp.swift | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Piper/Sources/App/PiperApp.swift b/Piper/Sources/App/PiperApp.swift index 6999af0..b8975a9 100644 --- a/Piper/Sources/App/PiperApp.swift +++ b/Piper/Sources/App/PiperApp.swift @@ -29,20 +29,8 @@ struct PiperApp: App { var body: some Scene { MenuBarExtra { - VStack(alignment: .leading) { - Text("Some text goes here...") - .foregroundStyle(.primary) - - Divider() - - Button { - // ... - } label: { - Text("Some text goes here...") - .frame(maxWidth: .infinity) - } - } - .padding() + MenuBarView() + .modelContainer(container) } label: { Image(systemName: "circle.fill") } -- 2.47.1