diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..841a85c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +Cartfile.resolved +Carthage/ +Zockerhoehle.xcodeproj/project.xcworkspace/xcuserdata/ +Zockerhoehle.xcodeproj/xcuserdata/julian.xcuserdatad/xcdebugger/ +Zockerhoehle.xcodeproj/xcuserdata/julian.xcuserdatad/xcschemes/Zockerhoehle.xcscheme diff --git a/Cartfile b/Cartfile new file mode 100644 index 0000000..feb86a6 --- /dev/null +++ b/Cartfile @@ -0,0 +1 @@ +github "dstranz/Disk" "feature/SPM_xcode11" diff --git a/Zockerhoehle copy-Info.plist b/Zockerhoehle copy-Info.plist new file mode 100644 index 0000000..e49a713 --- /dev/null +++ b/Zockerhoehle copy-Info.plist @@ -0,0 +1,52 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Zockerhöhle + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Zockerhoehle.xcodeproj/project.pbxproj b/Zockerhoehle.xcodeproj/project.pbxproj index 3eea45e..2b5bddd 100644 --- a/Zockerhoehle.xcodeproj/project.pbxproj +++ b/Zockerhoehle.xcodeproj/project.pbxproj @@ -7,21 +7,89 @@ objects = { /* Begin PBXBuildFile section */ + B926F12B2149B173004D36B7 /* ConsoleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F12A2149B173004D36B7 /* ConsoleCell.swift */; }; + B926F12D2149B264004D36B7 /* FlockeEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F12C2149B264004D36B7 /* FlockeEntry.swift */; }; + B926F131214AD9E4004D36B7 /* GameCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F130214AD9E4004D36B7 /* GameCollection.swift */; }; + B926F139214AE884004D36B7 /* FlockeWS.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F138214AE884004D36B7 /* FlockeWS.swift */; }; + B926F13C214C44FE004D36B7 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F13B214C44FE004D36B7 /* Attachment.swift */; }; + B926F13F214E4678004D36B7 /* GameCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F13E214E4678004D36B7 /* GameCell.swift */; }; + B926F14721502D53004D36B7 /* CodableExtensionAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F14621502D53004D36B7 /* CodableExtensionAny.swift */; }; + B926F14A21502DE1004D36B7 /* ConsoleEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F14921502DE1004D36B7 /* ConsoleEntry.swift */; }; B93C1B9D21496BFD0014FD6E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93C1B9C21496BFD0014FD6E /* AppDelegate.swift */; }; - B93C1B9F21496BFD0014FD6E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93C1B9E21496BFD0014FD6E /* ViewController.swift */; }; B93C1BA221496BFD0014FD6E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B93C1BA021496BFD0014FD6E /* Main.storyboard */; }; B93C1BA421496BFE0014FD6E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B93C1BA321496BFE0014FD6E /* Assets.xcassets */; }; - B93C1BA721496BFE0014FD6E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B93C1BA521496BFE0014FD6E /* LaunchScreen.storyboard */; }; + B93C1BB02149750E0014FD6E /* AllConsolesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93C1BAF2149750E0014FD6E /* AllConsolesViewController.swift */; }; + B93D60CC22D88F2B00DD390F /* AccessoryDetailController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93D60CB22D88F2B00DD390F /* AccessoryDetailController.swift */; }; + B93D60CE22D88F5700DD390F /* AccessoryDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */; }; + B9418449215422ED0050D099 /* AddEntryPopUpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9418448215422ED0050D099 /* AddEntryPopUpViewController.swift */; }; + B941844B2156891E0050D099 /* UIButtonX.swift in Sources */ = {isa = PBXBuildFile; fileRef = B941844A2156891E0050D099 /* UIButtonX.swift */; }; + B94CB4FF22D1352F0029BFAD /* Accessory+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4F322D1352F0029BFAD /* Accessory+CoreDataClass.swift */; }; + B94CB50022D1352F0029BFAD /* Accessory+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4F422D1352F0029BFAD /* Accessory+CoreDataProperties.swift */; }; + B94CB50122D1352F0029BFAD /* Cover+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4F522D1352F0029BFAD /* Cover+CoreDataClass.swift */; }; + B94CB50222D1352F0029BFAD /* Cover+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4F622D1352F0029BFAD /* Cover+CoreDataProperties.swift */; }; + B94CB50322D1352F0029BFAD /* Game+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4F722D1352F0029BFAD /* Game+CoreDataClass.swift */; }; + B94CB50422D1352F0029BFAD /* Game+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4F822D1352F0029BFAD /* Game+CoreDataProperties.swift */; }; + B94CB50522D1352F0029BFAD /* Console+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4F922D1352F0029BFAD /* Console+CoreDataClass.swift */; }; + B94CB50622D1352F0029BFAD /* Console+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4FA22D1352F0029BFAD /* Console+CoreDataProperties.swift */; }; + B94CB50722D1352F0029BFAD /* GameSeries+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4FB22D1352F0029BFAD /* GameSeries+CoreDataClass.swift */; }; + B94CB50822D1352F0029BFAD /* GameSeries+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4FC22D1352F0029BFAD /* GameSeries+CoreDataProperties.swift */; }; + B94CB50922D1352F0029BFAD /* Logo+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4FD22D1352F0029BFAD /* Logo+CoreDataClass.swift */; }; + B94CB50A22D1352F0029BFAD /* Logo+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4FE22D1352F0029BFAD /* Logo+CoreDataProperties.swift */; }; + B94CB53722D3B3CC0029BFAD /* GameDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB53622D3B3CC0029BFAD /* GameDetailView.swift */; }; + B94CB53922D3B6490029BFAD /* GameDetailController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB53822D3B6490029BFAD /* GameDetailController.swift */; }; + B98A734D22BAD27D00FB3410 /* Zockerhoehle.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B98A731722BA9E4600FB3410 /* Zockerhoehle.xcdatamodeld */; }; + B98A735E22BFAA4B00FB3410 /* ConsoleLibraryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F12E2149B6F5004D36B7 /* ConsoleLibraryViewController.swift */; }; + B98A736022C1738800FB3410 /* CDManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B98A735F22C1738800FB3410 /* CDManager.swift */; }; + B9BCF4CA2168ACB600ECBAAC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B9BCF4C92168ACB600ECBAAC /* LaunchScreen.storyboard */; }; + B9BCF523217900D700ECBAAC /* WaitingPopOver.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B9BCF521217900D700ECBAAC /* WaitingPopOver.storyboard */; }; + B9D6A39A22D885DD00A280DC /* AccessoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D6A39922D885DD00A280DC /* AccessoryCell.swift */; }; + B9E256FE2156D026009FD133 /* UIViewX.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9E256FD2156D026009FD133 /* UIViewX.swift */; }; + B9F002E52187AA3200E12B0A /* FlockeConnector.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F002E42187AA3200E12B0A /* FlockeConnector.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + B926F12A2149B173004D36B7 /* ConsoleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleCell.swift; sourceTree = ""; }; + B926F12C2149B264004D36B7 /* FlockeEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlockeEntry.swift; sourceTree = ""; }; + B926F12E2149B6F5004D36B7 /* ConsoleLibraryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleLibraryViewController.swift; sourceTree = ""; }; + B926F130214AD9E4004D36B7 /* GameCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCollection.swift; sourceTree = ""; }; + B926F138214AE884004D36B7 /* FlockeWS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlockeWS.swift; sourceTree = ""; }; + B926F13B214C44FE004D36B7 /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = ""; }; + B926F13E214E4678004D36B7 /* GameCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCell.swift; sourceTree = ""; }; + B926F14621502D53004D36B7 /* CodableExtensionAny.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableExtensionAny.swift; sourceTree = ""; }; + B926F14921502DE1004D36B7 /* ConsoleEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleEntry.swift; sourceTree = ""; }; B93C1B9921496BFD0014FD6E /* Zockerhoehle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Zockerhoehle.app; sourceTree = BUILT_PRODUCTS_DIR; }; B93C1B9C21496BFD0014FD6E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - B93C1B9E21496BFD0014FD6E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; B93C1BA121496BFD0014FD6E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; B93C1BA321496BFE0014FD6E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - B93C1BA621496BFE0014FD6E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; B93C1BA821496BFE0014FD6E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B93C1BAE21496CC50014FD6E /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Main.strings; sourceTree = ""; }; + B93C1BAF2149750E0014FD6E /* AllConsolesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllConsolesViewController.swift; sourceTree = ""; }; + B93D60CB22D88F2B00DD390F /* AccessoryDetailController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessoryDetailController.swift; sourceTree = ""; }; + B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessoryDetailView.swift; sourceTree = ""; }; + B9418448215422ED0050D099 /* AddEntryPopUpViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddEntryPopUpViewController.swift; sourceTree = ""; }; + B941844A2156891E0050D099 /* UIButtonX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIButtonX.swift; sourceTree = ""; }; + B94CB4F322D1352F0029BFAD /* Accessory+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Accessory+CoreDataClass.swift"; sourceTree = ""; }; + B94CB4F422D1352F0029BFAD /* Accessory+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Accessory+CoreDataProperties.swift"; sourceTree = ""; }; + B94CB4F522D1352F0029BFAD /* Cover+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Cover+CoreDataClass.swift"; sourceTree = ""; }; + B94CB4F622D1352F0029BFAD /* Cover+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Cover+CoreDataProperties.swift"; sourceTree = ""; }; + B94CB4F722D1352F0029BFAD /* Game+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Game+CoreDataClass.swift"; sourceTree = ""; }; + B94CB4F822D1352F0029BFAD /* Game+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Game+CoreDataProperties.swift"; sourceTree = ""; }; + B94CB4F922D1352F0029BFAD /* Console+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Console+CoreDataClass.swift"; sourceTree = ""; }; + B94CB4FA22D1352F0029BFAD /* Console+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Console+CoreDataProperties.swift"; sourceTree = ""; }; + B94CB4FB22D1352F0029BFAD /* GameSeries+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GameSeries+CoreDataClass.swift"; sourceTree = ""; }; + B94CB4FC22D1352F0029BFAD /* GameSeries+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GameSeries+CoreDataProperties.swift"; sourceTree = ""; }; + B94CB4FD22D1352F0029BFAD /* Logo+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logo+CoreDataClass.swift"; sourceTree = ""; }; + B94CB4FE22D1352F0029BFAD /* Logo+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logo+CoreDataProperties.swift"; sourceTree = ""; }; + B94CB53522D3708F0029BFAD /* Zockerhoehle copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Zockerhoehle copy-Info.plist"; path = "/Users/julian/Entwicklung/Zockerhoehle/Zockerhoehle copy-Info.plist"; sourceTree = ""; }; + B94CB53622D3B3CC0029BFAD /* GameDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameDetailView.swift; sourceTree = ""; }; + B94CB53822D3B6490029BFAD /* GameDetailController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameDetailController.swift; sourceTree = ""; }; + B98A731822BA9E4600FB3410 /* Zockerhoehle.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Zockerhoehle.xcdatamodel; sourceTree = ""; }; + B98A735F22C1738800FB3410 /* CDManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CDManager.swift; sourceTree = ""; }; + B9BCF4C92168ACB600ECBAAC /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + B9BCF522217900D700ECBAAC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Zockerhoehle/Base.lproj/WaitingPopOver.storyboard; sourceTree = ""; }; + B9D6A39922D885DD00A280DC /* AccessoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessoryCell.swift; sourceTree = ""; }; + B9E256FD2156D026009FD133 /* UIViewX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewX.swift; sourceTree = ""; }; + B9F002E42187AA3200E12B0A /* FlockeConnector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlockeConnector.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -35,11 +103,74 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + B90B64A12235909900E54BA3 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + B926F134214AE2C0004D36B7 /* Model */ = { + isa = PBXGroup; + children = ( + B926F130214AD9E4004D36B7 /* GameCollection.swift */, + B926F13B214C44FE004D36B7 /* Attachment.swift */, + B926F12C2149B264004D36B7 /* FlockeEntry.swift */, + B926F14921502DE1004D36B7 /* ConsoleEntry.swift */, + ); + path = Model; + sourceTree = ""; + }; + B926F135214AE2D4004D36B7 /* ViewController */ = { + isa = PBXGroup; + children = ( + B926F12E2149B6F5004D36B7 /* ConsoleLibraryViewController.swift */, + B93C1BAF2149750E0014FD6E /* AllConsolesViewController.swift */, + B9418448215422ED0050D099 /* AddEntryPopUpViewController.swift */, + B94CB53822D3B6490029BFAD /* GameDetailController.swift */, + B93D60CB22D88F2B00DD390F /* AccessoryDetailController.swift */, + ); + path = ViewController; + sourceTree = ""; + }; + B926F136214AE2E3004D36B7 /* Views */ = { + isa = PBXGroup; + children = ( + B926F12A2149B173004D36B7 /* ConsoleCell.swift */, + B926F13E214E4678004D36B7 /* GameCell.swift */, + B94CB53622D3B3CC0029BFAD /* GameDetailView.swift */, + B9D6A39922D885DD00A280DC /* AccessoryCell.swift */, + B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */, + ); + path = Views; + sourceTree = ""; + }; + B926F13A214AF21B004D36B7 /* Utils */ = { + isa = PBXGroup; + children = ( + B926F138214AE884004D36B7 /* FlockeWS.swift */, + B9F002E42187AA3200E12B0A /* FlockeConnector.swift */, + ); + path = Utils; + sourceTree = ""; + }; + B926F14821502D7F004D36B7 /* Lib */ = { + isa = PBXGroup; + children = ( + B926F14621502D53004D36B7 /* CodableExtensionAny.swift */, + B941844A2156891E0050D099 /* UIButtonX.swift */, + B9E256FD2156D026009FD133 /* UIViewX.swift */, + ); + path = Lib; + sourceTree = ""; + }; B93C1B9021496BFD0014FD6E = { isa = PBXGroup; children = ( B93C1B9B21496BFD0014FD6E /* Zockerhoehle */, B93C1B9A21496BFD0014FD6E /* Products */, + B90B64A12235909900E54BA3 /* Frameworks */, + B94CB53522D3708F0029BFAD /* Zockerhoehle copy-Info.plist */, ); sourceTree = ""; }; @@ -54,16 +185,43 @@ B93C1B9B21496BFD0014FD6E /* Zockerhoehle */ = { isa = PBXGroup; children = ( + B98A734622BACA9C00FB3410 /* CDModel */, + B926F14821502D7F004D36B7 /* Lib */, + B926F13A214AF21B004D36B7 /* Utils */, + B926F136214AE2E3004D36B7 /* Views */, + B926F135214AE2D4004D36B7 /* ViewController */, + B926F134214AE2C0004D36B7 /* Model */, B93C1B9C21496BFD0014FD6E /* AppDelegate.swift */, - B93C1B9E21496BFD0014FD6E /* ViewController.swift */, + B9BCF521217900D700ECBAAC /* WaitingPopOver.storyboard */, B93C1BA021496BFD0014FD6E /* Main.storyboard */, + B9BCF4C92168ACB600ECBAAC /* LaunchScreen.storyboard */, + B98A735F22C1738800FB3410 /* CDManager.swift */, B93C1BA321496BFE0014FD6E /* Assets.xcassets */, - B93C1BA521496BFE0014FD6E /* LaunchScreen.storyboard */, B93C1BA821496BFE0014FD6E /* Info.plist */, + B98A731722BA9E4600FB3410 /* Zockerhoehle.xcdatamodeld */, ); path = Zockerhoehle; sourceTree = ""; }; + B98A734622BACA9C00FB3410 /* CDModel */ = { + isa = PBXGroup; + children = ( + B94CB4F322D1352F0029BFAD /* Accessory+CoreDataClass.swift */, + B94CB4F422D1352F0029BFAD /* Accessory+CoreDataProperties.swift */, + B94CB4F522D1352F0029BFAD /* Cover+CoreDataClass.swift */, + B94CB4F622D1352F0029BFAD /* Cover+CoreDataProperties.swift */, + B94CB4F722D1352F0029BFAD /* Game+CoreDataClass.swift */, + B94CB4F822D1352F0029BFAD /* Game+CoreDataProperties.swift */, + B94CB4F922D1352F0029BFAD /* Console+CoreDataClass.swift */, + B94CB4FA22D1352F0029BFAD /* Console+CoreDataProperties.swift */, + B94CB4FB22D1352F0029BFAD /* GameSeries+CoreDataClass.swift */, + B94CB4FC22D1352F0029BFAD /* GameSeries+CoreDataProperties.swift */, + B94CB4FD22D1352F0029BFAD /* Logo+CoreDataClass.swift */, + B94CB4FE22D1352F0029BFAD /* Logo+CoreDataProperties.swift */, + ); + path = CDModel; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -74,6 +232,7 @@ B93C1B9521496BFD0014FD6E /* Sources */, B93C1B9621496BFD0014FD6E /* Frameworks */, B93C1B9721496BFD0014FD6E /* Resources */, + B90B64A4223590DA00E54BA3 /* ShellScript */, ); buildRules = ( ); @@ -96,6 +255,7 @@ TargetAttributes = { B93C1B9821496BFD0014FD6E = { CreatedOnToolsVersion = 9.4.1; + LastSwiftMigration = 1020; }; }; }; @@ -106,6 +266,7 @@ knownRegions = ( en, Base, + de, ); mainGroup = B93C1B9021496BFD0014FD6E; productRefGroup = B93C1B9A21496BFD0014FD6E /* Products */; @@ -122,21 +283,75 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - B93C1BA721496BFE0014FD6E /* LaunchScreen.storyboard in Resources */, + B9BCF4CA2168ACB600ECBAAC /* LaunchScreen.storyboard in Resources */, B93C1BA421496BFE0014FD6E /* Assets.xcassets in Resources */, + B9BCF523217900D700ECBAAC /* WaitingPopOver.storyboard in Resources */, B93C1BA221496BFD0014FD6E /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + B90B64A4223590DA00E54BA3 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/Carthage/Build/iOS/Disk.framework", + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/usr/local/bin/carthage copy-frameworks\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ B93C1B9521496BFD0014FD6E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B93C1B9F21496BFD0014FD6E /* ViewController.swift in Sources */, + B94CB53922D3B6490029BFAD /* GameDetailController.swift in Sources */, + B926F139214AE884004D36B7 /* FlockeWS.swift in Sources */, + B926F13C214C44FE004D36B7 /* Attachment.swift in Sources */, B93C1B9D21496BFD0014FD6E /* AppDelegate.swift in Sources */, + B94CB53722D3B3CC0029BFAD /* GameDetailView.swift in Sources */, + B94CB50322D1352F0029BFAD /* Game+CoreDataClass.swift in Sources */, + B94CB50822D1352F0029BFAD /* GameSeries+CoreDataProperties.swift in Sources */, + B93C1BB02149750E0014FD6E /* AllConsolesViewController.swift in Sources */, + B926F13F214E4678004D36B7 /* GameCell.swift in Sources */, + B9F002E52187AA3200E12B0A /* FlockeConnector.swift in Sources */, + B94CB50A22D1352F0029BFAD /* Logo+CoreDataProperties.swift in Sources */, + B94CB4FF22D1352F0029BFAD /* Accessory+CoreDataClass.swift in Sources */, + B98A734D22BAD27D00FB3410 /* Zockerhoehle.xcdatamodeld in Sources */, + B9E256FE2156D026009FD133 /* UIViewX.swift in Sources */, + B926F12B2149B173004D36B7 /* ConsoleCell.swift in Sources */, + B926F12D2149B264004D36B7 /* FlockeEntry.swift in Sources */, + B98A735E22BFAA4B00FB3410 /* ConsoleLibraryViewController.swift in Sources */, + B94CB50522D1352F0029BFAD /* Console+CoreDataClass.swift in Sources */, + B941844B2156891E0050D099 /* UIButtonX.swift in Sources */, + B94CB50922D1352F0029BFAD /* Logo+CoreDataClass.swift in Sources */, + B94CB50622D1352F0029BFAD /* Console+CoreDataProperties.swift in Sources */, + B926F131214AD9E4004D36B7 /* GameCollection.swift in Sources */, + B93D60CE22D88F5700DD390F /* AccessoryDetailView.swift in Sources */, + B926F14A21502DE1004D36B7 /* ConsoleEntry.swift in Sources */, + B93D60CC22D88F2B00DD390F /* AccessoryDetailController.swift in Sources */, + B94CB50722D1352F0029BFAD /* GameSeries+CoreDataClass.swift in Sources */, + B9418449215422ED0050D099 /* AddEntryPopUpViewController.swift in Sources */, + B94CB50022D1352F0029BFAD /* Accessory+CoreDataProperties.swift in Sources */, + B9D6A39A22D885DD00A280DC /* AccessoryCell.swift in Sources */, + B926F14721502D53004D36B7 /* CodableExtensionAny.swift in Sources */, + B94CB50422D1352F0029BFAD /* Game+CoreDataProperties.swift in Sources */, + B98A736022C1738800FB3410 /* CDManager.swift in Sources */, + B94CB50222D1352F0029BFAD /* Cover+CoreDataProperties.swift in Sources */, + B94CB50122D1352F0029BFAD /* Cover+CoreDataClass.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -147,16 +362,17 @@ isa = PBXVariantGroup; children = ( B93C1BA121496BFD0014FD6E /* Base */, + B93C1BAE21496CC50014FD6E /* de */, ); name = Main.storyboard; sourceTree = ""; }; - B93C1BA521496BFE0014FD6E /* LaunchScreen.storyboard */ = { + B9BCF521217900D700ECBAAC /* WaitingPopOver.storyboard */ = { isa = PBXVariantGroup; children = ( - B93C1BA621496BFE0014FD6E /* Base */, + B9BCF522217900D700ECBAAC /* Base */, ); - name = LaunchScreen.storyboard; + name = WaitingPopOver.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ @@ -166,6 +382,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -213,7 +430,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -226,6 +443,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -267,7 +485,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; @@ -282,6 +500,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = M9N7K3KZX9; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); INFOPLIST_FILE = Zockerhoehle/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -289,7 +511,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "de.mm-neuemedien.Zockerhoehle"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -300,6 +522,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = M9N7K3KZX9; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); INFOPLIST_FILE = Zockerhoehle/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -307,7 +533,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "de.mm-neuemedien.Zockerhoehle"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; @@ -334,6 +560,19 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + B98A731722BA9E4600FB3410 /* Zockerhoehle.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + B98A731822BA9E4600FB3410 /* Zockerhoehle.xcdatamodel */, + ); + currentVersion = B98A731822BA9E4600FB3410 /* Zockerhoehle.xcdatamodel */; + path = Zockerhoehle.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ }; rootObject = B93C1B9121496BFD0014FD6E /* Project object */; } diff --git a/Zockerhoehle.xcodeproj/xcuserdata/julian.xcuserdatad/xcschemes/xcschememanagement.plist b/Zockerhoehle.xcodeproj/xcuserdata/julian.xcuserdatad/xcschemes/xcschememanagement.plist index 764b9de..381e402 100644 --- a/Zockerhoehle.xcodeproj/xcuserdata/julian.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Zockerhoehle.xcodeproj/xcuserdata/julian.xcuserdatad/xcschemes/xcschememanagement.plist @@ -4,11 +4,24 @@ SchemeUserState + Zockerhoehle copy.xcscheme_^#shared#^_ + + orderHint + 1 + Zockerhoehle.xcscheme orderHint 0 + SuppressBuildableAutocreation + + B93C1B9821496BFD0014FD6E + + primary + + + diff --git a/Zockerhoehle/AppDelegate.swift b/Zockerhoehle/AppDelegate.swift index 443320d..a429f28 100644 --- a/Zockerhoehle/AppDelegate.swift +++ b/Zockerhoehle/AppDelegate.swift @@ -7,15 +7,23 @@ // import UIKit +import CoreData @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. + #if targetEnvironment(simulator) + if let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.path { + print("Documents Directory: \(documentsPath)") + } + #endif + + print("disFinishLaunchung") + return true } @@ -40,7 +48,5 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } - - } diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Contents.json b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Contents.json index d8db8d6..6cbb23b 100644 --- a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,93 +1,111 @@ { "images" : [ { - "idiom" : "iphone", "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-40.png", "scale" : "2x" }, { - "idiom" : "iphone", "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-60.png", "scale" : "3x" }, { - "idiom" : "iphone", "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-58.png", "scale" : "2x" }, { - "idiom" : "iphone", "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-87.png", "scale" : "3x" }, { - "idiom" : "iphone", "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-80.png", "scale" : "2x" }, { - "idiom" : "iphone", "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-121.png", "scale" : "3x" }, { - "idiom" : "iphone", "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-120.png", "scale" : "2x" }, { - "idiom" : "iphone", "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-180.png", "scale" : "3x" }, { - "idiom" : "ipad", "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-20.png", "scale" : "1x" }, { - "idiom" : "ipad", "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-41.png", "scale" : "2x" }, { - "idiom" : "ipad", "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-29.png", "scale" : "1x" }, { - "idiom" : "ipad", "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-59.png", "scale" : "2x" }, { - "idiom" : "ipad", "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-42.png", "scale" : "1x" }, { - "idiom" : "ipad", "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-81.png", "scale" : "2x" }, { - "idiom" : "ipad", "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76.png", "scale" : "1x" }, { - "idiom" : "ipad", "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-152.png", "scale" : "2x" }, { - "idiom" : "ipad", "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-167.png", "scale" : "2x" }, { - "idiom" : "ios-marketing", "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-1024.png", "scale" : "1x" } ], diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-1024.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-1024.png new file mode 100644 index 0000000..02827a7 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-1024.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-120.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-120.png new file mode 100644 index 0000000..9057a9d Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-120.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-121.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-121.png new file mode 100644 index 0000000..9057a9d Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-121.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-152.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-152.png new file mode 100644 index 0000000..e5acd22 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-152.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-167.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-167.png new file mode 100644 index 0000000..6467f47 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-167.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-180.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-180.png new file mode 100644 index 0000000..0c20764 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-180.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-20.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-20.png new file mode 100644 index 0000000..f1c3d0f Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-20.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-29.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-29.png new file mode 100644 index 0000000..c23207e Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-29.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-40.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-40.png new file mode 100644 index 0000000..664d4b6 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-40.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-41.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-41.png new file mode 100644 index 0000000..664d4b6 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-41.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-42.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-42.png new file mode 100644 index 0000000..664d4b6 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-42.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-58.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-58.png new file mode 100644 index 0000000..36a836b Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-58.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-59.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-59.png new file mode 100644 index 0000000..36a836b Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-59.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-60.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-60.png new file mode 100644 index 0000000..e3dd297 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-60.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-76.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100644 index 0000000..493400e Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-80.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-80.png new file mode 100644 index 0000000..c352eb7 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-80.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-81.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-81.png new file mode 100644 index 0000000..c352eb7 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-81.png differ diff --git a/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-87.png b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-87.png new file mode 100644 index 0000000..b401f0d Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/AppIcon.appiconset/Icon-87.png differ diff --git a/Zockerhoehle/Assets.xcassets/LaunchScreen.imageset/Contents.json b/Zockerhoehle/Assets.xcassets/LaunchScreen.imageset/Contents.json new file mode 100644 index 0000000..e9221c4 --- /dev/null +++ b/Zockerhoehle/Assets.xcassets/LaunchScreen.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "filename" : "Default-2436h.png", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Zockerhoehle/Assets.xcassets/LaunchScreen.imageset/Default-2436h.png b/Zockerhoehle/Assets.xcassets/LaunchScreen.imageset/Default-2436h.png new file mode 100644 index 0000000..a4bb9b3 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/LaunchScreen.imageset/Default-2436h.png differ diff --git a/Zockerhoehle/Assets.xcassets/basket.imageset/Contents.json b/Zockerhoehle/Assets.xcassets/basket.imageset/Contents.json new file mode 100644 index 0000000..63f8852 --- /dev/null +++ b/Zockerhoehle/Assets.xcassets/basket.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "basket-supermarket.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Zockerhoehle/Assets.xcassets/basket.imageset/basket-supermarket.png b/Zockerhoehle/Assets.xcassets/basket.imageset/basket-supermarket.png new file mode 100644 index 0000000..13f478d Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/basket.imageset/basket-supermarket.png differ diff --git a/Zockerhoehle/Assets.xcassets/cave.imageset/Contents.json b/Zockerhoehle/Assets.xcassets/cave.imageset/Contents.json new file mode 100644 index 0000000..76d4481 --- /dev/null +++ b/Zockerhoehle/Assets.xcassets/cave.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "cave-2.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Zockerhoehle/Assets.xcassets/cave.imageset/cave-2.png b/Zockerhoehle/Assets.xcassets/cave.imageset/cave-2.png new file mode 100644 index 0000000..ceb6916 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/cave.imageset/cave-2.png differ diff --git a/Zockerhoehle/Assets.xcassets/delete.imageset/Contents.json b/Zockerhoehle/Assets.xcassets/delete.imageset/Contents.json new file mode 100644 index 0000000..41b3654 --- /dev/null +++ b/Zockerhoehle/Assets.xcassets/delete.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "delete.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Zockerhoehle/Assets.xcassets/delete.imageset/delete.png b/Zockerhoehle/Assets.xcassets/delete.imageset/delete.png new file mode 100644 index 0000000..8b88b2c Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/delete.imageset/delete.png differ diff --git a/Zockerhoehle/Assets.xcassets/star.imageset/Contents.json b/Zockerhoehle/Assets.xcassets/star.imageset/Contents.json new file mode 100644 index 0000000..a6b6629 --- /dev/null +++ b/Zockerhoehle/Assets.xcassets/star.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "star.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Zockerhoehle/Assets.xcassets/star.imageset/star.png b/Zockerhoehle/Assets.xcassets/star.imageset/star.png new file mode 100644 index 0000000..3f1caa5 Binary files /dev/null and b/Zockerhoehle/Assets.xcassets/star.imageset/star.png differ diff --git a/Zockerhoehle/Base.lproj/LaunchScreen.storyboard b/Zockerhoehle/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f83f6fd..0000000 --- a/Zockerhoehle/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Zockerhoehle/Base.lproj/Main.storyboard b/Zockerhoehle/Base.lproj/Main.storyboard index 03c13c2..bb8a284 100644 --- a/Zockerhoehle/Base.lproj/Main.storyboard +++ b/Zockerhoehle/Base.lproj/Main.storyboard @@ -1,24 +1,504 @@ - + + - + - + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zockerhoehle/CDManager.swift b/Zockerhoehle/CDManager.swift new file mode 100644 index 0000000..d53a697 --- /dev/null +++ b/Zockerhoehle/CDManager.swift @@ -0,0 +1,69 @@ +// +// CDManager.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 24.06.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// + +import Foundation +import CoreData + +class CDManager { + + static let shared : CDManager = CDManager(); + + private init() { + + } + + // MARK: - Core Data stack + + lazy var persistentContainer: NSPersistentContainer = { + /* + The persistent container for the application. This implementation + creates and returns a container, having loaded the store for the + application to it. This property is optional since there are legitimate + error conditions that could cause the creation of the store to fail. + */ + let container = NSPersistentContainer(name: "Zockerhoehle") + container.loadPersistentStores(completionHandler: { (storeDescription, error) in + if let error = error as NSError? { + // Replace this implementation with code to handle the error appropriately. + // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. + + /* + Typical reasons for an error here include: + * The parent directory does not exist, cannot be created, or disallows writing. + * The persistent store is not accessible, due to permissions or data protection when the device is locked. + * The device is out of space. + * The store could not be migrated to the current model version. + Check the error message to determine what the actual problem was. + */ + fatalError("Unresolved error \(error), \(error.userInfo)") + } + }) + return container + }() + + lazy var viewContext : NSManagedObjectContext = { + self.persistentContainer.viewContext + }() + + // MARK: - Core Data Saving support + + func saveContext () { + persistentContainer.performBackgroundTask({(context) in + if context.hasChanges { + do { + try context.save() + } catch { + // Replace this implementation with code to handle the error appropriately. + // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. + let nserror = error as NSError + fatalError("Unresolved error \(nserror), \(nserror.userInfo)") + } + } + }) + } +} diff --git a/Zockerhoehle/CDModel/Accessory+CoreDataClass.swift b/Zockerhoehle/CDModel/Accessory+CoreDataClass.swift new file mode 100644 index 0000000..bb01f19 --- /dev/null +++ b/Zockerhoehle/CDModel/Accessory+CoreDataClass.swift @@ -0,0 +1,16 @@ +// +// Accessory+CoreDataClass.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + +@objc(Accessory) +public class Accessory: NSManagedObject { + +} diff --git a/Zockerhoehle/CDModel/Accessory+CoreDataProperties.swift b/Zockerhoehle/CDModel/Accessory+CoreDataProperties.swift new file mode 100644 index 0000000..0b47bb3 --- /dev/null +++ b/Zockerhoehle/CDModel/Accessory+CoreDataProperties.swift @@ -0,0 +1,26 @@ +// +// Accessory+CoreDataProperties.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + + +extension Accessory { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Accessory") + } + + @NSManaged public var color: String? + @NSManaged public var manufacturer: String? + @NSManaged public var name: String + @NSManaged public var inWishlist: Bool + @NSManaged public var console: Console? + +} diff --git a/Zockerhoehle/CDModel/Console+CoreDataClass.swift b/Zockerhoehle/CDModel/Console+CoreDataClass.swift new file mode 100644 index 0000000..febe48f --- /dev/null +++ b/Zockerhoehle/CDModel/Console+CoreDataClass.swift @@ -0,0 +1,16 @@ +// +// Console+CoreDataClass.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + +@objc(Console) +public class Console: NSManagedObject { + +} diff --git a/Zockerhoehle/CDModel/Console+CoreDataProperties.swift b/Zockerhoehle/CDModel/Console+CoreDataProperties.swift new file mode 100644 index 0000000..b5e34b6 --- /dev/null +++ b/Zockerhoehle/CDModel/Console+CoreDataProperties.swift @@ -0,0 +1,61 @@ +// +// Console+CoreDataProperties.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + + +extension Console { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Console") + } + + @NSManaged public var generation: Int64 + @NSManaged public var manufacturer: String? + @NSManaged public var name: String? + @NSManaged public var accessories: NSSet + @NSManaged public var games: NSSet + @NSManaged public var logo: Logo? + +} + +// MARK: Generated accessors for accessories +extension Console { + + @objc(addAccessoriesObject:) + @NSManaged public func addToAccessories(_ value: Accessory) + + @objc(removeAccessoriesObject:) + @NSManaged public func removeFromAccessories(_ value: Accessory) + + @objc(addAccessories:) + @NSManaged public func addToAccessories(_ values: NSSet) + + @objc(removeAccessories:) + @NSManaged public func removeFromAccessories(_ values: NSSet) + +} + +// MARK: Generated accessors for games +extension Console { + + @objc(addGamesObject:) + @NSManaged public func addToGames(_ value: Game) + + @objc(removeGamesObject:) + @NSManaged public func removeFromGames(_ value: Game) + + @objc(addGames:) + @NSManaged public func addToGames(_ values: NSSet) + + @objc(removeGames:) + @NSManaged public func removeFromGames(_ values: NSSet) + +} diff --git a/Zockerhoehle/CDModel/Cover+CoreDataClass.swift b/Zockerhoehle/CDModel/Cover+CoreDataClass.swift new file mode 100644 index 0000000..3eeba26 --- /dev/null +++ b/Zockerhoehle/CDModel/Cover+CoreDataClass.swift @@ -0,0 +1,16 @@ +// +// Cover+CoreDataClass.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + +@objc(Cover) +public class Cover: NSManagedObject { + +} diff --git a/Zockerhoehle/CDModel/Cover+CoreDataProperties.swift b/Zockerhoehle/CDModel/Cover+CoreDataProperties.swift new file mode 100644 index 0000000..25e0dba --- /dev/null +++ b/Zockerhoehle/CDModel/Cover+CoreDataProperties.swift @@ -0,0 +1,23 @@ +// +// Cover+CoreDataProperties.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData +import UIKit.UIImage + +extension Cover { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Cover") + } + + @NSManaged public var image: UIImage? + @NSManaged public var game: Game? + +} diff --git a/Zockerhoehle/CDModel/Game+CoreDataClass.swift b/Zockerhoehle/CDModel/Game+CoreDataClass.swift new file mode 100644 index 0000000..0f6cf8b --- /dev/null +++ b/Zockerhoehle/CDModel/Game+CoreDataClass.swift @@ -0,0 +1,16 @@ +// +// Game+CoreDataClass.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + +@objc(Game) +public class Game: NSManagedObject { + +} diff --git a/Zockerhoehle/CDModel/Game+CoreDataProperties.swift b/Zockerhoehle/CDModel/Game+CoreDataProperties.swift new file mode 100644 index 0000000..132928e --- /dev/null +++ b/Zockerhoehle/CDModel/Game+CoreDataProperties.swift @@ -0,0 +1,30 @@ +// +// Game+CoreDataProperties.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + + +extension Game { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Game") + } + + @NSManaged public var finished: Date? + @NSManaged public var inWishlist: Bool + @NSManaged public var isDigital: Bool + @NSManaged public var name: String + @NSManaged public var notes: String? + @NSManaged public var publisher: String? + @NSManaged public var console: Console? + @NSManaged public var series: GameSeries? + @NSManaged public var cover: Cover? + +} diff --git a/Zockerhoehle/CDModel/GameSeries+CoreDataClass.swift b/Zockerhoehle/CDModel/GameSeries+CoreDataClass.swift new file mode 100644 index 0000000..887afef --- /dev/null +++ b/Zockerhoehle/CDModel/GameSeries+CoreDataClass.swift @@ -0,0 +1,16 @@ +// +// GameSeries+CoreDataClass.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + +@objc(GameSeries) +public class GameSeries: NSManagedObject { + +} diff --git a/Zockerhoehle/CDModel/GameSeries+CoreDataProperties.swift b/Zockerhoehle/CDModel/GameSeries+CoreDataProperties.swift new file mode 100644 index 0000000..52fc4e6 --- /dev/null +++ b/Zockerhoehle/CDModel/GameSeries+CoreDataProperties.swift @@ -0,0 +1,41 @@ +// +// GameSeries+CoreDataProperties.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + + +extension GameSeries { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "GameSeries") + } + + @NSManaged public var cover: Data? + @NSManaged public var name: String? + @NSManaged public var games: NSSet + +} + +// MARK: Generated accessors for games +extension GameSeries { + + @objc(addGamesObject:) + @NSManaged public func addToGames(_ value: Game) + + @objc(removeGamesObject:) + @NSManaged public func removeFromGames(_ value: Game) + + @objc(addGames:) + @NSManaged public func addToGames(_ values: NSSet) + + @objc(removeGames:) + @NSManaged public func removeFromGames(_ values: NSSet) + +} diff --git a/Zockerhoehle/CDModel/Logo+CoreDataClass.swift b/Zockerhoehle/CDModel/Logo+CoreDataClass.swift new file mode 100644 index 0000000..e1f4c51 --- /dev/null +++ b/Zockerhoehle/CDModel/Logo+CoreDataClass.swift @@ -0,0 +1,16 @@ +// +// Logo+CoreDataClass.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData + +@objc(Logo) +public class Logo: NSManagedObject { + +} diff --git a/Zockerhoehle/CDModel/Logo+CoreDataProperties.swift b/Zockerhoehle/CDModel/Logo+CoreDataProperties.swift new file mode 100644 index 0000000..a4025cf --- /dev/null +++ b/Zockerhoehle/CDModel/Logo+CoreDataProperties.swift @@ -0,0 +1,23 @@ +// +// Logo+CoreDataProperties.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 06.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// +// + +import Foundation +import CoreData +import UIKit.UIImage + +extension Logo { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Logo") + } + + @NSManaged public var image: UIImage? + @NSManaged public var console: Console? + +} diff --git a/Zockerhoehle/Info.plist b/Zockerhoehle/Info.plist index 16be3b6..e49a713 100644 --- a/Zockerhoehle/Info.plist +++ b/Zockerhoehle/Info.plist @@ -4,6 +4,8 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Zockerhöhle CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -20,6 +22,11 @@ 1 LSRequiresIPhoneOS + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/Zockerhoehle/LaunchScreen.storyboard b/Zockerhoehle/LaunchScreen.storyboard new file mode 100644 index 0000000..1d70994 --- /dev/null +++ b/Zockerhoehle/LaunchScreen.storyboard @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zockerhoehle/Lib/CodableExtensionAny.swift b/Zockerhoehle/Lib/CodableExtensionAny.swift new file mode 100644 index 0000000..0270f59 --- /dev/null +++ b/Zockerhoehle/Lib/CodableExtensionAny.swift @@ -0,0 +1,111 @@ +// +// Ext.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 17.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import Foundation + +// Inspired by https://gist.github.com/mbuchetics/c9bc6c22033014aa0c550d3b4324411a + +struct JSONCodingKeys: CodingKey { + var stringValue: String + + init?(stringValue: String) { + self.stringValue = stringValue + } + + var intValue: Int? + + init?(intValue: Int) { + self.init(stringValue: "\(intValue)") + self.intValue = intValue + } +} + + +extension KeyedDecodingContainer { + + func decode(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary { + let container = try self.nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key) + return try container.decode(type) + } + + func decodeIfPresent(_ type: Dictionary.Type, forKey key: K) throws -> Dictionary? { + guard contains(key) else { + return nil + } + guard try decodeNil(forKey: key) == false else { + return nil + } + return try decode(type, forKey: key) + } + + func decode(_ type: Array.Type, forKey key: K) throws -> Array { + var container = try self.nestedUnkeyedContainer(forKey: key) + return try container.decode(type) + } + + func decodeIfPresent(_ type: Array.Type, forKey key: K) throws -> Array? { + guard contains(key) else { + return nil + } + guard try decodeNil(forKey: key) == false else { + return nil + } + return try decode(type, forKey: key) + } + + func decode(_ type: Dictionary.Type) throws -> Dictionary { + var dictionary = Dictionary() + + for key in allKeys { + if let boolValue = try? decode(Bool.self, forKey: key) { + dictionary[key.stringValue] = boolValue + } else if let stringValue = try? decode(String.self, forKey: key) { + dictionary[key.stringValue] = stringValue + } else if let intValue = try? decode(Int.self, forKey: key) { + dictionary[key.stringValue] = intValue + } else if let doubleValue = try? decode(Double.self, forKey: key) { + dictionary[key.stringValue] = doubleValue + } else if let nestedDictionary = try? decode(Dictionary.self, forKey: key) { + dictionary[key.stringValue] = nestedDictionary + } else if let nestedArray = try? decode(Array.self, forKey: key) { + dictionary[key.stringValue] = nestedArray + } + } + return dictionary + } +} + +extension UnkeyedDecodingContainer { + + mutating func decode(_ type: Array.Type) throws -> Array { + var array: [Any] = [] + while isAtEnd == false { + // See if the current value in the JSON array is `null` first and prevent infite recursion with nested arrays. + if try decodeNil() { + continue + } else if let value = try? decode(Bool.self) { + array.append(value) + } else if let value = try? decode(Double.self) { + array.append(value) + } else if let value = try? decode(String.self) { + array.append(value) + } else if let nestedDictionary = try? decode(Dictionary.self) { + array.append(nestedDictionary) + } else if let nestedArray = try? decode(Array.self) { + array.append(nestedArray) + } + } + return array + } + + mutating func decode(_ type: Dictionary.Type) throws -> Dictionary { + + let nestedContainer = try self.nestedContainer(keyedBy: JSONCodingKeys.self) + return try nestedContainer.decode(type) + } +} diff --git a/Zockerhoehle/Lib/UIButtonX.swift b/Zockerhoehle/Lib/UIButtonX.swift new file mode 100644 index 0000000..2914c46 --- /dev/null +++ b/Zockerhoehle/Lib/UIButtonX.swift @@ -0,0 +1,43 @@ +// +// UIButtonStoryBoardExtenstion.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 22.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import UIKit +import Foundation + +@IBDesignable class UIButtonX : UIButton { + + @IBInspectable var borderWidth: CGFloat { + set { + layer.borderWidth = newValue + } + get { + return layer.borderWidth + } + } + + @IBInspectable var cornerRadius: CGFloat { + set { + layer.cornerRadius = newValue + } + get { + return layer.cornerRadius + } + } + + @IBInspectable var borderColor: UIColor? { + set { + guard let uiColor = newValue else { return } + layer.borderColor = uiColor.cgColor + } + get { + guard let color = layer.borderColor else { return nil } + return UIColor(cgColor: color) + } + } +} + diff --git a/Zockerhoehle/Lib/UIViewX.swift b/Zockerhoehle/Lib/UIViewX.swift new file mode 100644 index 0000000..cb399fe --- /dev/null +++ b/Zockerhoehle/Lib/UIViewX.swift @@ -0,0 +1,53 @@ +// +// UIViewX.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 22.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import Foundation + +// +// UIButtonStoryBoardExtenstion.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 22.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import UIKit +import Foundation + +@IBDesignable class UIViewX : UIView { + + @IBInspectable var borderWidth: CGFloat { + set { + layer.borderWidth = newValue + } + get { + return layer.borderWidth + } + } + + @IBInspectable var cornerRadius: CGFloat { + set { + layer.cornerRadius = newValue + } + get { + return layer.cornerRadius + } + } + + @IBInspectable var borderColor: UIColor? { + set { + guard let uiColor = newValue else { return } + layer.borderColor = uiColor.cgColor + } + get { + guard let color = layer.borderColor else { return nil } + return UIColor(cgColor: color) + } + } +} + diff --git a/Zockerhoehle/Model/Attachment.swift b/Zockerhoehle/Model/Attachment.swift new file mode 100644 index 0000000..23b36c4 --- /dev/null +++ b/Zockerhoehle/Model/Attachment.swift @@ -0,0 +1,31 @@ +// +// Attachment.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 14.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import Foundation + +typealias AttachmentID = String + +struct Attachment : Codable { + var id : AttachmentID + var type : String + var file : Data? + var isDeleted : Bool + var description : String + var createdOn : String + var changedOn : String + + enum CodingKeys : String, CodingKey { + case id = "_id" + case type + case file + case isDeleted + case description + case createdOn = "created" + case changedOn = "changed" + } +} diff --git a/Zockerhoehle/Model/ConsoleEntry.swift b/Zockerhoehle/Model/ConsoleEntry.swift new file mode 100644 index 0000000..ea97868 --- /dev/null +++ b/Zockerhoehle/Model/ConsoleEntry.swift @@ -0,0 +1,44 @@ +// +// ConsoleEntry.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 17.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import Foundation + +class ConsoleEntry : FlockeEntry { + var generation : Int? { + get { + return self.content["Generation"] as? Int + } + } + + var manufacturer : String? { + get { + return self.content["Manufacturer"] as? String + } + } + + override init(entry: FlockeEntry) { + super.init(entry: entry) + } + + required init(from decoder: Decoder) throws { + try super.init(from: decoder) + } + + override func encodeContent(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + var contentContainer = container.nestedContainer(keyedBy: CodingKeysContentConsoleEntry.self, forKey: CodingKeys.content) + try contentContainer.encode(self.generation, forKey: CodingKeysContentConsoleEntry.Generation) + try contentContainer.encode(self.manufacturer, forKey: CodingKeysContentConsoleEntry.Manufacturer) + } + + enum CodingKeysContentConsoleEntry : String, CodingKey { + case Generation = "Generation" + case Manufacturer + } +} diff --git a/Zockerhoehle/Model/FlockeEntry.swift b/Zockerhoehle/Model/FlockeEntry.swift new file mode 100644 index 0000000..4b1595c --- /dev/null +++ b/Zockerhoehle/Model/FlockeEntry.swift @@ -0,0 +1,103 @@ +// +// Console.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 12.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import Foundation + +typealias FlockeEntryID = String + +class FlockeEntry : Codable { + let id : FlockeEntryID + let isDeleted : Bool + let name : String + let createdOn : String + let changedOn : String + let content : [String : Any] + var iconAttachment : Attachment? + var parents : [FlockeEntryID] + + init (entry : FlockeEntry) { + self.id = entry.id + self.isDeleted = entry.isDeleted + self.name = entry.name + self.createdOn = entry.createdOn + self.changedOn = entry.changedOn + self.content = entry.content + self.iconAttachment = entry.iconAttachment + self.parents = entry.parents + } + + required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + id = try container.decode(String.self, forKey: .id) + isDeleted = try container.decode(Bool.self, forKey: .isDeleted) + name = try container.decode(String.self, forKey: .name) + createdOn = try container.decode(String.self, forKey: .createdOn) + changedOn = try container.decode(String.self, forKey: .changedOn) + + parents = try container.decode([FlockeEntryID].self, forKey: .parents) + + do { + content = try container.decode([String : Any].self, forKey: .content) + }catch{ + content = [:] + } + + do { + let attachmentContainer = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .attachments) + + iconAttachment = try? attachmentContainer.decode(Attachment.self, forKey: .icon) + }catch { + iconAttachment = nil + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(self.id, forKey: .id) + try container.encode(self.isDeleted, forKey: .isDeleted) + try container.encode(self.name, forKey: .name) + try container.encode(self.createdOn, forKey: .createdOn) + try container.encode(self.changedOn, forKey: .changedOn) + + try container.encode(self.parents, forKey: .parents) + + var attachmentContainer = container.nestedContainer(keyedBy: CodingKeys.self, forKey: .attachments) + + try attachmentContainer.encode(self.iconAttachment, forKey: .icon) + + if (!self.content.isEmpty) { + try encodeContent(to: encoder); + } + } + + func encodeContent(to encoder: Encoder) throws {} + + enum CodingKeys : String, CodingKey { + case id = "_id" + case isDeleted + case name = "name" + case createdOn = "created" + case changedOn = "changed" + case content + case manufacturer = "Manufacturer" + case generation = "Generation" + case attachments + case icon + case parents + } +} + +extension FlockeEntry: Equatable { + static func == (lhs: FlockeEntry, rhs: FlockeEntry) -> Bool { + return lhs.id == rhs.id + } + + +} diff --git a/Zockerhoehle/Model/GameCollection.swift b/Zockerhoehle/Model/GameCollection.swift new file mode 100644 index 0000000..660562d --- /dev/null +++ b/Zockerhoehle/Model/GameCollection.swift @@ -0,0 +1,185 @@ +// +// Consoles.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 13.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import Foundation +import Disk +import CoreData + +protocol ConsoleItemObserver { + func consoleItemDataUpdate(for parent : FlockeEntryID) +} + +protocol AttachmentObserver { + func attachmentUpdate(attachmentID : AttachmentID) +} + +class GameCollection { + static let shared : GameCollection = GameCollection() + + //TODO: Zusammenfuehren von consoles und consoleItemsByParent + var consoles : [ConsoleEntry] = [] + var consoleItemsByParent : [FlockeEntryID : [FlockeEntry]] = [:] + var attachments : [AttachmentID : Attachment] = [:] + + private var consoleItemObservers : [ConsoleItemObserver] = [] + private var attachmentObservers : [AttachmentObserver] = [] + + init() { + do { + self.consoles = try Disk.retrieve("consoles.json", from: .caches, as: [ConsoleEntry].self) + self.consoleItemsByParent = try Disk.retrieve("consoleItems.json", from: .caches, as: [FlockeEntryID : [FlockeEntry]].self) + self.attachments = try Disk.retrieve("attachments.json", from: .caches, as: [AttachmentID : Attachment].self) + + //Fill core data on Startup + + print("Game Collection import begin"); + + let cdm = CDManager.shared + + for console in self.consoles { + let cdConsole = Console(entity: Console.entity(), insertInto: cdm.viewContext) + cdConsole.name = console.name + + cdConsole.generation = Int64(console.generation ?? 0) + cdConsole.manufacturer = console.manufacturer + + guard let consoleItems = self.consoleItemsByParent[console.id] else { + print("No games: \(console.name)") + continue + } + + if let imgID = console.iconAttachment?.id , let img = self.attachments[imgID]?.file { + let cdLogo = Logo(entity: Logo.entity(), insertInto: cdm.viewContext) + cdLogo.image = UIImage(data: img) + cdConsole.logo = cdLogo + } + + for item in consoleItems { + if (item.parents.contains(GameCollection.accessoryID)) { + let cdAccessory = Accessory(entity: Accessory.entity(), insertInto: cdm.viewContext) + + cdAccessory.name = item.name + cdAccessory.inWishlist = item.parents.contains(GameCollection.wishlistID) + cdConsole.addToAccessories(cdAccessory) + + }else if (item.parents.contains(GameCollection.videogameID)) { + let cdGame = Game(entity: Game.entity(), insertInto: cdm.viewContext) + + cdGame.name = item.name + cdGame.inWishlist = item.parents.contains(GameCollection.wishlistID) + + cdConsole.addToGames(cdGame) + } + } + } + + }catch let error as NSError { + print("Load of Chached not possible \(error.localizedDescription)"); + } + } + + func addFlockeEntryObserver(observer: ConsoleItemObserver) { + self.consoleItemObservers.append(observer) + } + + func addAttachmentObserver(observer: AttachmentObserver) { + self.attachmentObservers.append(observer) + } + + fileprivate func notifyConSoleItemObservers(_ parent: FlockeEntryID) { + for observer in self.consoleItemObservers { + observer.consoleItemDataUpdate(for: parent) + } + } + + func updateGameItems(items : [FlockeEntry], with parent : FlockeEntryID) { + if parent == GameCollection.consoleID { + updateConsoles(entrys: items) + }else { + self.consoleItemsByParent[parent] = items + + do { + try Disk.save(self.consoleItemsByParent, to: .caches, as: "consoleItems.json") + }catch let error as NSError { + print("Write of GameItems not possible \(error.localizedDescription)"); + } + } + + notifyConSoleItemObservers(parent) + } + + func remove(from: FlockeEntry, parentID: FlockeEntryID) { + from.parents.removeAll(where: {$0 == parentID}) + + for parent in from.parents { + notifyConSoleItemObservers(parent) + } + } + + func removeGameItem(from console : FlockeEntry, item: FlockeEntry) { + guard let consoleItems : [FlockeEntry] = self.consoleItemsByParent[console.id] else { + return + } + + if let index = consoleItems.firstIndex(of: item) { + consoleItemsByParent[console.id]!.remove(at: index); + + notifyConSoleItemObservers(console.id) + } + } + + func updateAttachment(attachment : Attachment) { + self.attachments[attachment.id] = attachment + + do { + try Disk.save(self.attachments, to: .caches, as: "attachments.json") + }catch let error as NSError { + print("Write of Attachments not possible \(error.localizedDescription)"); + } + + for observer in self.attachmentObservers { + observer.attachmentUpdate(attachmentID: attachment.id) + } + } + + func updateConsoles(entrys: [FlockeEntry]) { + self.consoles = [] + for entry in entrys { + self.consoles.append(ConsoleEntry(entry: entry)) + } + + //IN-Place Sort + self.consoles.sort { + //1. Sort by manufacturer + if ($0.manufacturer == $1.manufacturer) { +// //2. Sort by console generation + if ($0.generation == $1.generation) { +// //3. Sort by console name + return $0.name < $1.name + } + + return $0.generation! < $1.generation! + } + + return $0.manufacturer! < $1.manufacturer! + } + + do { + try Disk.save(self.consoles, to: .caches, as: "consoles.json") + }catch let error as NSError { + print("Write of ConsoleItem not possible \(error.localizedDescription)"); + } + } +} + +extension GameCollection { + static let consoleID : FlockeEntryID = "5b0c2ff8ba0c0b4ae7559911" + static let videogameID : FlockeEntryID = "5b116282ba0c0b4ae75599be" + static let wishlistID : FlockeEntryID = "5b11628dba0c0b4ae75599bf" + static let accessoryID : FlockeEntryID = "5b1162ccba0c0b4ae75599c1" +} diff --git a/Zockerhoehle/Utils/FlockeConnector.swift b/Zockerhoehle/Utils/FlockeConnector.swift new file mode 100644 index 0000000..2e5eedf --- /dev/null +++ b/Zockerhoehle/Utils/FlockeConnector.swift @@ -0,0 +1,45 @@ +// +// FlockeConnector.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 29.10.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import Foundation + +class FlockeConnector { + let flockeURL : URL? + let bodyDict : NSDictionary? + let requestType : String + let completionHandler : (Data?, URLResponse?, Error?) -> Void + + init(url : String, requestType : String = "GET", bodyDict : NSDictionary?, _ completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) { + self.flockeURL = URL.init(string: url) + self.bodyDict = bodyDict + self.requestType = requestType + self.completionHandler = completionHandler + } + + func doRequest() { + guard let url = self.flockeURL else { + print("DO Request: Creating URL fails") + return + } + + + do { + let requestBodyJSON = try JSONSerialization.data(withJSONObject: self.bodyDict!) + + var req = URLRequest.init(url: url) + req.httpMethod = self.requestType + req.httpBody = requestBodyJSON + req.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") + + URLSession.shared.dataTask(with: req, completionHandler: self.completionHandler).resume() + }catch { + print("Cannot convert to JSON") + return + } + } +} diff --git a/Zockerhoehle/Utils/FlockeWS.swift b/Zockerhoehle/Utils/FlockeWS.swift new file mode 100644 index 0000000..e5f7200 --- /dev/null +++ b/Zockerhoehle/Utils/FlockeWS.swift @@ -0,0 +1,143 @@ +// +// FlockeLoader.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 13.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import Foundation +import Disk + +extension Notification.Name { + static let FlockeWSDeleteFinished = Notification.Name("flockeWSDeleteFinished") + static let FlockeWSAddFinished = Notification.Name("flockeWSAddFinished") +} + +class FlockeWS { + @objc enum ERROR_STATE : Int { + case NO_ERROR + case REQUEST_FAILED + } + + static func fetchEntries(for parent: FlockeEntryID) { + guard let fetchEntriesURL = URL.init(string: "http://flocke.mueller.haus:8081/entry/parent/\(parent)") else { + print("FETCH ENTRIES: Creating URL fails") + return + } + + let task = URLSession.shared.dataTask(with: fetchEntriesURL) { (data, resp, err) in + if (err == nil) { + let consoles : [FlockeEntry] = try! JSONDecoder().decode([FlockeEntry].self, from: data!) + + DispatchQueue.main.async { + GameCollection.shared.updateGameItems(items: consoles, with: parent) + } + } + } + task.resume() + } + + static func fetchAttachment(attachment attachmentId : AttachmentID) { + guard let fetchAttachmentURL = URL.init(string: "http://flocke.mueller.haus:8081/attachment/\(attachmentId)") else { + print("FETCH ATTACHMENT: Creating URL fails") + return + } + + URLSession.shared.dataTask(with: fetchAttachmentURL) { (data, resp, err) in + if (err == nil) { + let attachment : Attachment = try! JSONDecoder().decode(Attachment.self, from: data!) + + + DispatchQueue.main.async { + GameCollection.shared.updateAttachment(attachment: attachment) + } + } + + }.resume() + } + + static func deleteEntry(by entry: FlockeEntryID) { + guard let flockeDeleteEntryURL = URL.init(string: "http://flocke.mueller.haus:8081/entry/\(entry)") else { + print("DELETE ENTRY: Creating URL fails") + return + } + + var req = URLRequest.init(url: flockeDeleteEntryURL) + req.httpMethod = "DELETE" + + URLSession.shared.dataTask(with: req) { (data, resp, err) in + if (err == nil) { + DispatchQueue.main.async { + //TODO GameCollection Update + NotificationCenter.default.post(name: .FlockeWSDeleteFinished, object: nil) + } + } + }.resume() + } + + static func deleteParents(entry entryID : FlockeEntryID, parents : [FlockeEntryID]) { + print("DELETE PARENTS WS \(entryID) - \(parents)") + + let addJSON : NSMutableDictionary = NSMutableDictionary() + addJSON.setValue(entryID, forKey: "id") + addJSON.setValue(parents, forKey: "parents") + + do { + let jsonBodyData = try JSONSerialization.data(withJSONObject: addJSON, options: []) + let jsonBodyString = String(data: jsonBodyData, encoding: .utf8) ?? "{}" + print(jsonBodyString) + + let connector : FlockeConnector = FlockeConnector(url: "http://flocke.mueller.haus:8081/entry/deleteParents", + requestType: "PUT", + bodyDict: addJSON) { (data, resp, err) in +// DispatchQueue.main.async { +// //NOP +// } + } + + connector.doRequest() + }catch { + return; + } + + return; + } + + + static func addEntry(name : String, consoleID : FlockeEntryID, isVideogame : Bool, isOnWishlist : Bool) { + print("ADD WS \(name) \(isVideogame) \(isOnWishlist)") + + var parents : [String] = [consoleID] + + if (isVideogame) { + parents.append(GameCollection.videogameID) + }else{ + parents.append(GameCollection.accessoryID) + } + + if isOnWishlist { + parents.append(GameCollection.wishlistID) + } + + let addJSON : NSMutableDictionary = NSMutableDictionary() + addJSON.setValue(name, forKey: "name") + addJSON.setValue(parents, forKey: "parents") + + let connector : FlockeConnector = FlockeConnector(url: "http://flocke.mueller.haus:8081/entry/", + requestType: "POST", + bodyDict: addJSON) { (data, resp, err) in + var requestError = FlockeWS.ERROR_STATE.NO_ERROR + + if (err != nil) { requestError = FlockeWS.ERROR_STATE.REQUEST_FAILED } + + + DispatchQueue.main.async { + let userInfo:[String: FlockeWS.ERROR_STATE] = ["error_state": requestError] + NotificationCenter.default.post(name: .FlockeWSAddFinished, object: nil, userInfo: userInfo) + } + } + + connector.doRequest() + } +} diff --git a/Zockerhoehle/ViewController.swift b/Zockerhoehle/ViewController.swift deleted file mode 100644 index 51493a3..0000000 --- a/Zockerhoehle/ViewController.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ViewController.swift -// Zockerhoehle -// -// Created by Julian-Steffen Müller on 12.09.18. -// Copyright © 2018 Julian-Steffen Müller. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - -} - diff --git a/Zockerhoehle/ViewController/AccessoryDetailController.swift b/Zockerhoehle/ViewController/AccessoryDetailController.swift new file mode 100644 index 0000000..2724821 --- /dev/null +++ b/Zockerhoehle/ViewController/AccessoryDetailController.swift @@ -0,0 +1,20 @@ +// +// AccessoryDetailController.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 12.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// + +import Foundation +import UIKit +import SwiftUI + +class AccessoryDetailController : UIViewController { + var accessory : Accessory? + + + @IBSegueAction func emebdedAccessoryDetaio(_ coder: NSCoder) -> UIViewController? { + return UIHostingController(coder: coder, rootView: AccessoryDetailView(accessory: accessory)) + } +} diff --git a/Zockerhoehle/ViewController/AddEntryPopUpViewController.swift b/Zockerhoehle/ViewController/AddEntryPopUpViewController.swift new file mode 100644 index 0000000..d009b3a --- /dev/null +++ b/Zockerhoehle/ViewController/AddEntryPopUpViewController.swift @@ -0,0 +1,71 @@ +// +// AddEntryPopUpViewController.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 20.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import UIKit + +class AddEntryPopUpViewController: UIViewController { + var isWishlist : Bool = false + var isVideogame : Bool = true + var console : Console? + + @IBOutlet weak var icon: UIImageView! + @IBOutlet weak var category: UISegmentedControl! + @IBOutlet weak var wishlistIcon: UIImageView! + @IBOutlet weak var name: UITextField! + @IBOutlet weak var addButton: UIButtonX! + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + self.category.selectedSegmentIndex = 0 + + if (!self.isVideogame && !self.isWishlist) { + self.category.selectedSegmentIndex = 1 + } + + self.wishlistIcon.isHidden = !self.isWishlist + + self.icon.image = self.console?.logo?.image + + //If the name is not filled the add Button should be disabled + addButton.isEnabled = name.text != "" + } + + @IBAction func nameChanged(_ sender: Any) { + addButton.isEnabled = name.text != "" + } + + @IBAction func add(_ sender: Any) { + self.isVideogame = self.category.selectedSegmentIndex == 0 + + guard let name = self.name.text else { + print("ERROR AddEntryPopoUpViewController::Add; Game name is empty") + return + } + + if self.isVideogame { + let game = Game(entity: Game.entity(), insertInto: CDManager.shared.viewContext) + game.name = name + game.console = console + + print("Added Game '\(game.name)'") + }else{ + let accessory = Accessory(entity: Accessory.entity(), insertInto: CDManager.shared.viewContext) + accessory.name = name + accessory.console = console + + print("Added Accessory '\(accessory.name)'") + } + + self.dismiss(animated: true) + } + + @IBAction func cancel(_ sender: Any) { + self.dismiss(animated: true) + } +} diff --git a/Zockerhoehle/ViewController/AllConsolesViewController.swift b/Zockerhoehle/ViewController/AllConsolesViewController.swift new file mode 100644 index 0000000..4912a25 --- /dev/null +++ b/Zockerhoehle/ViewController/AllConsolesViewController.swift @@ -0,0 +1,78 @@ +// +// UIConsoleTableViewController.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 12.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import UIKit +import CoreData + +class AllConsolesViewController: UIViewController, NSFetchedResultsControllerDelegate { + @IBOutlet weak var consolesTable: UITableView! + @IBOutlet weak var manufacturer: UILabel! + @IBOutlet weak var consoleLogo: UIImageView! + + lazy var fetchResultsController : NSFetchedResultsController = { + let consolesFetch : NSFetchRequest = Console.fetchRequest() + + consolesFetch.sortDescriptors = [NSSortDescriptor(key: "manufacturer", ascending: true), NSSortDescriptor(key: "generation", ascending: true), NSSortDescriptor(key: "name", ascending: true)] + + var consolesfetchRC = NSFetchedResultsController(fetchRequest: consolesFetch, managedObjectContext: CDManager.shared.viewContext, sectionNameKeyPath: nil, cacheName: nil) + + consolesfetchRC.delegate = self + + return consolesfetchRC + + }() + + func controllerDidChangeContent(_ controller: NSFetchedResultsController) { + print("AllConsolesViewController::controllerDidChangeContent") + self.consolesTable.reloadData() + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if (segue.identifier == "consoleDetail" && sender! is ConsoleCell) { + guard let consoleVC = segue.destination as? ConsoleLibraryViewController else { + return + } + guard let consoleCell = sender as? ConsoleCell else { + return + } + + consoleVC.console = consoleCell.console + } + } + + override func viewDidLoad() { + super.viewDidLoad() + FlockeWS.fetchEntries(for: GameCollection.consoleID) + do { + try fetchResultsController.performFetch() + }catch{ + print("AllConsolesViewController::viewDidLoad: Fetch not possible"); + } + } +} +extension AllConsolesViewController: UITableViewDataSource { + func numberOfSections(in tableView: UITableView) -> Int { + guard let sections = fetchResultsController.sections else { return 0 } + + return sections.count + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + guard let sections = fetchResultsController.sections else { return 0 } + + return sections[section].numberOfObjects + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = (tableView.dequeueReusableCell(withIdentifier: "ConsoleCell", for: indexPath)) as! ConsoleCell + + cell.console = fetchResultsController.object(at: indexPath) + + return cell + } +} diff --git a/Zockerhoehle/ViewController/ConsoleLibraryViewController.swift b/Zockerhoehle/ViewController/ConsoleLibraryViewController.swift new file mode 100644 index 0000000..f42df2a --- /dev/null +++ b/Zockerhoehle/ViewController/ConsoleLibraryViewController.swift @@ -0,0 +1,189 @@ +// +// ConsoleViewController.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 12.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import UIKit +import CoreData +import Combine + +class ConsoleLibraryViewController: UIViewController { + @IBOutlet weak var consoleItemTable: UITableView! + @IBOutlet weak var category: UISegmentedControl! + @IBOutlet weak var toggleWishList: UIBarButtonItem! + + var subsriber : Subscribers.Sink? + var videoGamesInLibrary : [Bool : [Game]] = [:] + var accessoriesinLibrary : [Bool : [Accessory]] = [:] + var showWishlist : Bool = false + + var console : Console? { + didSet { + self.title = console?.name ?? "N/A" + + //Remove subscription to old console object + subsriber?.cancel() + + subsriber = console?.publisher(for: \.games, options: .new).sink(receiveValue: {_ in + self.refreshConsoleLibrary() + }) + + refreshConsoleLibrary() + } + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if segue.identifier == "detail" { + guard let indexpath = self.consoleItemTable.indexPathForSelectedRow else { + print("ConsoleLibraryViewController::prepare::detail IndexPath for selectedRow could not be retreived") + return + } + + if let dest = segue.destination as? GameDetailController { + dest.game = self.videoGamesInLibrary[self.showWishlist]?[indexpath.row] + }else if let dest = segue.destination as? AccessoryDetailController { + dest.accessory = self.accessoriesinLibrary[self.showWishlist]?[indexpath.row] + } + }else if (segue.identifier == "consoleEntryAdd") { + guard let addPopup = segue.destination as? AddEntryPopUpViewController else { + print("ConsoleLibraryViewController::prepare::consoleEntryAdd Destination is no AddEntryPopUpViewController") + return + } + + addPopup.console = self.console + addPopup.isVideogame = self.category.selectedSegmentIndex == 0 + } + + } + + @IBAction func categoryChanged(_ sender: Any) { + self.consoleItemTable.reloadData() + } + + override func viewWillAppear(_ animated: Bool) { + if self.showWishlist { + self.toggleWishList.tintColor = UIColor.red + }else{ + self.toggleWishList.tintColor = UIColor.black + } + + self.toggleWishList.tintColor = UIColor.black + } + + func refreshConsoleLibrary() { + let videogames = self.console?.games.map({$0 as! Game}) ?? [] + self.videoGamesInLibrary[true] = videogames.filter({$0.inWishlist}) + self.videoGamesInLibrary[false] = videogames.filter({!$0.inWishlist}) + + let accessories = self.console?.accessories.map({$0 as! Accessory}) ?? [] + self.accessoriesinLibrary[true] = accessories.filter({$0.inWishlist}) + self.accessoriesinLibrary[false] = accessories.filter({!$0.inWishlist}) + + consoleItemTable?.reloadData() + } + + @IBAction func toggleWishlist(_ sender: Any) { + self.showWishlist = !self.showWishlist + + if self.showWishlist { + self.toggleWishList.tintColor = UIColor.red + }else{ + self.toggleWishList.tintColor = UIColor.black + } + + consoleItemTable.reloadData() + } +} + +extension ConsoleLibraryViewController: UITableViewDataSource { + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if self.category.selectedSegmentIndex == 0 { + return self.videoGamesInLibrary[self.showWishlist]?.count ?? 0 + }else{ + return self.accessoriesinLibrary[self.showWishlist]?.count ?? 0 + } + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if self.category.selectedSegmentIndex == 0 { + let gameCell = tableView.dequeueReusableCell(withIdentifier: "gameCell") as! GameCell + + gameCell.game = self.videoGamesInLibrary[self.showWishlist]?[indexPath.row] + + return gameCell + }else{ + let accessoryCell = tableView.dequeueReusableCell(withIdentifier: "accessoryCell") as! AccessoryCell + + + accessoryCell.accessory = self.accessoriesinLibrary[self.showWishlist]?[indexPath.row] + + return accessoryCell + } + + } +} + + +// Swipe Action - Delete / move console items from / into the library +extension ConsoleLibraryViewController: UITableViewDelegate { + + // Move console item to library + func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { + let bought = UIContextualAction(style: .destructive, title: "") { (action, view, actionDone) in + actionDone(true) + if self.category.selectedSegmentIndex == 0 { + let game = self.videoGamesInLibrary[self.showWishlist]?[indexPath.row] + game?.inWishlist = false + }else{ + let accessory = self.accessoriesinLibrary[self.showWishlist]?[indexPath.row] + accessory?.inWishlist = false + } + + self.refreshConsoleLibrary() + } + + bought.image = #imageLiteral(resourceName: "cave") + bought.backgroundColor = #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1) + + if (self.showWishlist) { + return UISwipeActionsConfiguration(actions: [bought]) + } + + return UISwipeActionsConfiguration(actions: []) + } + + // Delete console item from library + func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { + /*let selectedItem = self.consoleItemsToDisplay()[indexPath.row] + let delete = UIContextualAction(style: .destructive, title: "Delete") { (action, view, actionDone) in + let deleteWarning = UIAlertController( title: "Aus Zockerhöhle entfernen", + message: "Willst du '\("N/A")' wirklich aus der Zockerhöhle tragen?", + preferredStyle: .alert) + + deleteWarning.addAction(UIAlertAction(title: "Ja", style: .destructive, handler: { (action) in + actionDone(true) + + //FlockeWS.deleteEntry(by: selectedItem.id); + //GameCollection.shared.removeGameItem(from: self.currentConsole!, item: selectedItem) + })) + + deleteWarning.addAction(UIAlertAction(title: "Nein", style: .cancel, handler: { (action) in + actionDone(false) + })) + + self.present(deleteWarning, animated: true, completion: nil) + }*/ + + //delete.image = #imageLiteral(resourceName: "delete") + //delete.backgroundColor = #colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1) + + return UISwipeActionsConfiguration(actions: [])//delete]) + } +} diff --git a/Zockerhoehle/ViewController/GameDetailController.swift b/Zockerhoehle/ViewController/GameDetailController.swift new file mode 100644 index 0000000..0a6914a --- /dev/null +++ b/Zockerhoehle/ViewController/GameDetailController.swift @@ -0,0 +1,20 @@ +// +// ConsoleDetailEmbewdViewController.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 08.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// + +import Foundation +import UIKit +import SwiftUI + +class GameDetailController : UIViewController { + var game : Game? + + + @IBSegueAction func embedConsoleDetail(_ coder: NSCoder) -> UIViewController? { + return UIHostingController(coder: coder, rootView: GameDetailView(game: game)) + } +} diff --git a/Zockerhoehle/Views/AccessoryCell.swift b/Zockerhoehle/Views/AccessoryCell.swift new file mode 100644 index 0000000..9961014 --- /dev/null +++ b/Zockerhoehle/Views/AccessoryCell.swift @@ -0,0 +1,24 @@ +// +// AccessoryCell.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 12.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// + +import UIKit + +class AccessoryCell: UITableViewCell { + @IBOutlet weak var name: UILabel! + + var accessory : Accessory? { + didSet { + self.name.text = accessory?.name ?? "N/A" + } + } + + /*func setAccessory(accessory : Accessory?) { + self.accessory = accessory + self.name.text = accessory?.name ?? "N/A" + }*/ +} diff --git a/Zockerhoehle/Views/AccessoryDetailView.swift b/Zockerhoehle/Views/AccessoryDetailView.swift new file mode 100644 index 0000000..b061641 --- /dev/null +++ b/Zockerhoehle/Views/AccessoryDetailView.swift @@ -0,0 +1,29 @@ +// +// AccessoryDetailView.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 12.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// + +import SwiftUI + +struct AccessoryDetailView : View { + var accessory : Accessory? + + var body: some View { + Text(accessory?.name ?? "N/A").color(Color.red) + } + + init(accessory : Accessory?) { + self.accessory = accessory + } +} + +#if DEBUG +struct AccessoryDetailView_Previews : PreviewProvider { + static var previews: some View { + AccessoryDetailView(accessory: nil) + } +} +#endif diff --git a/Zockerhoehle/Views/ConsoleCell.swift b/Zockerhoehle/Views/ConsoleCell.swift new file mode 100644 index 0000000..165770c --- /dev/null +++ b/Zockerhoehle/Views/ConsoleCell.swift @@ -0,0 +1,30 @@ +// +// ConsoleCell.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 12.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import UIKit + +class ConsoleCell: UITableViewCell { + @IBOutlet weak var consoleName: UILabel! + @IBOutlet weak var logo: UIImageView! + @IBOutlet weak var gamesCounter: UILabel! + @IBOutlet weak var accessoryCounter: UILabel! + + public var console: Console? { + didSet { + consoleName.text = console?.name + self.logo.image = console?.logo?.image + + let ownedGames = console?.games.filtered(using: NSPredicate(format: "inWishlist = false")).count ?? 0 + let ownedAccessories = console?.accessories.filtered(using: NSPredicate(format: "inWishlist = false")).count ?? 0 + self.gamesCounter.text = "\(ownedGames)" + self.accessoryCounter.text = "\(ownedAccessories)" + + self.setNeedsDisplay() + } + } +} diff --git a/Zockerhoehle/Views/GameCell.swift b/Zockerhoehle/Views/GameCell.swift new file mode 100644 index 0000000..3f35e36 --- /dev/null +++ b/Zockerhoehle/Views/GameCell.swift @@ -0,0 +1,20 @@ +// +// GameCell.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 16.09.18. +// Copyright © 2018 Julian-Steffen Müller. All rights reserved. +// + +import UIKit + +class GameCell: UITableViewCell { + @IBOutlet weak var name: UILabel! + + var game : Game? { + didSet { + self.name.text = game?.name ?? "N/A" + } + } +} + diff --git a/Zockerhoehle/Views/GameDetailView.swift b/Zockerhoehle/Views/GameDetailView.swift new file mode 100644 index 0000000..c9dbffe --- /dev/null +++ b/Zockerhoehle/Views/GameDetailView.swift @@ -0,0 +1,28 @@ +// +// GameDetailView.swift +// Zockerhoehle +// +// Created by Julian-Steffen Müller on 08.07.19. +// Copyright © 2019 Julian-Steffen Müller. All rights reserved. +// + +import SwiftUI + +struct GameDetailView : View { + var game : Game? + var body: some View { + Text(game?.name ?? "N/A") + } + + init(game : Game?) { + self.game = game + } +} + +#if DEBUG +struct GameDetailView_Previews : PreviewProvider { + static var previews: some View { + GameDetailView(game: nil) + } +} +#endif diff --git a/Zockerhoehle/Zockerhoehle.xcdatamodeld/Zockerhoehle.xcdatamodel/contents b/Zockerhoehle/Zockerhoehle.xcdatamodeld/Zockerhoehle.xcdatamodel/contents new file mode 100644 index 0000000..0a345bc --- /dev/null +++ b/Zockerhoehle/Zockerhoehle.xcdatamodeld/Zockerhoehle.xcdatamodel/contents @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Zockerhoehle/Zockerhoehle/Base.lproj/WaitingPopOver.storyboard b/Zockerhoehle/Zockerhoehle/Base.lproj/WaitingPopOver.storyboard new file mode 100644 index 0000000..99d74f9 --- /dev/null +++ b/Zockerhoehle/Zockerhoehle/Base.lproj/WaitingPopOver.storyboard @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zockerhoehle/de.lproj/Main.strings b/Zockerhoehle/de.lproj/Main.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Zockerhoehle/de.lproj/Main.strings @@ -0,0 +1 @@ +