From 2c0aea563988446318f679219ace0c8cf307815d Mon Sep 17 00:00:00 2001 From: Brad Root Date: Fri, 7 Apr 2023 23:43:56 -0700 Subject: [PATCH 1/4] get basic ui in place with swiftui --- GamebookEngine.xcodeproj/project.pbxproj | 8 +- GamebookEngine/AppDelegate.swift | 4 +- GamebookEngine/Extensions.swift | 18 +++ .../Views/Game List/GameListView.swift | 137 ++++++++++++++++++ 4 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 GamebookEngine/Views/Game List/GameListView.swift diff --git a/GamebookEngine.xcodeproj/project.pbxproj b/GamebookEngine.xcodeproj/project.pbxproj index 44f6077..0a42afc 100644 --- a/GamebookEngine.xcodeproj/project.pbxproj +++ b/GamebookEngine.xcodeproj/project.pbxproj @@ -42,6 +42,7 @@ 44C522EB232F0B6D00E7AC95 /* GamePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44C522EA232F0B6D00E7AC95 /* GamePlayer.swift */; }; 44CB58C32326CFB6009E49D9 /* An Introduction to Gamebook Engine.gbook in Resources */ = {isa = PBXBuildFile; fileRef = 44CB58C22326CFB6009E49D9 /* An Introduction to Gamebook Engine.gbook */; }; 44CB58C523286792009E49D9 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44CB58C423286792009E49D9 /* Logging.swift */; }; + 44F8AA9B29E12F0F0031BCBB /* GameListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44F8AA9A29E12F0F0031BCBB /* GameListView.swift */; }; B402FFEE2315FEFA00900020 /* MarkdownEditorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B402FFEC2315FEFA00900020 /* MarkdownEditorViewController.swift */; }; B402FFEF2315FEFA00900020 /* MarkdownEditorViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B402FFED2315FEFA00900020 /* MarkdownEditorViewController.xib */; }; B402FFF22316055000900020 /* BRMarkdownParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = B402FFF12316055000900020 /* BRMarkdownParser.swift */; }; @@ -149,6 +150,7 @@ 44C522EA232F0B6D00E7AC95 /* GamePlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamePlayer.swift; sourceTree = ""; }; 44CB58C22326CFB6009E49D9 /* An Introduction to Gamebook Engine.gbook */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "An Introduction to Gamebook Engine.gbook"; sourceTree = ""; }; 44CB58C423286792009E49D9 /* Logging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = ""; }; + 44F8AA9A29E12F0F0031BCBB /* GameListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameListView.swift; sourceTree = ""; }; B402FFEC2315FEFA00900020 /* MarkdownEditorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownEditorViewController.swift; sourceTree = ""; }; B402FFED2315FEFA00900020 /* MarkdownEditorViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MarkdownEditorViewController.xib; sourceTree = ""; }; B402FFF12316055000900020 /* BRMarkdownParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRMarkdownParser.swift; sourceTree = ""; }; @@ -384,6 +386,7 @@ B4789FE8231887E3008DBE9F /* GameListTableViewController.xib */, B4789FEB2318880E008DBE9F /* GameListGameTableViewCell.swift */, B4789FEC2318880E008DBE9F /* GameListGameTableViewCell.xib */, + 44F8AA9A29E12F0F0031BCBB /* GameListView.swift */, ); path = "Game List"; sourceTree = ""; @@ -707,6 +710,7 @@ B4CB7FBA23120176009B4DF0 /* Rule+CoreDataClass.swift in Sources */, 4439E65F230B534D00C6A23C /* Decision+CoreDataProperties.swift in Sources */, 44CB58C523286792009E49D9 /* Logging.swift in Sources */, + 44F8AA9B29E12F0F0031BCBB /* GameListView.swift in Sources */, B4B6B3B923174CBD00E72320 /* MetadataEditorViewController.swift in Sources */, B4E9EFBF230B6DD500C9CA76 /* Extensions.swift in Sources */, 444358C4230C7BBE00A2E004 /* PlayViewController.swift in Sources */, @@ -920,7 +924,7 @@ CURRENT_PROJECT_VERSION = 15; DEVELOPMENT_TEAM = 2Y9M69QJKZ; INFOPLIST_FILE = GamebookEngine/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.6; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -942,7 +946,7 @@ CURRENT_PROJECT_VERSION = 15; DEVELOPMENT_TEAM = 2Y9M69QJKZ; INFOPLIST_FILE = GamebookEngine/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.6; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/GamebookEngine/AppDelegate.swift b/GamebookEngine/AppDelegate.swift index 6e6579b..e00976b 100644 --- a/GamebookEngine/AppDelegate.swift +++ b/GamebookEngine/AppDelegate.swift @@ -8,6 +8,7 @@ import CoreData import UIKit +import SwiftUI @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -27,7 +28,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { window = UIWindow(frame: UIScreen.main.bounds) guard let window = window else { return false } - window.rootViewController = GameListTableViewController() +// window.rootViewController = GameListTableViewController() + window.rootViewController = UIHostingController(rootView: GameListView()) window.makeKeyAndVisible() return true } diff --git a/GamebookEngine/Extensions.swift b/GamebookEngine/Extensions.swift index 156f7b0..9193c98 100644 --- a/GamebookEngine/Extensions.swift +++ b/GamebookEngine/Extensions.swift @@ -8,6 +8,24 @@ import Foundation import UIKit +import SwiftUI + +extension View { + /// Sets the text color for a navigation bar title. + /// - Parameter color: Color the title should be + /// + /// Supports both regular and large titles. + @available(iOS 14, *) + func navigationBarTitleTextColor(_ color: Color) -> some View { + let uiColor = UIColor(color) + + // Set appearance for both normal and large sizes. + UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: uiColor ] + UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: uiColor ] + + return self + } +} func angleBetween(pointOne: CGPoint, andPointTwo pointTwo: CGPoint) -> CGFloat { let xdiff = (pointTwo.x - pointOne.x) diff --git a/GamebookEngine/Views/Game List/GameListView.swift b/GamebookEngine/Views/Game List/GameListView.swift new file mode 100644 index 0000000..2485bf4 --- /dev/null +++ b/GamebookEngine/Views/Game List/GameListView.swift @@ -0,0 +1,137 @@ +// +// GameListView.swift +// GamebookEngine +// +// Created by Brad Root on 4/7/23. +// Copyright © 2023 Brad Root. All rights reserved. +// + +import SwiftUI + +struct GameCard: View { + let game: Game + + var body: some View { + HStack { + VStack { + Text(game.name) + .multilineTextAlignment(.leading) + .frame(maxWidth: .infinity, alignment: .leading) + .font(.title) + .fixedSize(horizontal: false, vertical: true) + .padding(EdgeInsets(top: 22, leading: 22, bottom: 4, trailing: 22)) + Text(game.author) + .font(.headline) + .frame(maxWidth: .infinity, alignment: .leading) + .foregroundColor(.secondary) + .padding(EdgeInsets(top: 0, leading: 22, bottom: 8, trailing: 22)) + Text(game.about ?? "") + .font(.subheadline) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(EdgeInsets(top: 0, leading: 22, bottom: 8, trailing: 22)) + Text("Play Gamebook") + .fontWeight(.medium) + .foregroundColor(Color("button")) + .frame(maxWidth: .infinity, alignment: .center) + .padding(EdgeInsets(top: 6, leading: 0, bottom: 8, trailing: 0)) + .background(Color("background")) + .cornerRadius(5) + .padding(EdgeInsets(top: 0, leading: 22, bottom: 22, trailing: 22)) + + + } + .background(Color("containerBackground")) + .foregroundColor(Color("text")) + .cornerRadius(10) + .padding(EdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 0)) + .shadow(color: Color(white: 0, opacity: 0.1), radius: 10) + + + + VStack { + Button { + print("Play") + } label: { + Image("play") + .foregroundColor(Color("button")) + }.frame(width: 50, height: 30, alignment: .center) + + Button { + print("Play") + } label: { + Image("edit") + .foregroundColor(Color("button")) + }.frame(width: 50, height: 30, alignment: .center) + + Button { + print("Play") + } label: { + Image("export") + .foregroundColor(Color("button")) + }.frame(width: 50, height: 30, alignment: .center) + + Button { + print("Play") + } label: { + Image("delete") + .foregroundColor(Color("button")) + }.frame(width: 50, height: 30, alignment: .center) + } + .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 10)) + } + } +} + + +struct GameListView: View { + @State private var games: [Game] = [] + + var body: some View { + NavigationView { + List(games, id: \.uuid) { game in + GameCard(game: game) + .listRowBackground(Color("background")) +// .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets()) + } + .listStyle(.plain) + .foregroundColor(Color("text")) + .background(Color("background")) + .scrollContentBackground(.hidden) + .navigationTitle("Your Gamebooks") + .navigationBarTitleTextColor(.secondary) + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + Button { + print("About tapped!") + } label: { + Image("add") + .foregroundColor(Color("button")) + } + } + ToolbarItem(placement: .navigationBarLeading) { + Button("Help") { + print("Help tapped!") + }.foregroundColor(Color("button")) + } + } + } + .onAppear(perform: fetchGames) + } + + func fetchGames() { + GameDatabase.standard.fetchGames { games in + if let games = games { + DispatchQueue.main.async { + self.games = games + } + } + } + } +} + +struct GameListView_Previews: PreviewProvider { + static var previews: some View { + GameListView() + } +} From 2ccfde5cf8a3f89ff98b1900bffbb3a988223fef Mon Sep 17 00:00:00 2001 From: Brad Root Date: Fri, 7 Apr 2023 23:47:53 -0700 Subject: [PATCH 2/4] switch navigation view to a navigation stack --- GamebookEngine/Views/Game List/GameListView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GamebookEngine/Views/Game List/GameListView.swift b/GamebookEngine/Views/Game List/GameListView.swift index 2485bf4..522a4c3 100644 --- a/GamebookEngine/Views/Game List/GameListView.swift +++ b/GamebookEngine/Views/Game List/GameListView.swift @@ -87,7 +87,7 @@ struct GameListView: View { @State private var games: [Game] = [] var body: some View { - NavigationView { + NavigationStack { List(games, id: \.uuid) { game in GameCard(game: game) .listRowBackground(Color("background")) From 6db426efd768d0b01ea4032fe98ebba8fcf11212 Mon Sep 17 00:00:00 2001 From: Brad Root Date: Fri, 7 Apr 2023 23:48:39 -0700 Subject: [PATCH 3/4] run swiftformat --- GamebookEngine/AppDelegate.swift | 2 +- GamebookEngine/Extensions.swift | 6 +++--- GamebookEngine/Views/Game List/GameListView.swift | 5 ----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/GamebookEngine/AppDelegate.swift b/GamebookEngine/AppDelegate.swift index e00976b..c35f16e 100644 --- a/GamebookEngine/AppDelegate.swift +++ b/GamebookEngine/AppDelegate.swift @@ -7,8 +7,8 @@ // import CoreData -import UIKit import SwiftUI +import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { diff --git a/GamebookEngine/Extensions.swift b/GamebookEngine/Extensions.swift index 9193c98..df8d53f 100644 --- a/GamebookEngine/Extensions.swift +++ b/GamebookEngine/Extensions.swift @@ -7,8 +7,8 @@ // import Foundation -import UIKit import SwiftUI +import UIKit extension View { /// Sets the text color for a navigation bar title. @@ -20,8 +20,8 @@ extension View { let uiColor = UIColor(color) // Set appearance for both normal and large sizes. - UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: uiColor ] - UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: uiColor ] + UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: uiColor] + UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: uiColor] return self } diff --git a/GamebookEngine/Views/Game List/GameListView.swift b/GamebookEngine/Views/Game List/GameListView.swift index 522a4c3..f085c93 100644 --- a/GamebookEngine/Views/Game List/GameListView.swift +++ b/GamebookEngine/Views/Game List/GameListView.swift @@ -37,8 +37,6 @@ struct GameCard: View { .background(Color("background")) .cornerRadius(5) .padding(EdgeInsets(top: 0, leading: 22, bottom: 22, trailing: 22)) - - } .background(Color("containerBackground")) .foregroundColor(Color("text")) @@ -46,8 +44,6 @@ struct GameCard: View { .padding(EdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 0)) .shadow(color: Color(white: 0, opacity: 0.1), radius: 10) - - VStack { Button { print("Play") @@ -82,7 +78,6 @@ struct GameCard: View { } } - struct GameListView: View { @State private var games: [Game] = [] From c19aa7e577f08be23ddd350bd262fb2353d8ded2 Mon Sep 17 00:00:00 2001 From: Brad Root Date: Sat, 8 Apr 2023 00:32:45 -0700 Subject: [PATCH 4/4] fix buttons not working properly --- .../Views/Game List/GameListView.swift | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/GamebookEngine/Views/Game List/GameListView.swift b/GamebookEngine/Views/Game List/GameListView.swift index f085c93..97ea25f 100644 --- a/GamebookEngine/Views/Game List/GameListView.swift +++ b/GamebookEngine/Views/Game List/GameListView.swift @@ -20,15 +20,18 @@ struct GameCard: View { .font(.title) .fixedSize(horizontal: false, vertical: true) .padding(EdgeInsets(top: 22, leading: 22, bottom: 4, trailing: 22)) + Text(game.author) .font(.headline) .frame(maxWidth: .infinity, alignment: .leading) .foregroundColor(.secondary) .padding(EdgeInsets(top: 0, leading: 22, bottom: 8, trailing: 22)) + Text(game.about ?? "") .font(.subheadline) .frame(maxWidth: .infinity, alignment: .leading) .padding(EdgeInsets(top: 0, leading: 22, bottom: 8, trailing: 22)) + Text("Play Gamebook") .fontWeight(.medium) .foregroundColor(Color("button")) @@ -50,28 +53,36 @@ struct GameCard: View { } label: { Image("play") .foregroundColor(Color("button")) - }.frame(width: 50, height: 30, alignment: .center) + } + .frame(width: 50, height: 30, alignment: .center) + .buttonStyle(.borderless) Button { print("Play") } label: { Image("edit") .foregroundColor(Color("button")) - }.frame(width: 50, height: 30, alignment: .center) + } + .frame(width: 50, height: 30, alignment: .center) + .buttonStyle(.borderless) Button { print("Play") } label: { Image("export") .foregroundColor(Color("button")) - }.frame(width: 50, height: 30, alignment: .center) + } + .frame(width: 50, height: 30, alignment: .center) + .buttonStyle(.borderless) Button { print("Play") } label: { Image("delete") .foregroundColor(Color("button")) - }.frame(width: 50, height: 30, alignment: .center) + } + .frame(width: 50, height: 30, alignment: .center) + .buttonStyle(.borderless) } .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 10)) } @@ -86,7 +97,6 @@ struct GameListView: View { List(games, id: \.uuid) { game in GameCard(game: game) .listRowBackground(Color("background")) -// .listRowSeparator(.hidden) .listRowInsets(EdgeInsets()) } .listStyle(.plain)