diff --git a/OnCue.xcodeproj/project.pbxproj b/OnCue.xcodeproj/project.pbxproj index 1218aca..27b0523 100644 --- a/OnCue.xcodeproj/project.pbxproj +++ b/OnCue.xcodeproj/project.pbxproj @@ -21,7 +21,7 @@ 46AD30D32C26559B00486C25 /* MainViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46AD30D22C26559B00486C25 /* MainViewPresenter.swift */; }; 46AD30D52C26559D00486C25 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 46AD30D42C26559D00486C25 /* Assets.xcassets */; }; 46AD30D82C26559D00486C25 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 46AD30D72C26559D00486C25 /* Preview Assets.xcassets */; }; - 46AD30DB2C26559D00486C25 /* OnCuePresenter Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 46AD30CE2C26559B00486C25 /* OnCuePresenter Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 46AD30DB2C26559D00486C25 /* OnCue.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 46AD30CE2C26559B00486C25 /* OnCue.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 46AD30E22C2656CB00486C25 /* OCCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46AD30E12C2656CB00486C25 /* OCCard.swift */; }; 46AD30E32C2656CB00486C25 /* OCCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46AD30E12C2656CB00486C25 /* OCCard.swift */; }; 46AD30E52C2656D100486C25 /* OCProject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46AD30E42C2656D100486C25 /* OCProject.swift */; }; @@ -57,7 +57,7 @@ dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; dstSubfolderSpec = 16; files = ( - 46AD30DB2C26559D00486C25 /* OnCuePresenter Watch App.app in Embed Watch Content */, + 46AD30DB2C26559D00486C25 /* OnCue.app in Embed Watch Content */, ); name = "Embed Watch Content"; runOnlyForDeploymentPostprocessing = 0; @@ -66,6 +66,7 @@ /* Begin PBXFileReference section */ 460D7DF52C2AE788002B623C /* TimerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimerManager.swift; sourceTree = ""; }; + 4614D4022C3DF680000799F5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 464787CA2C269CAF00A9C462 /* TeleprompterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeleprompterView.swift; sourceTree = ""; }; 46AD30B72C26557500486C25 /* OnCue.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OnCue.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46AD30BA2C26557500486C25 /* OnCueApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnCueApp.swift; sourceTree = ""; }; @@ -73,7 +74,7 @@ 46AD30BE2C26557500486C25 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = ""; }; 46AD30C02C26557600486C25 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 46AD30C32C26557600486C25 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; - 46AD30CE2C26559B00486C25 /* OnCuePresenter Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "OnCuePresenter Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 46AD30CE2C26559B00486C25 /* OnCue.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OnCue.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46AD30D02C26559B00486C25 /* OnCuePresenterApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnCuePresenterApp.swift; sourceTree = ""; }; 46AD30D22C26559B00486C25 /* MainViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewPresenter.swift; sourceTree = ""; }; 46AD30D42C26559D00486C25 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -126,7 +127,7 @@ isa = PBXGroup; children = ( 46AD30B72C26557500486C25 /* OnCue.app */, - 46AD30CE2C26559B00486C25 /* OnCuePresenter Watch App.app */, + 46AD30CE2C26559B00486C25 /* OnCue.app */, ); name = Products; sourceTree = ""; @@ -134,6 +135,7 @@ 46AD30B92C26557500486C25 /* OnCue */ = { isa = PBXGroup; children = ( + 4614D4022C3DF680000799F5 /* Info.plist */, 46D3E1472C27FAFC0060722E /* OnCue.entitlements */, 46AD30BA2C26557500486C25 /* OnCueApp.swift */, 46AD30E82C266AB900486C25 /* View */, @@ -247,9 +249,9 @@ productReference = 46AD30B72C26557500486C25 /* OnCue.app */; productType = "com.apple.product-type.application"; }; - 46AD30CD2C26559B00486C25 /* OnCuePresenter Watch App */ = { + 46AD30CD2C26559B00486C25 /* OnCuePresenter */ = { isa = PBXNativeTarget; - buildConfigurationList = 46AD30DC2C26559D00486C25 /* Build configuration list for PBXNativeTarget "OnCuePresenter Watch App" */; + buildConfigurationList = 46AD30DC2C26559D00486C25 /* Build configuration list for PBXNativeTarget "OnCuePresenter" */; buildPhases = ( 46AD30CA2C26559B00486C25 /* Sources */, 46AD30CB2C26559B00486C25 /* Frameworks */, @@ -259,9 +261,9 @@ ); dependencies = ( ); - name = "OnCuePresenter Watch App"; + name = OnCuePresenter; productName = "OnCuePresenter Watch App"; - productReference = 46AD30CE2C26559B00486C25 /* OnCuePresenter Watch App.app */; + productReference = 46AD30CE2C26559B00486C25 /* OnCue.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -296,7 +298,7 @@ projectRoot = ""; targets = ( 46AD30B62C26557500486C25 /* OnCue */, - 46AD30CD2C26559B00486C25 /* OnCuePresenter Watch App */, + 46AD30CD2C26559B00486C25 /* OnCuePresenter */, ); }; /* End PBXProject section */ @@ -368,7 +370,7 @@ /* Begin PBXTargetDependency section */ 46AD30DA2C26559D00486C25 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 46AD30CD2C26559B00486C25 /* OnCuePresenter Watch App */; + target = 46AD30CD2C26559B00486C25 /* OnCuePresenter */; targetProxy = 46AD30D92C26559D00486C25 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -506,6 +508,7 @@ DEVELOPMENT_TEAM = 9MP5435PRF; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OnCue/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = OnCue; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -542,6 +545,7 @@ DEVELOPMENT_TEAM = 9MP5435PRF; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OnCue/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = OnCue; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -576,7 +580,6 @@ DEVELOPMENT_TEAM = 9MP5435PRF; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = OnCuePresenter; INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; INFOPLIST_KEY_WKCompanionAppBundleIdentifier = xyz.breadone.oncue; LD_RUNPATH_SEARCH_PATHS = ( @@ -585,7 +588,7 @@ ); MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = xyz.breadone.oncue.watchkitapp; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = OnCue; SDKROOT = watchos; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -606,7 +609,6 @@ DEVELOPMENT_TEAM = 9MP5435PRF; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = OnCuePresenter; INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; INFOPLIST_KEY_WKCompanionAppBundleIdentifier = xyz.breadone.oncue; LD_RUNPATH_SEARCH_PATHS = ( @@ -615,7 +617,7 @@ ); MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = xyz.breadone.oncue.watchkitapp; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = OnCue; SDKROOT = watchos; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -646,7 +648,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 46AD30DC2C26559D00486C25 /* Build configuration list for PBXNativeTarget "OnCuePresenter Watch App" */ = { + 46AD30DC2C26559D00486C25 /* Build configuration list for PBXNativeTarget "OnCuePresenter" */ = { isa = XCConfigurationList; buildConfigurations = ( 46AD30DD2C26559D00486C25 /* Debug */, diff --git a/OnCue.xcodeproj/xcshareddata/xcschemes/OnCuePresenter Watch App.xcscheme b/OnCue.xcodeproj/xcshareddata/xcschemes/OnCuePresenter Watch App.xcscheme index 5b3a2ac..8ada2c1 100644 --- a/OnCue.xcodeproj/xcshareddata/xcschemes/OnCuePresenter Watch App.xcscheme +++ b/OnCue.xcodeproj/xcshareddata/xcschemes/OnCuePresenter Watch App.xcscheme @@ -16,8 +16,8 @@ @@ -59,8 +59,8 @@ @@ -76,8 +76,8 @@ diff --git a/OnCue/Info.plist b/OnCue/Info.plist new file mode 100644 index 0000000..ca9a074 --- /dev/null +++ b/OnCue/Info.plist @@ -0,0 +1,10 @@ + + + + + UIBackgroundModes + + remote-notification + + + diff --git a/OnCue/Model/OCCard.swift b/OnCue/Model/OCCard.swift index dc058ae..cfb292d 100644 --- a/OnCue/Model/OCCard.swift +++ b/OnCue/Model/OCCard.swift @@ -11,8 +11,9 @@ import SwiftData @Model final class OCCard: Identifiable { let id = UUID() - var content: String - var index: Int + var content: String = "" + var index: Int = 0 + var parentProject: OCProject? = nil init(content: String, index: Int) { self.content = content diff --git a/OnCue/Model/OCProject.swift b/OnCue/Model/OCProject.swift index f529666..bdcff95 100644 --- a/OnCue/Model/OCProject.swift +++ b/OnCue/Model/OCProject.swift @@ -7,14 +7,15 @@ import Foundation import SwiftData +import CloudKit @Model final class OCProject { - var name: String - var cards: [OCCard] - let creationDate: Date - var lastEditedDate: Date - var color: String + var name: String = "No Name" + var cards: [OCCard]? = [] + let creationDate: Date = Date() + var lastEditedDate: Date = Date() + var color: String = "ff7e30" var script: String { var txt = "" @@ -24,7 +25,7 @@ final class OCProject { var sortedCards: [OCCard] { get { - return self.cards.sorted(by: { $0.index < $1.index }) + return self.cards?.sorted(by: { $0.index < $1.index }) ?? [] } } @@ -41,10 +42,10 @@ final class OCProject { } func addCards(cards: OCCard...) { - cards.forEach({ self.cards.append($0) }) + cards.forEach({ self.cards?.append($0) }) } func removeCard(_ card: OCCard) { - self.cards.removeAll { $0.id == card.id } + self.cards?.removeAll { $0.id == card.id } } } diff --git a/OnCue/OnCue.entitlements b/OnCue/OnCue.entitlements index 0c67376..9f5c100 100644 --- a/OnCue/OnCue.entitlements +++ b/OnCue/OnCue.entitlements @@ -1,5 +1,16 @@ - + + aps-environment + development + com.apple.developer.icloud-container-identifiers + + iCloud.xyz.breadone.oncue + + com.apple.developer.icloud-services + + CloudKit + + diff --git a/OnCue/OnCueApp.swift b/OnCue/OnCueApp.swift index cca7441..cb2a8f8 100644 --- a/OnCue/OnCueApp.swift +++ b/OnCue/OnCueApp.swift @@ -7,6 +7,7 @@ import SwiftUI import SwiftData +import CoreData @main struct OnCueApp: App { @@ -19,6 +20,34 @@ struct OnCueApp: App { let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { +// #if DEBUG +// // Use an autorelease pool to make sure Swift deallocates the persistent +// // container before setting up the SwiftData stack. +// try autoreleasepool { +// let desc = NSPersistentStoreDescription(url: modelConfiguration.url) +// let opts = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.xyz.breadone.oncue") +// desc.cloudKitContainerOptions = opts +// // Load the store synchronously so it completes before initializing the +// // CloudKit schema. +// desc.shouldAddStoreAsynchronously = false +// if let mom = NSManagedObjectModel.makeManagedObjectModel(for: [OCProject.self, OCCard.self]) { +// let container = NSPersistentCloudKitContainer(name: "OnCue", managedObjectModel: mom) +// container.persistentStoreDescriptions = [desc] +// container.loadPersistentStores {_, err in +// if let err { +// fatalError(err.localizedDescription) +// } +// } +// // Initialize the CloudKit schema after the store finishes loading. +// try container.initializeCloudKitSchema() +// // Remove and unload the store from the persistent container. +// if let store = container.persistentStoreCoordinator.persistentStores.first { +// try container.persistentStoreCoordinator.remove(store) +// } +// } +// } +// #endif + return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") diff --git a/OnCue/View/CardsView.swift b/OnCue/View/CardsView.swift index 7c5b69d..bd40419 100644 --- a/OnCue/View/CardsView.swift +++ b/OnCue/View/CardsView.swift @@ -36,7 +36,7 @@ struct CardsView: View { } } } header: { - Text("\(project.cards.count) \(project.cards.count == 1 ? "Card" : "Cards")") + Text("\(project.cards?.count ?? 0) \(project.cards?.count ?? 0 == 1 ? "Card" : "Cards")") } } @@ -85,7 +85,7 @@ struct CardsView: View { } let card = OCCard(content: txt, index: (project.sortedCards.last?.index ?? -1) + 1) // adds one to the index, unless there arent any cards in which case default to 0 - project.cards.append(card) + project.cards?.append(card) try! ctx.save() newCardText = "" } diff --git a/OnCue/View/MainView.swift b/OnCue/View/MainView.swift index 0b219b0..872b505 100644 --- a/OnCue/View/MainView.swift +++ b/OnCue/View/MainView.swift @@ -99,7 +99,7 @@ private struct ProjectListView: View { .font(.title2) .foregroundStyle(Color(hex: project.color) ?? .white) } - Text("\(project.cards.count) \(project.cards.count == 1 ? "Card" : "Cards")") + Text("\(project.cards?.count ?? 0) \(project.cards?.count ?? 0 == 1 ? "Card" : "Cards")") } } .padding(.vertical, 3) diff --git a/OnCuePresenter Watch App/View/CueCardViewPresenter.swift b/OnCuePresenter Watch App/View/CueCardViewPresenter.swift index 9ad6f50..250bee2 100644 --- a/OnCuePresenter Watch App/View/CueCardViewPresenter.swift +++ b/OnCuePresenter Watch App/View/CueCardViewPresenter.swift @@ -12,7 +12,7 @@ struct CueCardViewPresenter: View { var body: some View { TabView() { - ForEach(project.cards) { card in + ForEach(project.cards ?? []) { card in CueCardView(card: card) } } diff --git a/OnCuePresenter Watch App/View/MainViewPresenter.swift b/OnCuePresenter Watch App/View/MainViewPresenter.swift index e21f2df..8d8ff31 100644 --- a/OnCuePresenter Watch App/View/MainViewPresenter.swift +++ b/OnCuePresenter Watch App/View/MainViewPresenter.swift @@ -27,7 +27,7 @@ struct MainViewPresenter: View { .bold() .font(.title2) .foregroundStyle(Color(hex: project.color) ?? .white) - Text("\(project.cards.count) \(project.cards.count == 1 ? "Card" : "Cards")") + Text("\(project.cards?.count ?? 0) \(project.cards?.count ?? 0 == 1 ? "Card" : "Cards")") } } .padding(.vertical, 3)