New Baseline -- Added basic Cloudkit support and changed to julian.steffen@me.com Apple Developer Account
This commit is contained in:
@@ -3,61 +3,87 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 50;
|
||||
objectVersion = 52;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
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 */; };
|
||||
B90E03EB238557D900E79643 /* LibraryImport.swift in Sources */ = {isa = PBXBuildFile; fileRef = B90E03EA238557D900E79643 /* LibraryImport.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 */; };
|
||||
B93C1BA421496BFE0014FD6E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B93C1BA321496BFE0014FD6E /* Assets.xcassets */; };
|
||||
B93D60CE22D88F5700DD390F /* AccessoryDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */; };
|
||||
B93D60D122E5009700DD390F /* GameViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93D60D022E5009700DD390F /* GameViewModel.swift */; };
|
||||
B94112DE233A37DD00159AE4 /* DateConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94112DD233A37DD00159AE4 /* DateConversion.swift */; };
|
||||
B94112E0233A4EF800159AE4 /* GamePickupsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94112DF233A4EF800159AE4 /* GamePickupsView.swift */; };
|
||||
B94112E2233B55B100159AE4 /* ConsoleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94112E1233B55B100159AE4 /* ConsoleViewModel.swift */; };
|
||||
B94112E4233B597D00159AE4 /* ConsoleEditView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94112E3233B597D00159AE4 /* ConsoleEditView.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 */; };
|
||||
B97AD2E0244CE4B4004AF00D /* Disk in Frameworks */ = {isa = PBXBuildFile; productRef = B97AD2DF244CE4B4004AF00D /* Disk */; };
|
||||
B9839983233A086A002F9946 /* Overview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9839982233A086A002F9946 /* Overview.swift */; };
|
||||
B983998C233A0BC9002F9946 /* Cover+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4F522D1352F0029BFAD /* Cover+CoreDataClass.swift */; };
|
||||
B9839991233A0E16002F9946 /* GameSeriesCover+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9839985233A0ADB002F9946 /* GameSeriesCover+CoreDataProperties.swift */; };
|
||||
B9839992233A0E19002F9946 /* GameSeriesCover+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9839984233A0ADB002F9946 /* GameSeriesCover+CoreDataClass.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 */; };
|
||||
B98B2FAA2328DF3400606DC4 /* GameSeriesStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B98B2FA92328DF3400606DC4 /* GameSeriesStore.swift */; };
|
||||
B98B2FAC232C0F8C00606DC4 /* ImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B98B2FAB232C0F8C00606DC4 /* ImagePicker.swift */; };
|
||||
B98CBBD2264E933A00B1B7AC /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B98CBBD1264E933A00B1B7AC /* CloudKit.framework */; };
|
||||
B98CBBDA264E98DD00B1B7AC /* GameSeries+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B98CBBD7264E98DD00B1B7AC /* GameSeries+CoreDataProperties.swift */; };
|
||||
B98CBBDB264E98DE00B1B7AC /* Console+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B98CBBD8264E98DD00B1B7AC /* Console+CoreDataProperties.swift */; };
|
||||
B98CBBDC264E98DE00B1B7AC /* GameSeries+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B98CBBD9264E98DD00B1B7AC /* GameSeries+CoreDataClass.swift */; };
|
||||
B98CBBDD264E98F300B1B7AC /* Console+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4F922D1352F0029BFAD /* Console+CoreDataClass.swift */; };
|
||||
B9A0550122F8C22D0054D9A0 /* GameSeriesAllView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9A0550022F8C22D0054D9A0 /* GameSeriesAllView.swift */; };
|
||||
B9A0550322F8C2740054D9A0 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9A0550222F8C2740054D9A0 /* MainView.swift */; };
|
||||
B9A0550522F8CB400054D9A0 /* GameSeriesLibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9A0550422F8CB400054D9A0 /* GameSeriesLibraryView.swift */; };
|
||||
B9BCF4CA2168ACB600ECBAAC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B9BCF4C92168ACB600ECBAAC /* LaunchScreen.storyboard */; };
|
||||
B9D2C6F722E98ED800797F67 /* AccessoryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D2C6F622E98ED800797F67 /* AccessoryViewModel.swift */; };
|
||||
B9F002E52187AA3200E12B0A /* FlockeConnector.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F002E42187AA3200E12B0A /* FlockeConnector.swift */; };
|
||||
B9E2A079233B69D400EAEB14 /* GameSeriesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9E2A078233B69D400EAEB14 /* GameSeriesViewModel.swift */; };
|
||||
B9E2A07B233B6A8F00EAEB14 /* GameSeriesEditView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9E2A07A233B6A8F00EAEB14 /* GameSeriesEditView.swift */; };
|
||||
B9E2A07E233B6E4F00EAEB14 /* ConsoleAllView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9E2A07C233B6E4F00EAEB14 /* ConsoleAllView.swift */; };
|
||||
B9E2A081233BA62100EAEB14 /* FeaturedStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9E2A080233BA62100EAEB14 /* FeaturedStore.swift */; };
|
||||
B9EC09822383F94B004BC9AB /* LibraryExport.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9EC09812383F94B004BC9AB /* LibraryExport.swift */; };
|
||||
B9EC098523854C24004BC9AB /* QGrid in Frameworks */ = {isa = PBXBuildFile; productRef = B9EC098423854C24004BC9AB /* QGrid */; };
|
||||
B9EC0987238555BF004BC9AB /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9EC0986238555BF004BC9AB /* SettingsView.swift */; };
|
||||
B9F44ABA22F312E600FC6B29 /* ConsoleLibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AB922F312E600FC6B29 /* ConsoleLibraryView.swift */; };
|
||||
B9F44ABE22F31DEF00FC6B29 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44ABD22F31DEF00FC6B29 /* SceneDelegate.swift */; };
|
||||
B9F44AE322F3216F00FC6B29 /* ConsolesListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AE222F3216F00FC6B29 /* ConsolesListView.swift */; };
|
||||
B9F44AE522F418F600FC6B29 /* ConsoleStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AE422F418F600FC6B29 /* ConsoleStore.swift */; };
|
||||
B9F44AE722F429D300FC6B29 /* GameStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AE622F429D300FC6B29 /* GameStore.swift */; };
|
||||
B9F44AE922F4655600FC6B29 /* AccessoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AE822F4655600FC6B29 /* AccessoryStore.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
B983997A233A0295002F9946 /* Embed Watch Content */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Watch Content";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
B926F12C2149B264004D36B7 /* FlockeEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlockeEntry.swift; sourceTree = "<group>"; };
|
||||
B926F12E2149B6F5004D36B7 /* ConsoleLibraryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleLibraryViewController.swift; sourceTree = "<group>"; };
|
||||
B926F130214AD9E4004D36B7 /* GameCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameCollection.swift; sourceTree = "<group>"; };
|
||||
B926F138214AE884004D36B7 /* FlockeWS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlockeWS.swift; sourceTree = "<group>"; };
|
||||
B926F13B214C44FE004D36B7 /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
|
||||
B90E03EA238557D900E79643 /* LibraryImport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryImport.swift; sourceTree = "<group>"; };
|
||||
B926F14621502D53004D36B7 /* CodableExtensionAny.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableExtensionAny.swift; sourceTree = "<group>"; };
|
||||
B926F14921502DE1004D36B7 /* ConsoleEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleEntry.swift; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
B93C1BA321496BFE0014FD6E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
B93C1BA821496BFE0014FD6E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessoryDetailView.swift; sourceTree = "<group>"; };
|
||||
B93D60D022E5009700DD390F /* GameViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewModel.swift; sourceTree = "<group>"; };
|
||||
B94112DD233A37DD00159AE4 /* DateConversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateConversion.swift; sourceTree = "<group>"; };
|
||||
B94112DF233A4EF800159AE4 /* GamePickupsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamePickupsView.swift; sourceTree = "<group>"; };
|
||||
B94112E1233B55B100159AE4 /* ConsoleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleViewModel.swift; sourceTree = "<group>"; };
|
||||
B94112E3233B597D00159AE4 /* ConsoleEditView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleEditView.swift; sourceTree = "<group>"; };
|
||||
B94CB4F322D1352F0029BFAD /* Accessory+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Accessory+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
B94CB4F422D1352F0029BFAD /* Accessory+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Accessory+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
B94CB4F522D1352F0029BFAD /* Cover+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Cover+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
@@ -66,20 +92,35 @@
|
||||
B94CB4F822D1352F0029BFAD /* Game+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Game+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
B94CB4F922D1352F0029BFAD /* Console+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Console+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
B94CB4FA22D1352F0029BFAD /* Console+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Console+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
B94CB4FB22D1352F0029BFAD /* GameSeries+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GameSeries+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
B94CB4FC22D1352F0029BFAD /* GameSeries+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GameSeries+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
B94CB4FD22D1352F0029BFAD /* Logo+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logo+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
B94CB4FE22D1352F0029BFAD /* Logo+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Logo+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
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 = "<absolute>"; };
|
||||
B94CB53622D3B3CC0029BFAD /* GameDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameDetailView.swift; sourceTree = "<group>"; };
|
||||
B9839982233A086A002F9946 /* Overview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Overview.swift; sourceTree = "<group>"; };
|
||||
B9839984233A0ADB002F9946 /* GameSeriesCover+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GameSeriesCover+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
B9839985233A0ADB002F9946 /* GameSeriesCover+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GameSeriesCover+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
B98A731822BA9E4600FB3410 /* Zockerhoehle.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Zockerhoehle.xcdatamodel; sourceTree = "<group>"; };
|
||||
B98A735F22C1738800FB3410 /* CDManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CDManager.swift; sourceTree = "<group>"; };
|
||||
B98B2FA92328DF3400606DC4 /* GameSeriesStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameSeriesStore.swift; sourceTree = "<group>"; };
|
||||
B98B2FAB232C0F8C00606DC4 /* ImagePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePicker.swift; sourceTree = "<group>"; };
|
||||
B98CBBD0264E933400B1B7AC /* Zockerhoehle.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Zockerhoehle.entitlements; sourceTree = "<group>"; };
|
||||
B98CBBD1264E933A00B1B7AC /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
|
||||
B98CBBD7264E98DD00B1B7AC /* GameSeries+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GameSeries+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
B98CBBD8264E98DD00B1B7AC /* Console+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Console+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
B98CBBD9264E98DD00B1B7AC /* GameSeries+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GameSeries+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
B9A0550022F8C22D0054D9A0 /* GameSeriesAllView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameSeriesAllView.swift; sourceTree = "<group>"; };
|
||||
B9A0550222F8C2740054D9A0 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
||||
B9A0550422F8CB400054D9A0 /* GameSeriesLibraryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameSeriesLibraryView.swift; sourceTree = "<group>"; };
|
||||
B9BCF4C92168ACB600ECBAAC /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
B9D2C6F622E98ED800797F67 /* AccessoryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessoryViewModel.swift; sourceTree = "<group>"; };
|
||||
B9F002E42187AA3200E12B0A /* FlockeConnector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlockeConnector.swift; sourceTree = "<group>"; };
|
||||
B9E2A078233B69D400EAEB14 /* GameSeriesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameSeriesViewModel.swift; sourceTree = "<group>"; };
|
||||
B9E2A07A233B6A8F00EAEB14 /* GameSeriesEditView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameSeriesEditView.swift; sourceTree = "<group>"; };
|
||||
B9E2A07C233B6E4F00EAEB14 /* ConsoleAllView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConsoleAllView.swift; sourceTree = "<group>"; };
|
||||
B9E2A080233BA62100EAEB14 /* FeaturedStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeaturedStore.swift; sourceTree = "<group>"; };
|
||||
B9EC09812383F94B004BC9AB /* LibraryExport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryExport.swift; sourceTree = "<group>"; };
|
||||
B9EC0986238555BF004BC9AB /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
B9F44AB922F312E600FC6B29 /* ConsoleLibraryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleLibraryView.swift; sourceTree = "<group>"; };
|
||||
B9F44ABD22F31DEF00FC6B29 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
B9F44AE222F3216F00FC6B29 /* ConsolesListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsolesListView.swift; sourceTree = "<group>"; };
|
||||
B9F44AE422F418F600FC6B29 /* ConsoleStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleStore.swift; sourceTree = "<group>"; };
|
||||
B9F44AE622F429D300FC6B29 /* GameStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameStore.swift; sourceTree = "<group>"; };
|
||||
B9F44AE822F4655600FC6B29 /* AccessoryStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessoryStore.swift; sourceTree = "<group>"; };
|
||||
@@ -90,6 +131,9 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B98CBBD2264E933A00B1B7AC /* CloudKit.framework in Frameworks */,
|
||||
B9EC098523854C24004BC9AB /* QGrid in Frameworks */,
|
||||
B97AD2E0244CE4B4004AF00D /* Disk in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -99,36 +143,26 @@
|
||||
B90B64A12235909900E54BA3 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B98CBBD1264E933A00B1B7AC /* CloudKit.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B926F134214AE2C0004D36B7 /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B926F130214AD9E4004D36B7 /* GameCollection.swift */,
|
||||
B926F13B214C44FE004D36B7 /* Attachment.swift */,
|
||||
B926F12C2149B264004D36B7 /* FlockeEntry.swift */,
|
||||
B926F14921502DE1004D36B7 /* ConsoleEntry.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B926F135214AE2D4004D36B7 /* ViewController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B926F12E2149B6F5004D36B7 /* ConsoleLibraryViewController.swift */,
|
||||
);
|
||||
path = ViewController;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B926F136214AE2E3004D36B7 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B94CB53622D3B3CC0029BFAD /* GameDetailView.swift */,
|
||||
B9E2A07A233B6A8F00EAEB14 /* GameSeriesEditView.swift */,
|
||||
B9A0550422F8CB400054D9A0 /* GameSeriesLibraryView.swift */,
|
||||
B9A0550022F8C22D0054D9A0 /* GameSeriesAllView.swift */,
|
||||
B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */,
|
||||
B94CB53622D3B3CC0029BFAD /* GameDetailView.swift */,
|
||||
B94112E3233B597D00159AE4 /* ConsoleEditView.swift */,
|
||||
B9F44AB922F312E600FC6B29 /* ConsoleLibraryView.swift */,
|
||||
B9F44AE222F3216F00FC6B29 /* ConsolesListView.swift */,
|
||||
B9E2A07C233B6E4F00EAEB14 /* ConsoleAllView.swift */,
|
||||
B94112DF233A4EF800159AE4 /* GamePickupsView.swift */,
|
||||
B9A0550222F8C2740054D9A0 /* MainView.swift */,
|
||||
B9EC0986238555BF004BC9AB /* SettingsView.swift */,
|
||||
B9839982233A086A002F9946 /* Overview.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@@ -136,20 +170,15 @@
|
||||
B926F13A214AF21B004D36B7 /* Utils */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B926F138214AE884004D36B7 /* FlockeWS.swift */,
|
||||
B9F002E42187AA3200E12B0A /* FlockeConnector.swift */,
|
||||
B926F14621502D53004D36B7 /* CodableExtensionAny.swift */,
|
||||
B94112DD233A37DD00159AE4 /* DateConversion.swift */,
|
||||
B98B2FAB232C0F8C00606DC4 /* ImagePicker.swift */,
|
||||
B9EC09812383F94B004BC9AB /* LibraryExport.swift */,
|
||||
B90E03EA238557D900E79643 /* LibraryImport.swift */,
|
||||
);
|
||||
path = Utils;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B926F14821502D7F004D36B7 /* Lib */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B926F14621502D53004D36B7 /* CodableExtensionAny.swift */,
|
||||
);
|
||||
path = Lib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B93C1B9021496BFD0014FD6E = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -171,13 +200,11 @@
|
||||
B93C1B9B21496BFD0014FD6E /* Zockerhoehle */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B98CBBD0264E933400B1B7AC /* Zockerhoehle.entitlements */,
|
||||
B93D60CF22E5006F00DD390F /* ViewModel */,
|
||||
B98A734622BACA9C00FB3410 /* CDModel */,
|
||||
B926F14821502D7F004D36B7 /* Lib */,
|
||||
B926F13A214AF21B004D36B7 /* Utils */,
|
||||
B926F136214AE2E3004D36B7 /* Views */,
|
||||
B926F135214AE2D4004D36B7 /* ViewController */,
|
||||
B926F134214AE2C0004D36B7 /* Model */,
|
||||
B93C1B9C21496BFD0014FD6E /* AppDelegate.swift */,
|
||||
B9F44ABD22F31DEF00FC6B29 /* SceneDelegate.swift */,
|
||||
B9BCF4C92168ACB600ECBAAC /* LaunchScreen.storyboard */,
|
||||
@@ -192,11 +219,15 @@
|
||||
B93D60CF22E5006F00DD390F /* ViewModel */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B94112E1233B55B100159AE4 /* ConsoleViewModel.swift */,
|
||||
B93D60D022E5009700DD390F /* GameViewModel.swift */,
|
||||
B9E2A078233B69D400EAEB14 /* GameSeriesViewModel.swift */,
|
||||
B9D2C6F622E98ED800797F67 /* AccessoryViewModel.swift */,
|
||||
B9F44AE422F418F600FC6B29 /* ConsoleStore.swift */,
|
||||
B9F44AE622F429D300FC6B29 /* GameStore.swift */,
|
||||
B9F44AE822F4655600FC6B29 /* AccessoryStore.swift */,
|
||||
B98B2FA92328DF3400606DC4 /* GameSeriesStore.swift */,
|
||||
B9E2A080233BA62100EAEB14 /* FeaturedStore.swift */,
|
||||
);
|
||||
path = ViewModel;
|
||||
sourceTree = "<group>";
|
||||
@@ -204,6 +235,11 @@
|
||||
B98A734622BACA9C00FB3410 /* CDModel */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B98CBBD8264E98DD00B1B7AC /* Console+CoreDataProperties.swift */,
|
||||
B98CBBD9264E98DD00B1B7AC /* GameSeries+CoreDataClass.swift */,
|
||||
B98CBBD7264E98DD00B1B7AC /* GameSeries+CoreDataProperties.swift */,
|
||||
B9839984233A0ADB002F9946 /* GameSeriesCover+CoreDataClass.swift */,
|
||||
B9839985233A0ADB002F9946 /* GameSeriesCover+CoreDataProperties.swift */,
|
||||
B94CB4F322D1352F0029BFAD /* Accessory+CoreDataClass.swift */,
|
||||
B94CB4F422D1352F0029BFAD /* Accessory+CoreDataProperties.swift */,
|
||||
B94CB4F522D1352F0029BFAD /* Cover+CoreDataClass.swift */,
|
||||
@@ -212,8 +248,6 @@
|
||||
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 */,
|
||||
);
|
||||
@@ -231,12 +265,17 @@
|
||||
B93C1B9621496BFD0014FD6E /* Frameworks */,
|
||||
B93C1B9721496BFD0014FD6E /* Resources */,
|
||||
B90B64A4223590DA00E54BA3 /* ShellScript */,
|
||||
B983997A233A0295002F9946 /* Embed Watch Content */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Zockerhoehle;
|
||||
packageProductDependencies = (
|
||||
B9EC098423854C24004BC9AB /* QGrid */,
|
||||
B97AD2DF244CE4B4004AF00D /* Disk */,
|
||||
);
|
||||
productName = Zockerhoehle;
|
||||
productReference = B93C1B9921496BFD0014FD6E /* Zockerhoehle.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
@@ -247,8 +286,8 @@
|
||||
B93C1B9121496BFD0014FD6E /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0940;
|
||||
LastUpgradeCheck = 0940;
|
||||
LastSwiftUpdateCheck = 1100;
|
||||
LastUpgradeCheck = 1250;
|
||||
ORGANIZATIONNAME = "Julian-Steffen Müller";
|
||||
TargetAttributes = {
|
||||
B93C1B9821496BFD0014FD6E = {
|
||||
@@ -266,6 +305,10 @@
|
||||
Base,
|
||||
);
|
||||
mainGroup = B93C1B9021496BFD0014FD6E;
|
||||
packageReferences = (
|
||||
B9EC098323854C24004BC9AB /* XCRemoteSwiftPackageReference "QGrid" */,
|
||||
B97AD2DE244CE4B4004AF00D /* XCRemoteSwiftPackageReference "Disk" */,
|
||||
);
|
||||
productRefGroup = B93C1B9A21496BFD0014FD6E /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
@@ -296,7 +339,6 @@
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(SRCROOT)/Carthage/Build/iOS/Disk.framework",
|
||||
);
|
||||
outputFileListPaths = (
|
||||
);
|
||||
@@ -304,7 +346,8 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/usr/local/bin/carthage copy-frameworks\n";
|
||||
shellScript = "
|
||||
";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
@@ -313,39 +356,50 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B926F139214AE884004D36B7 /* FlockeWS.swift in Sources */,
|
||||
B926F13C214C44FE004D36B7 /* Attachment.swift in Sources */,
|
||||
B98CBBDD264E98F300B1B7AC /* Console+CoreDataClass.swift in Sources */,
|
||||
B98CBBDB264E98DE00B1B7AC /* Console+CoreDataProperties.swift in Sources */,
|
||||
B98B2FAA2328DF3400606DC4 /* GameSeriesStore.swift in Sources */,
|
||||
B9839991233A0E16002F9946 /* GameSeriesCover+CoreDataProperties.swift in Sources */,
|
||||
B983998C233A0BC9002F9946 /* Cover+CoreDataClass.swift in Sources */,
|
||||
B9839992233A0E19002F9946 /* GameSeriesCover+CoreDataClass.swift in Sources */,
|
||||
B94112E0233A4EF800159AE4 /* GamePickupsView.swift in Sources */,
|
||||
B94112E2233B55B100159AE4 /* ConsoleViewModel.swift in Sources */,
|
||||
B9A0550522F8CB400054D9A0 /* GameSeriesLibraryView.swift in Sources */,
|
||||
B9839983233A086A002F9946 /* Overview.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 */,
|
||||
B98B2FAC232C0F8C00606DC4 /* ImagePicker.swift in Sources */,
|
||||
B9F44ABA22F312E600FC6B29 /* ConsoleLibraryView.swift in Sources */,
|
||||
B9F44ABE22F31DEF00FC6B29 /* SceneDelegate.swift in Sources */,
|
||||
B9A0550322F8C2740054D9A0 /* MainView.swift in Sources */,
|
||||
B9D2C6F722E98ED800797F67 /* AccessoryViewModel.swift in Sources */,
|
||||
B9F002E52187AA3200E12B0A /* FlockeConnector.swift in Sources */,
|
||||
B98CBBDA264E98DD00B1B7AC /* GameSeries+CoreDataProperties.swift in Sources */,
|
||||
B94CB50A22D1352F0029BFAD /* Logo+CoreDataProperties.swift in Sources */,
|
||||
B94CB4FF22D1352F0029BFAD /* Accessory+CoreDataClass.swift in Sources */,
|
||||
B98A734D22BAD27D00FB3410 /* Zockerhoehle.xcdatamodeld in Sources */,
|
||||
B93D60D122E5009700DD390F /* GameViewModel.swift in Sources */,
|
||||
B9F44AE722F429D300FC6B29 /* GameStore.swift in Sources */,
|
||||
B926F12D2149B264004D36B7 /* FlockeEntry.swift in Sources */,
|
||||
B98A735E22BFAA4B00FB3410 /* ConsoleLibraryViewController.swift in Sources */,
|
||||
B94CB50522D1352F0029BFAD /* Console+CoreDataClass.swift in Sources */,
|
||||
B90E03EB238557D900E79643 /* LibraryImport.swift in Sources */,
|
||||
B94CB50922D1352F0029BFAD /* Logo+CoreDataClass.swift in Sources */,
|
||||
B94CB50622D1352F0029BFAD /* Console+CoreDataProperties.swift in Sources */,
|
||||
B926F131214AD9E4004D36B7 /* GameCollection.swift in Sources */,
|
||||
B98CBBDC264E98DE00B1B7AC /* GameSeries+CoreDataClass.swift in Sources */,
|
||||
B9A0550122F8C22D0054D9A0 /* GameSeriesAllView.swift in Sources */,
|
||||
B94112E4233B597D00159AE4 /* ConsoleEditView.swift in Sources */,
|
||||
B94112DE233A37DD00159AE4 /* DateConversion.swift in Sources */,
|
||||
B9E2A081233BA62100EAEB14 /* FeaturedStore.swift in Sources */,
|
||||
B93D60CE22D88F5700DD390F /* AccessoryDetailView.swift in Sources */,
|
||||
B926F14A21502DE1004D36B7 /* ConsoleEntry.swift in Sources */,
|
||||
B94CB50722D1352F0029BFAD /* GameSeries+CoreDataClass.swift in Sources */,
|
||||
B9EC09822383F94B004BC9AB /* LibraryExport.swift in Sources */,
|
||||
B94CB50022D1352F0029BFAD /* Accessory+CoreDataProperties.swift in Sources */,
|
||||
B9E2A07B233B6A8F00EAEB14 /* GameSeriesEditView.swift in Sources */,
|
||||
B926F14721502D53004D36B7 /* CodableExtensionAny.swift in Sources */,
|
||||
B94CB50422D1352F0029BFAD /* Game+CoreDataProperties.swift in Sources */,
|
||||
B9F44AE922F4655600FC6B29 /* AccessoryStore.swift in Sources */,
|
||||
B98A736022C1738800FB3410 /* CDManager.swift in Sources */,
|
||||
B94CB50222D1352F0029BFAD /* Cover+CoreDataProperties.swift in Sources */,
|
||||
B9F44AE322F3216F00FC6B29 /* ConsolesListView.swift in Sources */,
|
||||
B94CB50122D1352F0029BFAD /* Cover+CoreDataClass.swift in Sources */,
|
||||
B9E2A07E233B6E4F00EAEB14 /* ConsoleAllView.swift in Sources */,
|
||||
B9EC0987238555BF004BC9AB /* SettingsView.swift in Sources */,
|
||||
B9F44AE522F418F600FC6B29 /* ConsoleStore.swift in Sources */,
|
||||
B9E2A079233B69D400EAEB14 /* GameSeriesViewModel.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -379,6 +433,7 @@
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
@@ -440,6 +495,7 @@
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
@@ -472,10 +528,10 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "";
|
||||
CODE_SIGN_ENTITLEMENTS = Zockerhoehle/Zockerhoehle.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = M9N7K3KZX9;
|
||||
DEVELOPMENT_TEAM = 85J8CBD673;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Carthage/Build/iOS",
|
||||
@@ -485,7 +541,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "de.mm-neuemedien.Zockerhoehle";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = haus.mueller.zockerhoehle;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -497,7 +553,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "";
|
||||
CODE_SIGN_ENTITLEMENTS = Zockerhoehle/Zockerhoehle.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = M9N7K3KZX9;
|
||||
@@ -510,7 +566,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "de.mm-neuemedien.Zockerhoehle";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = haus.mueller.zockerhoehle;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -541,6 +597,38 @@
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
B97AD2DE244CE4B4004AF00D /* XCRemoteSwiftPackageReference "Disk" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/saoudrizwan/Disk";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.6.4;
|
||||
};
|
||||
};
|
||||
B9EC098323854C24004BC9AB /* XCRemoteSwiftPackageReference "QGrid" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/Q-Mobile/QGrid";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 0.1.3;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
B97AD2DF244CE4B4004AF00D /* Disk */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = B97AD2DE244CE4B4004AF00D /* XCRemoteSwiftPackageReference "Disk" */;
|
||||
productName = Disk;
|
||||
};
|
||||
B9EC098423854C24004BC9AB /* QGrid */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = B9EC098323854C24004BC9AB /* XCRemoteSwiftPackageReference "QGrid" */;
|
||||
productName = QGrid;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
|
||||
/* Begin XCVersionGroup section */
|
||||
B98A731722BA9E4600FB3410 /* Zockerhoehle.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Zockerhoehle.xcodeproj">
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"object": {
|
||||
"pins": [
|
||||
{
|
||||
"package": "Disk",
|
||||
"repositoryURL": "https://github.com/saoudrizwan/Disk",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "b0cb4fdf23e51849cc2460bdc6de795c3bcca99d",
|
||||
"version": "0.6.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "QGrid",
|
||||
"repositoryURL": "https://github.com/Q-Mobile/QGrid",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "40607aec336a8097c94bcadb81762592d89073ac",
|
||||
"version": "0.1.3"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -14,6 +14,16 @@
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>ZockerhoehleWatch (Notification).xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
<key>ZockerhoehleWatch.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
|
||||
@@ -23,8 +23,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
#endif
|
||||
|
||||
print("disFinishLaunchung")
|
||||
FlockeWS.fetchEntries(for: GameCollection.consoleID)
|
||||
|
||||
//FlockeWS.fetchEntries(for: GameCollection.consoleID)
|
||||
|
||||
//TODO Game Serien entfernen
|
||||
/*let gameSeriesEntities = ["Assasins Creed", "Mario", "Zelda", "Pikmin", "Heroes of Might and Magic", "Gears of War"]
|
||||
|
||||
for series in gameSeriesEntities {
|
||||
let cdSeries = GameSeries(context: CDManager.shared.viewContext)@
|
||||
cdSeries.uuid = UUID()
|
||||
cdSeries.name = series
|
||||
}*/
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 KiB |
@@ -2,7 +2,7 @@
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "star.png",
|
||||
"filename" : "Image.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
BIN
Zockerhoehle/Assets.xcassets/digitalGame.imageset/Image.png
vendored
Normal file
BIN
Zockerhoehle/Assets.xcassets/digitalGame.imageset/Image.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
Zockerhoehle/Assets.xcassets/star.imageset/star.png
vendored
BIN
Zockerhoehle/Assets.xcassets/star.imageset/star.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
@@ -2,15 +2,16 @@
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "basket-supermarket.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Image.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Image-1.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
BIN
Zockerhoehle/Assets.xcassets/wishlist.imageset/Image-1.png
vendored
Normal file
BIN
Zockerhoehle/Assets.xcassets/wishlist.imageset/Image-1.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
BIN
Zockerhoehle/Assets.xcassets/wishlist.imageset/Image.png
vendored
Normal file
BIN
Zockerhoehle/Assets.xcassets/wishlist.imageset/Image.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
@@ -26,7 +26,8 @@ class CDManager {
|
||||
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")
|
||||
let container = NSPersistentCloudKitContainer(name: "Zockerhoehle")
|
||||
|
||||
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
|
||||
if let error = error as NSError? {
|
||||
// Replace this implementation with code to handle the error appropriately.
|
||||
@@ -43,6 +44,7 @@ class CDManager {
|
||||
fatalError("Unresolved error \(error), \(error.userInfo)")
|
||||
}
|
||||
})
|
||||
container.viewContext.automaticallyMergesChangesFromParent = true
|
||||
return container
|
||||
}()
|
||||
|
||||
@@ -53,10 +55,13 @@ class CDManager {
|
||||
// MARK: - Core Data Saving support
|
||||
|
||||
func saveContext () {
|
||||
persistentContainer.performBackgroundTask({(context) in
|
||||
print("CHANGES: \(self.persistentContainer.viewContext.hasChanges)")
|
||||
self.persistentContainer.performBackgroundTask({(context) in
|
||||
print("Context \(context.hasChanges)")
|
||||
if context.hasChanges {
|
||||
do {
|
||||
try context.save()
|
||||
print("--------------------saved-------")
|
||||
} 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.
|
||||
|
||||
@@ -18,3 +18,37 @@ public class Accessory: NSManagedObject, Identifiable {
|
||||
return fetchRequest
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@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?
|
||||
@NSManaged public var lentTo : String?
|
||||
@NSManaged public var uuid : UUID
|
||||
*/
|
||||
|
||||
extension Accessory : Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case color
|
||||
case manufacturer
|
||||
case name
|
||||
case inWishlist
|
||||
case console
|
||||
case lentTo
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(uuid, forKey: .uuid)
|
||||
try container.encode(color, forKey: .color)
|
||||
try container.encode(manufacturer, forKey: .manufacturer)
|
||||
try container.encode(name, forKey: .name)
|
||||
try container.encode(inWishlist, forKey: .inWishlist)
|
||||
try container.encode(console?.uuid!.uuidString ?? "", forKey: .console)
|
||||
try container.encode(lentTo, forKey: .lentTo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,5 +22,7 @@ extension Accessory {
|
||||
@NSManaged public var name: String
|
||||
@NSManaged public var inWishlist: Bool
|
||||
@NSManaged public var console: Console?
|
||||
@NSManaged public var lentTo : String?
|
||||
@NSManaged public var uuid : UUID
|
||||
|
||||
}
|
||||
|
||||
@@ -9,14 +9,96 @@
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
@objc(Console)
|
||||
public class Console: NSManagedObject, Identifiable {
|
||||
|
||||
var logoAsUIImage : UIImage? {
|
||||
get {
|
||||
if let logoImage = self.logo?.image {
|
||||
return logoImage
|
||||
}
|
||||
|
||||
return .none
|
||||
}
|
||||
|
||||
set {
|
||||
if let logoImage = newValue {
|
||||
let newLogo = Logo(context: CDManager.shared.viewContext)
|
||||
newLogo.console = self
|
||||
newLogo.image = logoImage
|
||||
self.logo = newLogo
|
||||
}/*else{
|
||||
//This deletes the cover?
|
||||
if let logo = self.logo {
|
||||
print("Console::logoImage::set DELETE Logo")
|
||||
CDManager.shared.viewContext.delete(logo)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
public static func sortConsoleByNewestGame(consoleA : Console, consoleB : Console) -> Bool {
|
||||
guard let newestGameConsoleA = (consoleA.games!.allObjects as! [Game]).max(by:{
|
||||
Game.compareByCreationDate(gameA: $0, gameB: $1)
|
||||
}) else { return false }
|
||||
guard let newestGameConsoleB = (consoleB.games!.allObjects as! [Game]).max(by:{
|
||||
Game.compareByCreationDate(gameA: $0, gameB: $1)
|
||||
}) else { return false }
|
||||
|
||||
guard let gameACreated = newestGameConsoleA.createdAt else { return true }
|
||||
guard let gameBCreated = newestGameConsoleB.createdAt else { return false }
|
||||
|
||||
return gameACreated > gameBCreated
|
||||
}
|
||||
|
||||
public var id : NSManagedObjectID {
|
||||
get {
|
||||
return self.objectID
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension Console : Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case name
|
||||
case shortName
|
||||
case generation
|
||||
case manufacturer
|
||||
case accessories
|
||||
case games
|
||||
case logo
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(uuid, forKey: .uuid)
|
||||
try container.encode(name, forKey: .name)
|
||||
try container.encode(shortName ?? "", forKey: .shortName)
|
||||
try container.encode(generation, forKey: .generation)
|
||||
try container.encode(manufacturer ?? "", forKey: .manufacturer)
|
||||
|
||||
var accessoryList : [String] = []
|
||||
for accessory in accessories! {
|
||||
if let accessory = accessory as? Accessory {
|
||||
accessoryList.append(accessory.uuid.uuidString)
|
||||
}
|
||||
}
|
||||
try container.encode(accessoryList, forKey: .accessories)
|
||||
|
||||
var gamesList : [String] = []
|
||||
for game in games! {
|
||||
if let game = game as? Game {
|
||||
gamesList.append(game.uuid!.uuidString)
|
||||
}
|
||||
}
|
||||
try container.encode(gamesList, forKey: .games)
|
||||
|
||||
let logoBase64 = logo?.image?.pngData()?.base64EncodedString() ?? ""
|
||||
try container.encode(logoBase64, forKey: .logo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Console+CoreDataProperties.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 06.07.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
// Created by Julian-Steffen Müller on 14.05.21.
|
||||
// Copyright © 2021 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
@@ -17,11 +17,14 @@ extension Console {
|
||||
return NSFetchRequest<Console>(entityName: "Console")
|
||||
}
|
||||
|
||||
@NSManaged public var circumstances: String?
|
||||
@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 name: String?
|
||||
@NSManaged public var shortName: String?
|
||||
@NSManaged public var uuid: UUID?
|
||||
@NSManaged public var accessories: NSSet?
|
||||
@NSManaged public var games: NSSet?
|
||||
@NSManaged public var logo: Logo?
|
||||
|
||||
}
|
||||
|
||||
@@ -12,5 +12,4 @@ import CoreData
|
||||
|
||||
@objc(Cover)
|
||||
public class Cover: NSManagedObject {
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@ extension Cover {
|
||||
}
|
||||
|
||||
@NSManaged public var image: UIImage?
|
||||
@NSManaged public var game: Game?
|
||||
@NSManaged public var game: Game
|
||||
|
||||
}
|
||||
|
||||
@@ -19,4 +19,78 @@ public class Game: NSManagedObject, Identifiable {
|
||||
return fetchRequest
|
||||
}
|
||||
|
||||
@nonobjc public class func fetchRequest(gameSeries : GameSeries) -> NSFetchRequest<Game> {
|
||||
let fetchRequest = NSFetchRequest<Game>(entityName: "Game")
|
||||
fetchRequest.predicate = NSPredicate(format: "series == %@", gameSeries)
|
||||
return fetchRequest
|
||||
}
|
||||
|
||||
public func addGameSeries(by objectIDStringified : String) {
|
||||
if let url = URL(string: objectIDStringified) {
|
||||
let persistentStoreCoordinator = CDManager.shared.persistentContainer.persistentStoreCoordinator
|
||||
|
||||
if let objectID = persistentStoreCoordinator.managedObjectID(forURIRepresentation: url) {
|
||||
if let gameSeries = CDManager.shared.viewContext.object(with: objectID) as? GameSeries {
|
||||
self.series = gameSeries
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static func compareByCreationDate(gameA : Game, gameB : Game) -> Bool {
|
||||
guard let gameACreated = gameA.createdAt else { return true }
|
||||
guard let gameBCreated = gameB.createdAt else { return false }
|
||||
|
||||
return gameACreated < gameBCreated
|
||||
}
|
||||
|
||||
init(context: NSManagedObjectContext) {
|
||||
super.init(entity: Game.entity(), insertInto: context)
|
||||
|
||||
if self.createdAt == .none {
|
||||
self.createdAt = Date()
|
||||
}
|
||||
}
|
||||
@objc
|
||||
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
|
||||
super.init(entity: entity, insertInto: context)
|
||||
}
|
||||
}
|
||||
|
||||
extension Game : Encodable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case name
|
||||
case notes
|
||||
case isDigital
|
||||
case lentTo
|
||||
case createdAt
|
||||
case publisher
|
||||
case isFinished
|
||||
case inWishlist
|
||||
case console
|
||||
case gameSeries
|
||||
case cover
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(uuid, forKey: .uuid)
|
||||
try container.encode(name, forKey: .name)
|
||||
try container.encode(notes ?? "", forKey: .notes)
|
||||
try container.encode(isDigital, forKey: .isDigital)
|
||||
try container.encode(lentTo ?? "", forKey: .lentTo)
|
||||
try container.encode(createdAt?.formattedInTimeZone(), forKey: .createdAt)
|
||||
try container.encode(publisher ?? "", forKey: .publisher)
|
||||
try container.encode(isFinished, forKey: .isFinished)
|
||||
try container.encode(inWishlist, forKey: .inWishlist)
|
||||
|
||||
let consoleUUID : String = console?.uuid?.uuidString ?? ""
|
||||
let gameSeriesUUID : String = series?.uuid.uuidString ?? ""
|
||||
try container.encode(consoleUUID, forKey: .console)
|
||||
try container.encode(gameSeriesUUID, forKey: .gameSeries)
|
||||
|
||||
let imgBase64 = cover?.image?.pngData()?.base64EncodedString() ?? ""
|
||||
try container.encode(imgBase64, forKey: .cover)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Game+CoreDataProperties.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 06.07.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
// Created by Julian-Steffen Müller on 14.05.21.
|
||||
// Copyright © 2021 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
@@ -11,20 +11,24 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
extension Game{
|
||||
extension Game {
|
||||
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<Game> {
|
||||
return NSFetchRequest<Game>(entityName: "Game")
|
||||
}
|
||||
|
||||
@NSManaged public var isFinished: Bool
|
||||
@NSManaged public var circumstances: String?
|
||||
@NSManaged public var createdAt: Date?
|
||||
@NSManaged public var inWishlist: Bool
|
||||
@NSManaged public var isDigital: Bool
|
||||
@NSManaged public var name: String
|
||||
@NSManaged public var isFinished: Bool
|
||||
@NSManaged public var lentTo: String?
|
||||
@NSManaged public var name: String?
|
||||
@NSManaged public var notes: String?
|
||||
@NSManaged public var publisher: String?
|
||||
@NSManaged public var uuid: UUID?
|
||||
@NSManaged public var console: Console?
|
||||
@NSManaged public var series: GameSeries?
|
||||
@NSManaged public var cover: Cover?
|
||||
@NSManaged public var series: GameSeries?
|
||||
|
||||
}
|
||||
|
||||
@@ -2,15 +2,65 @@
|
||||
// GameSeries+CoreDataClass.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 06.07.19.
|
||||
// Created by Julian-Steffen Müller on 24.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
import UIKit
|
||||
|
||||
@objc(GameSeries)
|
||||
public class GameSeries: NSManagedObject {
|
||||
public class GameSeries: NSManagedObject, Identifiable {
|
||||
|
||||
public var id : String {
|
||||
return objectID.uriRepresentation().absoluteString
|
||||
}
|
||||
|
||||
var coverAsUIImage : UIImage? {
|
||||
get {
|
||||
if let coverImage = self.cover?.image {
|
||||
return coverImage
|
||||
}
|
||||
|
||||
return .none
|
||||
}
|
||||
|
||||
set {
|
||||
if let coverImage = newValue {
|
||||
let newCover = GameSeriesCover(context: CDManager.shared.viewContext)
|
||||
newCover.gameSeries = self
|
||||
newCover.image = coverImage
|
||||
self.cover = newCover
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension GameSeries : Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case name
|
||||
case games
|
||||
case cover
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(uuid, forKey: .uuid)
|
||||
try container.encode(name, forKey: .name)
|
||||
|
||||
var gamesList : [String] = []
|
||||
for game in games {
|
||||
if let game = game as? Game {
|
||||
gamesList.append(game.objectID.uriRepresentation().absoluteString)
|
||||
}
|
||||
}
|
||||
try container.encode(gamesList, forKey: .games)
|
||||
|
||||
let coverBase64 = cover?.image?.pngData()?.base64EncodedString() ?? ""
|
||||
try container.encode(coverBase64, forKey: .cover)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// GameSeries+CoreDataProperties.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 06.07.19.
|
||||
// Created by Julian-Steffen Müller on 24.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
//
|
||||
@@ -17,9 +17,10 @@ extension GameSeries {
|
||||
return NSFetchRequest<GameSeries>(entityName: "GameSeries")
|
||||
}
|
||||
|
||||
@NSManaged public var cover: Data?
|
||||
@NSManaged public var name: String?
|
||||
@NSManaged public var name: String
|
||||
@NSManaged public var uuid : UUID
|
||||
@NSManaged public var games: NSSet
|
||||
@NSManaged public var cover: GameSeriesCover?
|
||||
|
||||
}
|
||||
|
||||
|
||||
16
Zockerhoehle/CDModel/GameSeriesCover+CoreDataClass.swift
Normal file
16
Zockerhoehle/CDModel/GameSeriesCover+CoreDataClass.swift
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// GameSeriesCover+CoreDataClass.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 24.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
@objc(GameSeriesCover)
|
||||
public class GameSeriesCover: NSManagedObject {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// GameSeriesCover+CoreDataProperties.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 24.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
import UIKit
|
||||
|
||||
extension GameSeriesCover {
|
||||
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<GameSeriesCover> {
|
||||
return NSFetchRequest<GameSeriesCover>(entityName: "GameSeriesCover")
|
||||
}
|
||||
|
||||
@NSManaged public var image: UIImage?
|
||||
@NSManaged public var gameSeries: GameSeries?
|
||||
|
||||
}
|
||||
@@ -20,6 +20,8 @@
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string></string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
@@ -46,6 +48,12 @@
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
//
|
||||
// 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"
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
var tmpConsole : Console? = .none
|
||||
for console in self.consoles {
|
||||
let cdConsole = Console(entity: Console.entity(), insertInto: cdm.viewContext)
|
||||
cdConsole.name = console.name
|
||||
|
||||
if cdConsole.name == "Nintendo Entertainment System" {
|
||||
tmpConsole = cdConsole
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guard let con = tmpConsole else {
|
||||
print("No Console")
|
||||
return
|
||||
}
|
||||
let fetchReq = NSFetchRequest<Game>(entityName: "Game")
|
||||
fetchReq.predicate = NSPredicate(format: "console=%@", con)
|
||||
do {
|
||||
let fetchRes = try CDManager.shared.viewContext.fetch(fetchReq)
|
||||
|
||||
for g in fetchRes {
|
||||
print("\(g.name)")
|
||||
}
|
||||
}catch {
|
||||
print(error)
|
||||
}
|
||||
|
||||
}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"
|
||||
}
|
||||
@@ -13,8 +13,8 @@ import SwiftUI
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate, UIApplicationDelegate {
|
||||
var window: UIWindow?
|
||||
|
||||
let gameStore = GameStore(console: .none)
|
||||
let consoleStore = ConsoleStore()
|
||||
let consolesStore = ConsoleStore()
|
||||
let gameSeriesStore = GameSeriesStore()
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||
@@ -24,8 +24,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UIApplicationDelegate {
|
||||
// Use a UIHostingController as window root view controller
|
||||
if let windowScene = scene as? UIWindowScene {
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
let view = ConsolesListView(gameStore: self.gameStore)
|
||||
window.rootViewController = UIHostingController(rootView: view)
|
||||
|
||||
window.rootViewController = UIHostingController(rootView: MainView()
|
||||
.environmentObject(self.gameSeriesStore)
|
||||
.environmentObject(self.consolesStore))
|
||||
self.window = window
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
|
||||
27
Zockerhoehle/Utils/DateConversion.swift
Normal file
27
Zockerhoehle/Utils/DateConversion.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// DateConversion.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 24.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Date {
|
||||
func formattedInTimeZone(timezone : TimeZone = .current) -> String {
|
||||
// 1) Create a DateFormatter() object.
|
||||
let format = DateFormatter()
|
||||
|
||||
// 2) Set the current timezone to .current, or America/Chicago.
|
||||
format.timeZone = timezone
|
||||
|
||||
// 3) Set the format of the altered date.
|
||||
format.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
||||
|
||||
// 4) Set the current date, altered by timezone.
|
||||
let dateString = format.string(from: self)
|
||||
|
||||
return dateString
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
//
|
||||
// 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)
|
||||
for console in consoles {
|
||||
FlockeWS.fetchEntries(for: console.id)
|
||||
|
||||
if let att = console.iconAttachment {
|
||||
FlockeWS.fetchAttachment(attachment: att.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
print("FLOCKEWS::fetchEntries; \(err?.localizedDescription ?? "N/A")")
|
||||
}
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
63
Zockerhoehle/Utils/ImagePicker.swift
Normal file
63
Zockerhoehle/Utils/ImagePicker.swift
Normal file
@@ -0,0 +1,63 @@
|
||||
import SwiftUI
|
||||
import Combine
|
||||
import UIKit
|
||||
|
||||
final class ImagePicker : ObservableObject {
|
||||
|
||||
static let shared : ImagePicker = ImagePicker()
|
||||
|
||||
private init() {} //force using the singleton: ImagePicker.shared
|
||||
let view = ImagePicker.View()
|
||||
let coordinator = ImagePicker.Coordinator()
|
||||
|
||||
// Bindable Object part
|
||||
let objectWillChange = PassthroughSubject<UIImage?, Never>()
|
||||
|
||||
var image: UIImage? = .none {
|
||||
didSet {
|
||||
objectWillChange.send(image)
|
||||
print("ImagePicker::image Image Changed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension ImagePicker {
|
||||
|
||||
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
|
||||
|
||||
// UIImagePickerControllerDelegate
|
||||
func imagePickerController(_ picker: UIImagePickerController,
|
||||
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
|
||||
let uiImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
|
||||
ImagePicker.shared.image = uiImage
|
||||
picker.dismiss(animated:true)
|
||||
}
|
||||
|
||||
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
|
||||
picker.dismiss(animated:true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct View: UIViewControllerRepresentable {
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
ImagePicker.shared.coordinator
|
||||
}
|
||||
|
||||
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker.View>) -> UIImagePickerController {
|
||||
let picker = UIImagePickerController()
|
||||
picker.delegate = context.coordinator
|
||||
|
||||
return picker
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: UIImagePickerController,
|
||||
context: UIViewControllerRepresentableContext<ImagePicker.View>) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
100
Zockerhoehle/Utils/LibraryExport.swift
Normal file
100
Zockerhoehle/Utils/LibraryExport.swift
Normal file
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// LibraryExport.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 19.11.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Compression
|
||||
|
||||
struct LibraryExporter : Encodable {
|
||||
private var games : [Game]
|
||||
private var consoles : [Console]
|
||||
private var gameSeries : [GameSeries]
|
||||
private var accessories : [Accessory]
|
||||
|
||||
init (games: [Game], consoles: [Console], gameSeries: [GameSeries], accessories : [Accessory]) {
|
||||
self.games = games
|
||||
self.consoles = consoles
|
||||
self.gameSeries = gameSeries
|
||||
self.accessories = accessories
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case games
|
||||
case consoles
|
||||
case gameSeries
|
||||
case accessories
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(games, forKey: .games)
|
||||
try container.encode(consoles, forKey: .consoles)
|
||||
try container.encode(gameSeries, forKey: .gameSeries)
|
||||
try container.encode(accessories, forKey: .accessories)
|
||||
}
|
||||
|
||||
func export() -> Data? {
|
||||
let jsonEncoder = JSONEncoder()
|
||||
|
||||
do {
|
||||
let exportJSON = try jsonEncoder.encode(self)
|
||||
return exportJSON
|
||||
}catch {
|
||||
return Data?.none
|
||||
}
|
||||
}
|
||||
|
||||
func export(name : String) {
|
||||
if let data = export() {
|
||||
//let exportFileName = "libExp_\(Date().formattedInTimeZone()).json"
|
||||
let exportFileName = "libExp_\(name).json"
|
||||
let byteCount = data.count // replace with data.count
|
||||
let bcf = ByteCountFormatter()
|
||||
bcf.allowedUnits = [.useMB] // optional: restricts the units to MB only
|
||||
bcf.countStyle = .file
|
||||
let fileSizeAsString = bcf.string(fromByteCount: Int64(byteCount))
|
||||
print("Exported Library to '\(exportFileName)' (Size: \(fileSizeAsString))")
|
||||
|
||||
do {
|
||||
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
|
||||
let encodedFileURL = documentDirectory.appendingPathComponent(exportFileName)
|
||||
|
||||
try data.write(to: encodedFileURL)
|
||||
}catch {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Currently python decoder missing 15 characters
|
||||
func exportCompressedZLIB() -> Data? {
|
||||
if let data = self.export() {
|
||||
let exportString = String(data: data, encoding: .utf8)!
|
||||
|
||||
var sourceBuffer = Array(exportString.utf8)
|
||||
let destinationBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: exportString.count)
|
||||
|
||||
let algorithm = COMPRESSION_ZLIB
|
||||
|
||||
let compressedSize = compression_encode_buffer(destinationBuffer, exportString.count,
|
||||
&sourceBuffer, exportString.count,
|
||||
nil,
|
||||
algorithm)
|
||||
|
||||
if compressedSize > 0 {
|
||||
let exportData = NSData(bytesNoCopy: destinationBuffer, length: compressedSize) as Data
|
||||
|
||||
return exportData
|
||||
}else {
|
||||
print("LibraryExport::exportCompressedZLIB - Compression failed 'compressedSite == 0'")
|
||||
return Data?.none
|
||||
}
|
||||
}
|
||||
|
||||
return Data?.none
|
||||
}
|
||||
}
|
||||
328
Zockerhoehle/Utils/LibraryImport.swift
Normal file
328
Zockerhoehle/Utils/LibraryImport.swift
Normal file
@@ -0,0 +1,328 @@
|
||||
//
|
||||
// LibraryImport.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 20.11.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import CoreData
|
||||
|
||||
// MARK: - Library Import
|
||||
|
||||
class LibraryImport {
|
||||
static func backupName(from filename : String) -> String? {
|
||||
if filename.hasPrefix("libExp_") && filename.hasSuffix(".json") {
|
||||
var backupName = filename
|
||||
backupName.removeFirst("libExp_".count)
|
||||
backupName.removeLast(".json".count)
|
||||
return backupName
|
||||
}else{
|
||||
return .none
|
||||
}
|
||||
}
|
||||
func backupFiles() -> [String] {
|
||||
do {
|
||||
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
|
||||
|
||||
let filesInDocumentsDir = try FileManager.default.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: .none, options: [])
|
||||
|
||||
let backupFiles = filesInDocumentsDir.filter{
|
||||
$0.isFileURL
|
||||
}.map {
|
||||
$0.lastPathComponent
|
||||
}.filter {
|
||||
$0.hasPrefix("libExp_") && $0.hasSuffix(".json")
|
||||
}.sorted(by: { $0 > $1 })
|
||||
|
||||
return backupFiles
|
||||
|
||||
}catch let error {
|
||||
print(error)
|
||||
print("LibraryImport::backupFiles - Error reading files from Document directory!")
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
private func resetDatabase() {
|
||||
print(GameSeriesStore().gameSeries)
|
||||
CDManager.shared.viewContext.reset()
|
||||
CDManager.shared.viewContext.performAndWait {
|
||||
let deleteRequests =
|
||||
[NSBatchDeleteRequest(fetchRequest: Game.fetchRequest()),
|
||||
NSBatchDeleteRequest(fetchRequest: Accessory.fetchRequest()),
|
||||
NSBatchDeleteRequest(fetchRequest: Console.fetchRequest()),
|
||||
NSBatchDeleteRequest(fetchRequest: GameSeries.fetchRequest()),
|
||||
NSBatchDeleteRequest(fetchRequest: Logo.fetchRequest()),
|
||||
NSBatchDeleteRequest(fetchRequest: Cover.fetchRequest())]
|
||||
|
||||
let storeCoordinator = CDManager.shared.persistentContainer.persistentStoreCoordinator
|
||||
do {
|
||||
for deleteRequest in deleteRequests {
|
||||
try storeCoordinator.execute(deleteRequest, with: CDManager.shared.viewContext)
|
||||
}
|
||||
}catch let error {
|
||||
print(error)
|
||||
print("LibraryImport::resetDatabase - Reset of Database failes!")
|
||||
}
|
||||
}
|
||||
print(GameSeriesStore().gameSeries)
|
||||
}
|
||||
|
||||
private func makeCDGame(from game: BHLGame, _ gameDict: inout [UUID : Game], _ cdConsole: Console) {
|
||||
let cdGame = Game(context: CDManager.shared.viewContext)
|
||||
gameDict[game.uuid] = cdGame
|
||||
cdGame.name = game.name
|
||||
cdGame.uuid = game.uuid
|
||||
cdGame.inWishlist = game.inWishlist
|
||||
cdGame.isFinished = game.isFinished
|
||||
cdGame.lentTo = game.lentTo
|
||||
//TODO: cdGame.createdAt = game.createdAt.
|
||||
|
||||
let cdCover = Cover(context: CDManager.shared.viewContext)
|
||||
cdCover.image = game.cover
|
||||
cdCover.game = cdGame
|
||||
cdGame.cover = cdCover
|
||||
|
||||
cdConsole.addToGames(cdGame)
|
||||
cdGame.console = cdConsole
|
||||
print("Imported: \(cdGame.name) for \(cdConsole.name)")
|
||||
}
|
||||
|
||||
private func makeCDAccessory(from accessory: BHLAccessory, _ accessoryDict: inout [UUID : Accessory], _ cdConsole: Console) {
|
||||
let cdAccessory = Accessory(context: CDManager.shared.viewContext)
|
||||
accessoryDict[accessory.uuid] = cdAccessory
|
||||
cdAccessory.name = accessory.name
|
||||
cdAccessory.uuid = accessory.uuid
|
||||
cdAccessory.lentTo = accessory.lentTo
|
||||
cdAccessory.color = accessory.color
|
||||
cdAccessory.manufacturer = accessory.manufacturer
|
||||
cdAccessory.inWishlist = accessory.inWishlist
|
||||
|
||||
cdConsole.addToAccessories(cdAccessory)
|
||||
cdAccessory.console = cdConsole
|
||||
}
|
||||
|
||||
private func makeCDConsole(from console : BHLConsole) -> Console {
|
||||
let cdConsole = Console(context: CDManager.shared.viewContext)
|
||||
cdConsole.name = console.name
|
||||
cdConsole.uuid = console.uuid
|
||||
cdConsole.manufacturer = console.manufacturer
|
||||
cdConsole.shortName = console.shortName
|
||||
cdConsole.generation = Int64(console.generation)
|
||||
|
||||
let cdLogo = Logo(context: CDManager.shared.viewContext)
|
||||
cdLogo.image = console.logo
|
||||
cdLogo.console = cdConsole
|
||||
cdConsole.logo = cdLogo
|
||||
|
||||
return cdConsole
|
||||
}
|
||||
|
||||
private func makeCDGameSeries(from gameSeries: BHLGameSeries, _ gameDict: inout [UUID : Game]) {
|
||||
let cdGameSeries = GameSeries(context: CDManager.shared.viewContext)
|
||||
cdGameSeries.name = gameSeries.name
|
||||
|
||||
let cdCover = GameSeriesCover(context: CDManager.shared.viewContext)
|
||||
cdCover.image = gameSeries.cover
|
||||
cdCover.gameSeries = cdGameSeries
|
||||
cdGameSeries.cover = cdCover
|
||||
|
||||
for uuid in gameSeries.games {
|
||||
if let game = gameDict[uuid] {
|
||||
cdGameSeries.addToGames(game)
|
||||
game.series = cdGameSeries
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func importLIB(from filename: String) {
|
||||
do {
|
||||
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
|
||||
|
||||
let file = documentDirectory.appendingPathComponent(filename)
|
||||
|
||||
if file.isFileURL {
|
||||
let library = try JSONDecoder().decode(BHLibrary.self, from: Data(contentsOf: file))
|
||||
|
||||
resetDatabase()
|
||||
|
||||
var gameDict = [UUID:Game]()
|
||||
var accessoryDict = [UUID:Accessory]()
|
||||
|
||||
for console in library.consoles {
|
||||
let cdConsole = makeCDConsole(from: console)
|
||||
|
||||
print("CONSOLE: \(cdConsole.name) with \(console.games.count) games")
|
||||
for uuid in console.games {
|
||||
|
||||
if let game = library.games.first(where: {$0.uuid == uuid}) {
|
||||
makeCDGame(from: game, &gameDict, cdConsole)
|
||||
}else{
|
||||
print("LibraryImport::importLIB - Game with UUID '\(uuid)' not found")
|
||||
}
|
||||
}
|
||||
|
||||
for uuid in console.accessories {
|
||||
if let accessory = library.accessories.first(where: {$0.uuid == uuid}) {
|
||||
makeCDAccessory(from: accessory, &accessoryDict, cdConsole)
|
||||
}else{
|
||||
print("LibraryImport::importLIB - Accessory with UUID '\(uuid)' not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for gameSeries in library.gameSeries {
|
||||
makeCDGameSeries(from: gameSeries, &gameDict)
|
||||
}
|
||||
}
|
||||
|
||||
}catch let error {
|
||||
print(error)
|
||||
print("LibraryImport::importLIB - Error while importing!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - BHLLibrary Classes
|
||||
|
||||
struct BHLibrary : Decodable {
|
||||
let games : [BHLGame]
|
||||
let consoles : [BHLConsole]
|
||||
let gameSeries : [BHLGameSeries]
|
||||
let accessories : [BHLAccessory]
|
||||
}
|
||||
|
||||
struct BHLGame : Decodable {
|
||||
let uuid : UUID
|
||||
let name : String
|
||||
let lentTo : String?
|
||||
let isDigital : Bool
|
||||
let inWishlist : Bool
|
||||
let isFinished : Bool
|
||||
let notes : String?
|
||||
let createdAt : String?
|
||||
let publisher : String?
|
||||
let console : UUID?
|
||||
let series : UUID?
|
||||
let cover : UIImage?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case name
|
||||
case lentTo
|
||||
case isDigital
|
||||
case inWishlist
|
||||
case isFinished
|
||||
case notes
|
||||
case createdAt
|
||||
case publisher
|
||||
case console
|
||||
case series
|
||||
case cover
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
uuid = try container.decode(UUID.self, forKey: .uuid)
|
||||
name = try container.decode(String.self, forKey: .name)
|
||||
lentTo = try container.decode(String?.self, forKey: .lentTo)
|
||||
isDigital = try container.decode(Bool.self, forKey: .isDigital)
|
||||
inWishlist = try container.decode(Bool.self, forKey: .inWishlist)
|
||||
isFinished = try container.decode(Bool.self, forKey: .isFinished)
|
||||
notes = try container.decode(String?.self, forKey: .notes)
|
||||
createdAt = try container.decode(String?.self, forKey: .notes)
|
||||
publisher = try container.decode(String?.self, forKey: .publisher)
|
||||
console = try container.decode(UUID?.self, forKey: .console)
|
||||
series = try container.decode(UUID?.self, forKey: .console)
|
||||
|
||||
|
||||
if let coverBase64 = try container.decode(String?.self, forKey: .cover),
|
||||
let coverData = Data(base64Encoded: coverBase64) {
|
||||
cover = UIImage(data: coverData)
|
||||
}else {
|
||||
cover = .none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BHLAccessory : Decodable {
|
||||
let uuid : UUID
|
||||
let name : String
|
||||
let color : String?
|
||||
let manufacturer : String?
|
||||
let inWishlist : Bool
|
||||
let lentTo : String?
|
||||
let console : UUID?
|
||||
}
|
||||
|
||||
struct BHLGameSeries : Decodable {
|
||||
let uuid : UUID
|
||||
let name : String
|
||||
let cover : UIImage?
|
||||
let games : [UUID]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case name
|
||||
case cover
|
||||
case games
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
uuid = try container.decode(UUID.self, forKey: .uuid)
|
||||
name = try container.decode(String.self, forKey: .name)
|
||||
games = try container.decode([UUID].self, forKey: .games)
|
||||
|
||||
if let coverBase64 = try container.decode(String?.self, forKey: .cover),
|
||||
let coverData = Data(base64Encoded: coverBase64) {
|
||||
cover = UIImage(data: coverData)
|
||||
}else {
|
||||
cover = .none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BHLConsole : Decodable {
|
||||
let uuid : UUID
|
||||
let name : String
|
||||
let logo : UIImage?
|
||||
let generation : Int
|
||||
let manufacturer : String?
|
||||
let shortName : String?
|
||||
let accessories : [UUID]
|
||||
let games : [UUID]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case name
|
||||
case logo
|
||||
case generation
|
||||
case manufacturer
|
||||
case shortName
|
||||
case accessories
|
||||
case games
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
uuid = try container.decode(UUID.self, forKey: .uuid)
|
||||
name = try container.decode(String.self, forKey: .name)
|
||||
generation = try container.decode(Int.self, forKey: .generation)
|
||||
manufacturer = try container.decode(String?.self, forKey: .manufacturer)
|
||||
shortName = try container.decode(String?.self, forKey: .shortName)
|
||||
accessories = try container.decode([UUID].self, forKey: .accessories)
|
||||
games = try container.decode([UUID].self, forKey: .games)
|
||||
|
||||
if let coverBase64 = try container.decode(String?.self, forKey: .logo),
|
||||
let coverData = Data(base64Encoded: coverBase64) {
|
||||
logo = UIImage(data: coverData)
|
||||
}else {
|
||||
logo = .none
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
//
|
||||
// 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<NSSet, Never>?
|
||||
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.isWishlist = self.showWishlist
|
||||
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)
|
||||
|
||||
var actions : [UIContextualAction] = []
|
||||
if (self.showWishlist) {
|
||||
actions.append(bought)
|
||||
}
|
||||
|
||||
let swipeConf = UISwipeActionsConfiguration(actions: actions)
|
||||
swipeConf.performsFirstActionWithFullSwipe = false
|
||||
|
||||
return swipeConf
|
||||
}
|
||||
|
||||
// Delete console item from library
|
||||
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
|
||||
let delete = UIContextualAction(style: .destructive, title: "Delete") { (action, view, actionDone) in
|
||||
|
||||
var nso : NSManagedObject? = .none
|
||||
var name : String?
|
||||
if self.category.selectedSegmentIndex == 0 {
|
||||
nso = self.videoGamesInLibrary[self.showWishlist]?[indexPath.row]
|
||||
name = self.videoGamesInLibrary[self.showWishlist]?[indexPath.row].name
|
||||
|
||||
}else{
|
||||
nso = self.accessoriesinLibrary[self.showWishlist]?[indexPath.row]
|
||||
name = self.accessoriesinLibrary[self.showWishlist]?[indexPath.row].name
|
||||
}
|
||||
|
||||
let deleteWarning = UIAlertController( title: "Aus Zockerhöhle entfernen",
|
||||
message: "Willst du '\(name ?? "N/A")' wirklich aus der Zockerhöhle tragen?",
|
||||
preferredStyle: .alert)
|
||||
|
||||
deleteWarning.addAction(UIAlertAction(title: "Ja", style: .destructive, handler: { (action) in
|
||||
actionDone(true)
|
||||
if nso != nil {
|
||||
CDManager.shared.viewContext.delete(nso!)
|
||||
}
|
||||
}))
|
||||
|
||||
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)
|
||||
|
||||
let swipeConf = UISwipeActionsConfiguration(actions: [delete])
|
||||
swipeConf.performsFirstActionWithFullSwipe = false
|
||||
|
||||
return swipeConf
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -49,6 +49,10 @@ class AccessoryStore : NSObject, ObservableObject, NSFetchedResultsControllerDel
|
||||
self.consoleFilter = console
|
||||
}
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
print("GameStore::controllerDidChangeContent")
|
||||
self.objectWillChange.send()
|
||||
|
||||
@@ -10,53 +10,63 @@ import Foundation
|
||||
import UIKit
|
||||
import Combine
|
||||
import SwiftUI
|
||||
import CoreData
|
||||
|
||||
class AccessoryViewModel : ObservableObject {
|
||||
var objectWillChange = ObservableObjectPublisher()
|
||||
|
||||
var inWishlist : Bool {
|
||||
didSet {
|
||||
if let accessory = self.accessory {
|
||||
guard let accessory = self.accessory else { return }
|
||||
|
||||
accessory.inWishlist = inWishlist
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var manufacturer : String? {
|
||||
didSet {
|
||||
if let accessory = self.accessory {
|
||||
guard let accessory = self.accessory else { return }
|
||||
|
||||
accessory.manufacturer = manufacturer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var color : String? {
|
||||
didSet {
|
||||
if let accessory = self.accessory {
|
||||
guard let accessory = self.accessory else { return }
|
||||
|
||||
accessory.color = color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var name : String {
|
||||
didSet {
|
||||
if let accessory = self.accessory {
|
||||
guard let accessory = self.accessory else { return }
|
||||
|
||||
accessory.name = name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var lentTo : String? {
|
||||
didSet {
|
||||
guard let accessory = self.accessory else { return }
|
||||
|
||||
accessory.lentTo = lentTo;
|
||||
}
|
||||
}
|
||||
private var accessory : Accessory? {
|
||||
didSet {
|
||||
if accessory != nil {
|
||||
self.name = accessory!.name
|
||||
self.inWishlist = accessory!.inWishlist
|
||||
self.color = accessory!.color
|
||||
self.manufacturer = accessory!.manufacturer
|
||||
}
|
||||
guard let accessory = accessory else { return }
|
||||
|
||||
self.name = accessory.name
|
||||
self.inWishlist = accessory.inWishlist
|
||||
self.color = accessory.color
|
||||
self.manufacturer = accessory.manufacturer
|
||||
}
|
||||
}
|
||||
|
||||
var NSManagedObjectChangedObserver : AnyCancellable? = .none
|
||||
|
||||
init(accessory : Accessory) {
|
||||
self.accessory = accessory
|
||||
|
||||
@@ -65,11 +75,24 @@ class AccessoryViewModel : ObservableObject {
|
||||
self.color = accessory.color
|
||||
self.manufacturer = accessory.manufacturer
|
||||
|
||||
_ = NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange, object: CDManager.shared.viewContext).sink {
|
||||
//TODO
|
||||
self.NSManagedObjectChangedObserver = NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange, object: CDManager.shared.viewContext).first().sink { notification in
|
||||
guard let accessory = self.accessory else { return }
|
||||
guard let userInfo = notification.userInfo else { return }
|
||||
|
||||
var managedObjectIsMatching = false
|
||||
if let inserts = userInfo[NSInsertedObjectsKey] as? Set<NSManagedObject> {
|
||||
if inserts.contains(accessory) { managedObjectIsMatching = true }
|
||||
}
|
||||
if let updates = userInfo[NSUpdatedObjectsKey] as? Set<NSManagedObject> {
|
||||
if updates.contains(accessory) { managedObjectIsMatching = true }
|
||||
}
|
||||
if let deletes = userInfo[NSDeletedObjectsKey] as? Set<NSManagedObject> {
|
||||
if deletes.contains(accessory) { managedObjectIsMatching = true }
|
||||
}
|
||||
|
||||
if managedObjectIsMatching {
|
||||
self.objectWillChange.send()
|
||||
if let accessory = self.accessory {
|
||||
print("Accessory: \(accessory.name) Notification: \($0.description)")
|
||||
print("AccessoryViewModel::NSMangedObjectChanged MY Accessory")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
55
Zockerhoehle/ViewModel/ConsoleViewModel.swift
Normal file
55
Zockerhoehle/ViewModel/ConsoleViewModel.swift
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// ConsoleViewModel.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 25.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
|
||||
class ConsoleViewModel : ObservableObject {
|
||||
var objectWillChange = ObservableObjectPublisher()
|
||||
|
||||
init(_ console: Console) {
|
||||
self.console = console
|
||||
self.name = console.name!
|
||||
}
|
||||
|
||||
private var console : Console? {
|
||||
didSet {
|
||||
guard let console = console else { return }
|
||||
|
||||
self.name = console.name!
|
||||
}
|
||||
}
|
||||
|
||||
var name : String {
|
||||
didSet {
|
||||
guard let console = console else { return }
|
||||
console.name = name
|
||||
}
|
||||
}
|
||||
|
||||
var logo : UIImage? {
|
||||
get {
|
||||
if let logoImage = self.console?.logo?.image {
|
||||
return logoImage
|
||||
}
|
||||
|
||||
return .none
|
||||
}
|
||||
|
||||
set {
|
||||
if let console = self.console {
|
||||
if let logoImage = newValue {
|
||||
let newLogo = Logo(context: CDManager.shared.viewContext)
|
||||
newLogo.console = console
|
||||
newLogo.image = logoImage
|
||||
console.logo = newLogo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
54
Zockerhoehle/ViewModel/FeaturedStore.swift
Normal file
54
Zockerhoehle/ViewModel/FeaturedStore.swift
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// FeaturedStore.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 25.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
class FeaturedStore : ObservableObject {
|
||||
var objectWillChange = PassthroughSubject<Void, Never>()
|
||||
|
||||
var gameStore = GameStore(sortDescriptors: [NSSortDescriptor(key: "createdAt", ascending: false), NSSortDescriptor(key: "name", ascending: true)], fetchLimit: 1)
|
||||
|
||||
|
||||
var consoleStore = ConsoleStore()
|
||||
|
||||
var consoleStoreSubscriber : AnyCancellable?
|
||||
var gameStoreSubscriber : AnyCancellable?
|
||||
|
||||
init() {
|
||||
_ = self.consoleStore.consoles
|
||||
if (self.gameStore.games.count > 0) {
|
||||
self.featuredGame = self.gameStore.games.first
|
||||
}
|
||||
|
||||
self.featuredConsole = self.featuredGame?.console
|
||||
|
||||
gameStoreSubscriber = self.gameStore.objectWillChange.sink { _ in
|
||||
self.featuredGame = self.gameStore.games.first
|
||||
self.featuredConsole = self.featuredGame?.console
|
||||
}
|
||||
}
|
||||
|
||||
var featuredGame : Game? {
|
||||
willSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
var featuredAccessory : Accessory? {
|
||||
willSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
var featuredConsole : Console? {
|
||||
willSet {
|
||||
objectWillChange.send()
|
||||
}
|
||||
}
|
||||
}
|
||||
48
Zockerhoehle/ViewModel/GameSeriesStore.swift
Normal file
48
Zockerhoehle/ViewModel/GameSeriesStore.swift
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// ConsoleStore.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 02.08.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import SwiftUI
|
||||
import CoreData
|
||||
|
||||
class GameSeriesStore : NSObject, ObservableObject, NSFetchedResultsControllerDelegate {
|
||||
var objectWillChange = ObservableObjectPublisher()
|
||||
|
||||
var gameSeries : [GameSeries] {
|
||||
get {
|
||||
if self.fetchResultsController.fetchedObjects == nil {
|
||||
do {
|
||||
try fetchResultsController.performFetch()
|
||||
}catch {
|
||||
print("ConsoleStore::consoles Perform Fetch not possible '\(error)'")
|
||||
}
|
||||
}
|
||||
|
||||
return self.fetchResultsController.fetchedObjects ?? []
|
||||
}
|
||||
}
|
||||
|
||||
lazy var fetchResultsController : NSFetchedResultsController<GameSeries> = {
|
||||
let fetch : NSFetchRequest<GameSeries> = GameSeries.fetchRequest()
|
||||
|
||||
fetch.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
|
||||
|
||||
var fetchRC = NSFetchedResultsController(fetchRequest: fetch, managedObjectContext: CDManager.shared.viewContext, sectionNameKeyPath: nil, cacheName: nil)
|
||||
|
||||
fetchRC.delegate = self
|
||||
|
||||
return fetchRC
|
||||
|
||||
}()
|
||||
|
||||
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
print("AllConsolesViewController::controllerDidChangeContent")
|
||||
self.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
55
Zockerhoehle/ViewModel/GameSeriesViewModel.swift
Normal file
55
Zockerhoehle/ViewModel/GameSeriesViewModel.swift
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// ConsoleViewModel.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 25.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
|
||||
class GameSeriesViewModel : ObservableObject {
|
||||
var objectWillChange = ObservableObjectPublisher()
|
||||
|
||||
init(_ gameSeries: GameSeries) {
|
||||
self.gameSeries = gameSeries
|
||||
self.name = gameSeries.name
|
||||
}
|
||||
|
||||
private var gameSeries : GameSeries? {
|
||||
didSet {
|
||||
guard let gameSeries = gameSeries else { return }
|
||||
|
||||
self.name = gameSeries.name
|
||||
}
|
||||
}
|
||||
|
||||
var name : String {
|
||||
didSet {
|
||||
guard let gameSeries = gameSeries else { return }
|
||||
gameSeries.name = name
|
||||
}
|
||||
}
|
||||
|
||||
var cover : UIImage? {
|
||||
get {
|
||||
if let logoImage = self.gameSeries?.cover?.image {
|
||||
return logoImage
|
||||
}
|
||||
|
||||
return .none
|
||||
}
|
||||
|
||||
set {
|
||||
if let gameSeries = self.gameSeries {
|
||||
if let image = newValue {
|
||||
let newCover = GameSeriesCover(context: CDManager.shared.viewContext)
|
||||
newCover.gameSeries = gameSeries
|
||||
newCover.image = image
|
||||
gameSeries.cover = newCover
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,10 +14,14 @@ import Combine
|
||||
class GameStore : NSObject, ObservableObject, NSFetchedResultsControllerDelegate {
|
||||
var objectWillChange = PassthroughSubject<Void , Never>()
|
||||
var consoleFilter : Console?
|
||||
var gameSeriesFilter : GameSeries?
|
||||
var sortDescriptors : [NSSortDescriptor] = [NSSortDescriptor(key: "name", ascending: true)]
|
||||
var fetchLimit : Int = 0
|
||||
|
||||
var games : [Game] {
|
||||
get {
|
||||
if self.fetchResultsController.fetchedObjects == nil {
|
||||
|
||||
do {
|
||||
try fetchResultsController.performFetch()
|
||||
}catch {
|
||||
@@ -25,7 +29,21 @@ class GameStore : NSObject, ObservableObject, NSFetchedResultsControllerDelegate
|
||||
}
|
||||
}
|
||||
|
||||
return self.fetchResultsController.fetchedObjects ?? []
|
||||
let result = self.fetchResultsController.fetchedObjects ?? []
|
||||
|
||||
//Anscheinend ein Bug im FetchResultController das er das fetchLimit manchmal ignoriert
|
||||
if self.fetchLimit > 0 && result.count > self.fetchLimit {
|
||||
print("GameStore::games Fetch limit of ignored. Expected: \(self.fetchLimit) Delivered: \(result.count)")
|
||||
|
||||
var clampedResult : [Game] = []
|
||||
for index in 0..<self.fetchLimit {
|
||||
clampedResult.append(result[index])
|
||||
}
|
||||
|
||||
return clampedResult
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +51,14 @@ class GameStore : NSObject, ObservableObject, NSFetchedResultsControllerDelegate
|
||||
var gamesFetch : NSFetchRequest<Game> = Game.fetchRequest()
|
||||
if let console = consoleFilter {
|
||||
gamesFetch = Game.fetchRequest(console: console)
|
||||
}else if let gameSeries = gameSeriesFilter {
|
||||
gamesFetch = Game.fetchRequest(gameSeries: gameSeries)
|
||||
}else {
|
||||
print("No filter: fetch Limit: \(self.fetchLimit)")
|
||||
}
|
||||
|
||||
gamesFetch.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
|
||||
gamesFetch.fetchLimit = self.fetchLimit
|
||||
gamesFetch.sortDescriptors = self.sortDescriptors
|
||||
|
||||
let gamesFetchRC = NSFetchedResultsController(fetchRequest: gamesFetch, managedObjectContext: CDManager.shared.viewContext, sectionNameKeyPath: nil, cacheName: nil)
|
||||
|
||||
@@ -44,13 +67,30 @@ class GameStore : NSObject, ObservableObject, NSFetchedResultsControllerDelegate
|
||||
return gamesFetchRC
|
||||
}()
|
||||
|
||||
init(console : Console?) {
|
||||
init(console : Console?, fetchLimit : Int = 0) {
|
||||
super.init()
|
||||
self.consoleFilter = console
|
||||
self.fetchLimit = fetchLimit
|
||||
}
|
||||
|
||||
init(gameSeries: GameSeries?, fetchLimit : Int = 0) {
|
||||
super.init()
|
||||
self.gameSeriesFilter = gameSeries
|
||||
self.fetchLimit = fetchLimit
|
||||
}
|
||||
|
||||
init(sortDescriptors : [NSSortDescriptor], fetchLimit : Int = 0) {
|
||||
super.init()
|
||||
self.sortDescriptors = sortDescriptors
|
||||
self.fetchLimit = fetchLimit
|
||||
}
|
||||
|
||||
init(fetchLimit : Int = 0) {
|
||||
super.init()
|
||||
self.fetchLimit = fetchLimit
|
||||
}
|
||||
|
||||
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||
print("GameStore::controllerDidChangeContent")
|
||||
self.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,60 +17,129 @@ class GameViewModel : ObservableObject {
|
||||
|
||||
private var game : Game? {
|
||||
didSet {
|
||||
if game != nil {
|
||||
self.name = game!.name
|
||||
self.inWishlist = game!.inWishlist
|
||||
self.isDigital = game!.isDigital
|
||||
self.isFinished = game!.isFinished
|
||||
guard let game = game else { return }
|
||||
|
||||
self.name = game.name!
|
||||
self.inWishlist = game.inWishlist
|
||||
self.isDigital = game.isDigital
|
||||
self.isFinished = game.isFinished
|
||||
}
|
||||
}
|
||||
|
||||
var lentTo : String {
|
||||
didSet {
|
||||
guard let game = self.game else { return }
|
||||
|
||||
if lentTo != "" {
|
||||
game.lentTo = lentTo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var name : String {
|
||||
didSet {
|
||||
if let game = self.game {
|
||||
guard let game = self.game else { return }
|
||||
|
||||
game.name = name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var inWishlist : Bool {
|
||||
didSet {
|
||||
if let game = self.game {
|
||||
guard let game = self.game else { return }
|
||||
|
||||
game.inWishlist = inWishlist
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isDigital : Bool {
|
||||
didSet {
|
||||
if let game = self.game {
|
||||
guard let game = self.game else { return }
|
||||
|
||||
game.isDigital = isDigital
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isFinished : Bool {
|
||||
didSet {
|
||||
if let game = self.game {
|
||||
guard let game = self.game else { return }
|
||||
|
||||
game.isFinished = isFinished
|
||||
}
|
||||
}
|
||||
|
||||
var gameSeries : String {
|
||||
willSet {
|
||||
if newValue != "" , let game = self.game {
|
||||
game.addGameSeries(by: newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var console : Console? {
|
||||
get {
|
||||
return self.game?.console
|
||||
}
|
||||
}
|
||||
|
||||
var cover : UIImage? {
|
||||
get {
|
||||
if let coverImage = self.game?.cover?.image {
|
||||
return coverImage
|
||||
}
|
||||
|
||||
return .none
|
||||
}
|
||||
|
||||
set {
|
||||
if let game = self.game {
|
||||
if let coverImage = newValue {
|
||||
let newCover = Cover(context: CDManager.shared.viewContext)
|
||||
newCover.game = game
|
||||
newCover.image = coverImage
|
||||
game.cover = newCover
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func removeGame() {
|
||||
if let game = self.game {
|
||||
CDManager.shared.viewContext.delete(game)
|
||||
}
|
||||
}
|
||||
|
||||
var NSManagedObjectChangedObserver : AnyCancellable? = .none
|
||||
|
||||
init(game : Game) {
|
||||
self.game = game
|
||||
|
||||
self.name = game.name
|
||||
self.name = game.name!
|
||||
self.inWishlist = game.inWishlist
|
||||
self.isDigital = game.isDigital
|
||||
self.isFinished = game.isFinished
|
||||
self.gameSeries = game.series?.id ?? ""
|
||||
self.lentTo = game.lentTo ?? ""
|
||||
|
||||
_ = NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange, object: CDManager.shared.viewContext).sink {
|
||||
//TODO
|
||||
self.NSManagedObjectChangedObserver = NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange, object: CDManager.shared.viewContext).first().sink { notification in
|
||||
|
||||
guard let game = self.game else { return }
|
||||
guard let userInfo = notification.userInfo else { return }
|
||||
|
||||
var managedObjectIsMatching = false
|
||||
if let inserts = userInfo[NSInsertedObjectsKey] as? Set<NSManagedObject> {
|
||||
if inserts.contains(game) { managedObjectIsMatching = true }
|
||||
}
|
||||
if let updates = userInfo[NSUpdatedObjectsKey] as? Set<NSManagedObject> {
|
||||
if updates.contains(game) { managedObjectIsMatching = true }
|
||||
}
|
||||
if let deletes = userInfo[NSDeletedObjectsKey] as? Set<NSManagedObject> {
|
||||
if deletes.contains(game) { managedObjectIsMatching = true }
|
||||
}
|
||||
|
||||
if managedObjectIsMatching {
|
||||
self.objectWillChange.send()
|
||||
if let game = self.game {
|
||||
print("Game: \(game.name) Notification: \($0.description)")
|
||||
print("GameViewModel::NSMangedObjectChanged Update of \(game.name)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,3 @@ struct AccessoryDetailView : View {
|
||||
self.accessoryVM = accessoryVM!
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
struct AccessoryDetailView_Previews : PreviewProvider {
|
||||
static var previews: some View {
|
||||
AccessoryDetailView(accessoryVM: nil)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
108
Zockerhoehle/Views/ConsoleAllView.swift
Normal file
108
Zockerhoehle/Views/ConsoleAllView.swift
Normal file
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// ConsolesListView.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 01.08.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import QGrid
|
||||
|
||||
struct ModalAddConsoleToLibrary : View {
|
||||
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
|
||||
|
||||
@State var modalConsoleName : String = ""
|
||||
|
||||
private func addConsoleToLibrary() {
|
||||
//TODO
|
||||
}
|
||||
|
||||
var addButton : some View {
|
||||
return Button(action: {
|
||||
addConsoleToLibrary()
|
||||
self.presentationMode.wrappedValue.dismiss()},
|
||||
label: { Text("Add") })
|
||||
.disabled(self.modalConsoleName.trimmingCharacters(in: .whitespacesAndNewlines) == "" )
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
Form {
|
||||
TextField("Name", text: $modalConsoleName)
|
||||
}
|
||||
.font(.caption)
|
||||
.navigationBarTitle(Text("New Console"))
|
||||
.navigationBarItems(leading: Button(action: { self.presentationMode.wrappedValue.dismiss() },
|
||||
label: {Text("Cancel")}),
|
||||
//Add Button is disabled if no name is entered
|
||||
trailing: addButton)
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ConsolesListView : View {
|
||||
@EnvironmentObject var consoleStore : ConsoleStore
|
||||
@State var showAddConsoleToLibraryModal: Bool = false
|
||||
|
||||
var body: some View {
|
||||
/*List(consoleStore.consoles) {console in
|
||||
NavigationLink(destination: ConsoleLibraryView(console: console)) {
|
||||
HStack {
|
||||
if console.logo?.image != nil {
|
||||
Image(uiImage: console.logo!.image!).resizable().frame(width: 50.0, height: 50.0)
|
||||
}else {
|
||||
Image(systemName: "stop").resizable().frame(width: 50.0, height: 50.0)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("\(console.name)")
|
||||
Text("Spiele: \(console.games.filter({($0 as! Game).inWishlist == false}).count), Zubehör: \(console.accessories.filter({($0 as! Accessory).inWishlist == false}).count)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
QGrid(consoleStore.consoles, columns: 4, columnsInLandscape: 6) {
|
||||
GridCell(console: $0)
|
||||
}
|
||||
.padding()
|
||||
.navigationBarTitle(Text("Zockerhöhle"))
|
||||
.navigationBarItems(trailing:
|
||||
Button(action: {
|
||||
self.showAddConsoleToLibraryModal = true
|
||||
}) {
|
||||
Image(systemName: "plus")
|
||||
})
|
||||
.sheet(isPresented: $showAddConsoleToLibraryModal) {
|
||||
ModalAddConsoleToLibrary()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GridCell: View {
|
||||
var console: Console
|
||||
|
||||
var body: some View {
|
||||
VStack() {
|
||||
if console.logo?.image != nil {
|
||||
NavigationLink(destination: ConsoleLibraryView(console: console)) {
|
||||
VStack {
|
||||
Image(uiImage: (console.logo?.image)!)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
//.shadow(color: .primary, radius: 5)
|
||||
.padding([.horizontal, .top], 7)
|
||||
Text(console.shortName ?? console.name!).lineLimit(1)
|
||||
}
|
||||
}.buttonStyle(PlainButtonStyle())
|
||||
|
||||
}else{
|
||||
Text("mu")
|
||||
}
|
||||
//
|
||||
//Text(person.lastName).lineLimit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Zockerhoehle/Views/ConsoleEditView.swift
Normal file
42
Zockerhoehle/Views/ConsoleEditView.swift
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// ConsoleDetailView.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 25.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ConsoleEditView: View {
|
||||
@ObservedObject var consoleViewModel : ConsoleViewModel
|
||||
|
||||
@State var showLogoImagePicker = false
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
TextField("Name der Konsole", text: $consoleViewModel.name)
|
||||
|
||||
consoleViewModel.logo.map {
|
||||
Image (uiImage: $0)
|
||||
.resizable()
|
||||
.frame(width:100, height: 100)
|
||||
}
|
||||
|
||||
Button(action: { self.showLogoImagePicker = true }, label: { Text("Pick Image") })
|
||||
}
|
||||
.navigationBarTitle("Editiere Konsole")
|
||||
.sheet(isPresented: $showLogoImagePicker) {
|
||||
ImagePicker.shared.view
|
||||
}
|
||||
.onReceive(ImagePicker.shared.objectWillChange, perform: { image in
|
||||
if let image = image {
|
||||
self.consoleViewModel.logo = image
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
init(_ console : Console) {
|
||||
self.consoleViewModel = ConsoleViewModel(console)
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,68 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ModalAddToConsoleLibrary : View {
|
||||
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
|
||||
|
||||
@State var modalAddName : String = ""
|
||||
@State var modalAddToWishlist : Bool
|
||||
@State var modalIsDigital : Bool = false
|
||||
|
||||
@State var isVideogamesSelected : Bool
|
||||
|
||||
var console : Console;
|
||||
|
||||
private func addGameToLibrary() {
|
||||
let game = Game(context: CDManager.shared.viewContext)
|
||||
game.name = self.modalAddName
|
||||
game.console = self.console;
|
||||
game.inWishlist = self.modalAddToWishlist
|
||||
game.isDigital = self.modalIsDigital
|
||||
}
|
||||
|
||||
private func addAccessoryToLibrary() {
|
||||
let accessory = Accessory(context: CDManager.shared.viewContext)
|
||||
accessory.name = self.modalAddName
|
||||
accessory.console = self.console
|
||||
accessory.inWishlist = self.modalAddToWishlist
|
||||
}
|
||||
|
||||
var addButton : some View {
|
||||
return Button(action: {
|
||||
if (self.isVideogamesSelected) {
|
||||
self.addGameToLibrary()
|
||||
|
||||
}else{
|
||||
self.addAccessoryToLibrary()
|
||||
}
|
||||
self.presentationMode.wrappedValue.dismiss()},
|
||||
label: { Text("Add") })
|
||||
.disabled(self.modalAddName.trimmingCharacters(in: .whitespacesAndNewlines) == "" )
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
Form {
|
||||
TextField("Name", text: $modalAddName)
|
||||
if self.isVideogamesSelected {
|
||||
Toggle(isOn: $modalIsDigital, label: {
|
||||
Text("Ist Digital")
|
||||
})
|
||||
}
|
||||
Toggle(isOn: $modalAddToWishlist, label: {
|
||||
Text("Auf die Wunschliste")
|
||||
})
|
||||
}
|
||||
.font(.caption)
|
||||
.navigationBarTitle(self.isVideogamesSelected ? Text("New Game") : Text("New Accessory"))
|
||||
.navigationBarItems(leading: Button(action: { self.presentationMode.wrappedValue.dismiss() },
|
||||
label: {Text("Cancel")}),
|
||||
//Add Button is disabled if no name is entered
|
||||
trailing: addButton)
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ConsoleLibraryView : View {
|
||||
@State var isVideogamesSelected = true
|
||||
@@ -16,19 +78,8 @@ struct ConsoleLibraryView : View {
|
||||
@ObservedObject var accessoryStore : AccessoryStore
|
||||
|
||||
@State var showWishlist = false
|
||||
|
||||
@State var isModal: Bool = false
|
||||
|
||||
var modal: some View {
|
||||
NavigationView {
|
||||
Form {
|
||||
Text("bl")
|
||||
}
|
||||
.font(.caption)
|
||||
.navigationBarTitle(self.isVideogamesSelected ? Text("New Game") : Text("New Accessory"))
|
||||
.navigationBarItems(trailing: Button(action: { self.isModal = false } ) { Text("Done") })
|
||||
}
|
||||
}
|
||||
@State var showAddToConsoleLibraryModal: Bool = false
|
||||
@State var showLogoImagePicker = false
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
@@ -44,14 +95,29 @@ struct ConsoleLibraryView : View {
|
||||
if self.isVideogamesSelected {
|
||||
List {
|
||||
ForEach(gameStore.games.filter({$0.inWishlist == self.showWishlist})) { game in
|
||||
NavigationLink(destination: GameDetailView(gameVM: GameViewModel(game: game))) {
|
||||
Text("\(game.name)")
|
||||
NavigationLink(destination: GameDetailView(game: game)) {
|
||||
HStack {
|
||||
/*game.cover.map {
|
||||
Image(uiImage: $0.image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 75)
|
||||
}*/
|
||||
|
||||
Text("\(game.name!)")
|
||||
|
||||
if game.isDigital {
|
||||
Image("digitalGame")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 15)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else {
|
||||
List {
|
||||
|
||||
ForEach(accessoryStore.accessories.filter({$0.inWishlist == self.showWishlist})) { accessory in
|
||||
NavigationLink(destination: AccessoryDetailView(accessoryVM: AccessoryViewModel(accessory: accessory))) {
|
||||
Text("\(accessory.name)")
|
||||
@@ -59,23 +125,33 @@ struct ConsoleLibraryView : View {
|
||||
}
|
||||
}
|
||||
}
|
||||
}.navigationBarTitle(Text("\(self.console?.name ?? "N/A")"), displayMode: .automatic)
|
||||
}
|
||||
.navigationBarTitle(Text("\(self.console?.name ?? "N/A")"), displayMode: .automatic)
|
||||
.navigationBarItems(trailing:
|
||||
HStack {
|
||||
Button(action: {
|
||||
self.isModal = true
|
||||
}) {
|
||||
Image(systemName: "plus")
|
||||
}.padding(5)
|
||||
Button(action: {
|
||||
self.showWishlist.toggle()
|
||||
}) {
|
||||
Image(systemName: "star")
|
||||
}.accentColor(self.showWishlist ? Color.red : Color.blue)
|
||||
NavigationLink(destination: ConsoleEditView(self.console!)) {
|
||||
Image(systemName: "pencil.and.ellipsis.rectangle")
|
||||
}
|
||||
|
||||
Button(action: { self.showAddToConsoleLibraryModal = true },
|
||||
label: { Image(systemName: "plus")})
|
||||
.padding(5)
|
||||
|
||||
Button(action: { self.showWishlist.toggle()},
|
||||
label: { Image("wishlist")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
})
|
||||
.sheet(isPresented: $isModal, onDismiss: {}, content: {
|
||||
self.modal
|
||||
.accentColor(self.showWishlist ? Color.red : Color.blue)
|
||||
})
|
||||
.sheet(isPresented: $showAddToConsoleLibraryModal) {
|
||||
if self.console != nil {
|
||||
ModalAddToConsoleLibrary(modalAddToWishlist: self.showWishlist, isVideogamesSelected: true, console: self.console!)
|
||||
}else{
|
||||
Text("Fehler: Keine Konsole übergeben")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
init(console : Console?) {
|
||||
@@ -84,11 +160,3 @@ struct ConsoleLibraryView : View {
|
||||
self.accessoryStore = AccessoryStore(console: console)
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
struct ConsoleLibraryView_Previews : PreviewProvider {
|
||||
static var previews: some View {
|
||||
ConsoleLibraryView(console: .none)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
//
|
||||
// ConsolesListView.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 01.08.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct ConsolesListView : View {
|
||||
@ObservedObject var consoleStore : ConsoleStore = ConsoleStore()
|
||||
@ObservedObject var gameStore : GameStore
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List {
|
||||
ForEach(consoleStore.consoles) {console in
|
||||
//TODO environmentObject should not be passed through the hierarchy
|
||||
//This is only for fixin a swiftui bug
|
||||
NavigationLink(destination: ConsoleLibraryView(console: console)) {
|
||||
Text("\(console.name)")
|
||||
}
|
||||
}
|
||||
}.navigationBarTitle(Text("Zockerhöhle"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
struct ConsolesListView_Previews : PreviewProvider {
|
||||
static var previews: some View {
|
||||
ConsolesListView(gameStore: GameStore(console: .none))
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -9,16 +9,59 @@
|
||||
import SwiftUI
|
||||
|
||||
struct GameDetailView : View {
|
||||
//@Binding var g : Game
|
||||
@ObservedObject var gameVM : GameViewModel
|
||||
|
||||
@State private var showDeleteAlert : Bool = false
|
||||
@State var hasFinishedDate : Bool = false
|
||||
@State var playthroughDate : Date = Date()
|
||||
|
||||
@EnvironmentObject var gameSeriesStore : GameSeriesStore
|
||||
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
|
||||
|
||||
|
||||
@State var showingPicker = false
|
||||
|
||||
@State var image : Image? = nil
|
||||
|
||||
@State var isLent : Bool = false
|
||||
|
||||
var gameSeriesPicker : some View {
|
||||
Picker(selection: $gameVM.gameSeries, label:
|
||||
Text("Spieleserie")
|
||||
, content: {
|
||||
Text("Keine").tag("")
|
||||
ForEach(gameSeriesStore.gameSeries) { gameSeries in
|
||||
Text("\(gameSeries.name)").tag(gameSeries.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var imageCoverSection : some View {
|
||||
Section {
|
||||
VStack{
|
||||
Button("Show image picker") {
|
||||
self.showingPicker = true
|
||||
}
|
||||
|
||||
if self.gameVM.cover != nil {
|
||||
Image(uiImage: self.gameVM.cover!)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section {
|
||||
TextField("Videogame name", text: $gameVM.name)
|
||||
|
||||
//Gray color should indicate immutable data
|
||||
Text("\(gameVM.console?.name ?? "No console")").foregroundColor(.gray)
|
||||
|
||||
Toggle(isOn: $gameVM.isDigital, label: {
|
||||
Text("Nur Digital")
|
||||
})
|
||||
@@ -27,6 +70,20 @@ struct GameDetailView : View {
|
||||
Text("In Wunschliste")
|
||||
})
|
||||
|
||||
Toggle(isOn: $isLent, label: {
|
||||
Text("Verliehen?")
|
||||
}).onReceive(gameVM.objectWillChange) { _ in
|
||||
self.isLent = self.gameVM.lentTo != "";
|
||||
}.onAppear() {
|
||||
self.isLent = self.gameVM.lentTo != "";
|
||||
}
|
||||
|
||||
if isLent {
|
||||
TextField("Verliehen an", text: $gameVM.lentTo)
|
||||
}
|
||||
|
||||
gameSeriesPicker
|
||||
|
||||
Toggle(isOn: $gameVM.isFinished , label: {
|
||||
Text("Durchgezockt")
|
||||
})
|
||||
@@ -43,20 +100,55 @@ struct GameDetailView : View {
|
||||
in: ...Date(),
|
||||
displayedComponents: [.date])
|
||||
}
|
||||
}
|
||||
|
||||
}.navigationBarTitle(Text("\(gameVM.name)"), displayMode: .automatic)
|
||||
imageCoverSection
|
||||
|
||||
Section{
|
||||
gameDeleteButton
|
||||
}
|
||||
|
||||
}
|
||||
.navigationBarTitle(Text("\(gameVM.name)"), displayMode: .automatic)
|
||||
.sheet(isPresented: $showingPicker,
|
||||
onDismiss: {
|
||||
// do whatever you need here
|
||||
}, content: {
|
||||
ImagePicker.shared.view
|
||||
})
|
||||
.onReceive(ImagePicker.shared.objectWillChange) { image in
|
||||
if let image = image {
|
||||
self.gameVM.cover = image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Irgendwie gibt es einen Bug der den Alert im navigationBarItem zwei mal aufruft.
|
||||
//Deswegen muss der delete Button is auf weiteres in die Form
|
||||
var gameDeleteButton : some View {
|
||||
Button(action: {
|
||||
self.showDeleteAlert = true
|
||||
}, label: {
|
||||
Spacer()
|
||||
Text("Spiel löschen")
|
||||
Spacer()
|
||||
//Image(systemName: "trash").foregroundColor(.red)
|
||||
})
|
||||
.accentColor(.red)
|
||||
.alert(isPresented: $showDeleteAlert, content: {
|
||||
Alert(title: Text("Aus Zockerhöhle entfernen"), message: Text("Willst du '\(self.gameVM.name)' wirklich aus der Zockerhöhle werfen?"), primaryButton: Alert.Button.destructive(Text("Ja!"), action: {
|
||||
//self.presentationMode.value.dismiss()
|
||||
self.gameVM.removeGame()
|
||||
}), secondaryButton: Alert.Button.cancel(Text("Lieber doch nicht")))
|
||||
})
|
||||
}
|
||||
|
||||
init(gameVM : GameViewModel?) {
|
||||
self.gameVM = gameVM!
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
struct GameDetailView_Previews : PreviewProvider {
|
||||
static var previews: some View {
|
||||
GameDetailView(gameVM: nil)
|
||||
init(game : Game) {
|
||||
self.gameVM = GameViewModel(game: game)
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
23
Zockerhoehle/Views/GamePickupsView.swift
Normal file
23
Zockerhoehle/Views/GamePickupsView.swift
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// LatestGamePickupsView.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 24.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct GamePickupsView: View {
|
||||
@ObservedObject var gameStore = GameStore(sortDescriptors: [NSSortDescriptor(key: "createdAt", ascending: false), NSSortDescriptor(key: "name", ascending: true)], fetchLimit: 50)
|
||||
|
||||
var body: some View {
|
||||
List(gameStore.games) { game in
|
||||
NavigationLink(destination: GameDetailView(game: game)) {
|
||||
Text("\(game.name!)")
|
||||
}
|
||||
}
|
||||
.padding(.top) // Workaround, damit die Liste beim scrollen nicht unter der NavigationView angezeigt wird
|
||||
.navigationBarTitle(Text("Latest Pickups"))
|
||||
}
|
||||
}
|
||||
89
Zockerhoehle/Views/GameSeriesAllView.swift
Normal file
89
Zockerhoehle/Views/GameSeriesAllView.swift
Normal file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// GameSeriesListView.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 05.08.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct GameSeriesAllView: View {
|
||||
@EnvironmentObject var gameSeriesStore : GameSeriesStore
|
||||
|
||||
@State var modalVisible : Bool = false
|
||||
@State var modalAddName : String = ""
|
||||
|
||||
@State var showingPicker : Bool = false
|
||||
|
||||
@State var image : UIImage?
|
||||
|
||||
var modalAddGameSeries: some View {
|
||||
NavigationView {
|
||||
Form {
|
||||
TextField("Name", text: $modalAddName)
|
||||
self.image.map { Image(uiImage: $0).resizable().frame(width: 100, height: 100)}
|
||||
|
||||
Button(action: { self.showingPicker = true}, label: { Text("Wähle Bild") })
|
||||
}
|
||||
.navigationBarTitle(Text("New Game Series"))
|
||||
.navigationBarItems(leading: Button(action: {self.modalVisible = false }, label: {Text("Cancel")})
|
||||
//Add Button is disabled if no name is entered
|
||||
, trailing: Button(action: {
|
||||
let gameSeries = GameSeries(context: CDManager.shared.viewContext)
|
||||
gameSeries.name = self.modalAddName
|
||||
if let image = self.image {
|
||||
let cover = GameSeriesCover(context: CDManager.shared.viewContext)
|
||||
cover.image = image
|
||||
cover.gameSeries = gameSeries
|
||||
gameSeries.cover = cover
|
||||
}
|
||||
self.modalVisible = false
|
||||
}) { Text("Add") }.disabled(self.modalAddName.trimmingCharacters(in: .whitespacesAndNewlines) == "" ))
|
||||
.sheet(isPresented: $showingPicker,
|
||||
onDismiss: {
|
||||
|
||||
}, content: {
|
||||
ImagePicker.shared.view
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func resetModalVariables() {
|
||||
self.modalAddName = ""
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
List(gameSeriesStore.gameSeries) { gameSeries in
|
||||
NavigationLink(destination: GameSeriesLibraryView(gameSeries: gameSeries)) {
|
||||
HStack {
|
||||
gameSeries.cover?.image.map {
|
||||
Image(uiImage: $0)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 50)
|
||||
}
|
||||
VStack(alignment: .leading) {
|
||||
Text(gameSeries.name)
|
||||
//Sonst wird der TExt kurioser Weise abgeschnitten wenn ein Bild davor ist. Hier nochmal später rein
|
||||
//schauen
|
||||
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .leading)
|
||||
Text("Spiele: \(gameSeries.games.filter({!($0 as! Game).inWishlist}).count ?? 0)/\(gameSeries.games.count ?? 0)").font(.caption)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.navigationBarTitle(Text("Videospielserien"))
|
||||
.navigationBarItems(trailing:
|
||||
Button(action: {
|
||||
self.modalVisible = true
|
||||
}) {
|
||||
Image(systemName: "plus")
|
||||
})
|
||||
.sheet(isPresented: $modalVisible, onDismiss: {}, content: {
|
||||
self.modalAddGameSeries
|
||||
})
|
||||
}
|
||||
}
|
||||
42
Zockerhoehle/Views/GameSeriesEditView.swift
Normal file
42
Zockerhoehle/Views/GameSeriesEditView.swift
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// ConsoleDetailView.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 25.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct GameSeriesEditView: View {
|
||||
@ObservedObject var gameSeriesViewModel : GameSeriesViewModel
|
||||
|
||||
@State var showCoverImagePicker = false
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
TextField("Name der Konsole", text: $gameSeriesViewModel.name)
|
||||
|
||||
gameSeriesViewModel.cover.map {
|
||||
Image (uiImage: $0)
|
||||
.resizable()
|
||||
.frame(width:100, height: 100)
|
||||
}
|
||||
|
||||
Button(action: { self.showCoverImagePicker = true }, label: { Text("Pick Image") })
|
||||
}
|
||||
.navigationBarTitle("Editiere Spieleserie")
|
||||
.sheet(isPresented: $showCoverImagePicker) {
|
||||
ImagePicker.shared.view
|
||||
}
|
||||
.onReceive(ImagePicker.shared.objectWillChange, perform: { image in
|
||||
if let image = image {
|
||||
self.gameSeriesViewModel.cover = image
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
init(_ gameSeries : GameSeries) {
|
||||
self.gameSeriesViewModel = GameSeriesViewModel(gameSeries)
|
||||
}
|
||||
}
|
||||
50
Zockerhoehle/Views/GameSeriesLibraryView.swift
Normal file
50
Zockerhoehle/Views/GameSeriesLibraryView.swift
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// GameSeriesDetailView.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 05.08.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct GameSeriesLibraryView: View {
|
||||
@ObservedObject var gameStore : GameStore
|
||||
@State var isDetailActivated : Bool = false
|
||||
|
||||
var gameSeries : GameSeries?
|
||||
|
||||
var body: some View {
|
||||
List(gameStore.games) { game in
|
||||
NavigationLink(destination: GameDetailView(game: game)) {
|
||||
Text("\(game.name!)")
|
||||
|
||||
if game.isDigital {
|
||||
Image("digitalGame")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 15)
|
||||
}
|
||||
|
||||
if game.inWishlist {
|
||||
Image("wishlist")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 15)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarTitle(Text(self.gameSeries?.name ?? "n/a"))
|
||||
.navigationBarItems(trailing:
|
||||
NavigationLink(destination: GameSeriesEditView(self.gameSeries!)) {
|
||||
Image(systemName: "pencil.and.ellipsis.rectangle")
|
||||
}
|
||||
)
|
||||
.padding()
|
||||
}
|
||||
|
||||
init(gameSeries: GameSeries?) {
|
||||
self.gameSeries = gameSeries
|
||||
gameStore = GameStore(gameSeries: gameSeries)
|
||||
}
|
||||
}
|
||||
27
Zockerhoehle/Views/MainView.swift
Normal file
27
Zockerhoehle/Views/MainView.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// MainView.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 05.08.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct MainView: View {
|
||||
var body: some View {
|
||||
Overview()
|
||||
// TabView {
|
||||
// ConsolesListView()
|
||||
// .tabItem({ Text("Konsolen") })
|
||||
// .tag(1)
|
||||
// GameSeriesAllView()
|
||||
// .tabItem({ Text("Serien") })
|
||||
// .tag(2)
|
||||
// Overview()
|
||||
// .tabItem({ Text("Überischt") })
|
||||
// .tag(0)
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
206
Zockerhoehle/Views/Overview.swift
Normal file
206
Zockerhoehle/Views/Overview.swift
Normal file
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// Overview.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 24.09.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct OverviewHeader<Destination : View> : View {
|
||||
private var destination : Destination
|
||||
private var title : String
|
||||
|
||||
init(title : String, destination : Destination) {
|
||||
self.title = title
|
||||
self.destination = destination
|
||||
}
|
||||
|
||||
var body : some View {
|
||||
HStack {
|
||||
Text("\(self.title)")
|
||||
.font(.headline)
|
||||
.padding(.leading, 15)
|
||||
.padding(.top, 5)
|
||||
Spacer()
|
||||
NavigationLink(destination: self.destination) {
|
||||
Text("Alle anzeigen")
|
||||
.font(.caption)
|
||||
.padding(.top, 10)
|
||||
.padding(.trailing, 15)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Overview: View {
|
||||
@EnvironmentObject var consoleStore : ConsoleStore
|
||||
@ObservedObject var gameStore : GameStore = GameStore(sortDescriptors: [NSSortDescriptor(key: "createdAt", ascending: false), NSSortDescriptor(key: "name", ascending: true)], fetchLimit: 10)
|
||||
@EnvironmentObject var gameSeriesStore : GameSeriesStore
|
||||
@ObservedObject var featuredStore = FeaturedStore()
|
||||
|
||||
var ConsolesOverview : some View {
|
||||
VStack(alignment: .leading) {
|
||||
OverviewHeader(title: "Aktivste Konsolen", destination: ConsolesListView())
|
||||
|
||||
if consoleStore.consoles.count == 0 {
|
||||
Text("No consoles")
|
||||
}else{
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(alignment: .top, spacing: 0) {
|
||||
ForEach(consoleStore.consoles.sorted(by: { Console.sortConsoleByNewestGame(consoleA: $0, consoleB: $1)})) { console in
|
||||
NavigationLink(destination: ConsoleLibraryView(console: console)) {
|
||||
VStack(alignment: .leading) {
|
||||
Group {
|
||||
console.logo?.image.map {
|
||||
Image(uiImage: $0)
|
||||
.resizable()
|
||||
.padding(10)
|
||||
.cornerRadius(5)
|
||||
}
|
||||
}
|
||||
.frame(width: 100, height: 100)
|
||||
//.background(Color(UIColor.lightGray))
|
||||
//.cornerRadius(5)
|
||||
|
||||
Text("\(console.name!)")
|
||||
.font(.caption)
|
||||
.frame(width: 100)
|
||||
|
||||
}.padding(.leading, 15)
|
||||
}.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
}.padding(.trailing, 15)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var GamesOverview : some View {
|
||||
VStack(alignment: .leading) {
|
||||
//TODO
|
||||
OverviewHeader(title: "Latest Game Pickups", destination: GamePickupsView())
|
||||
|
||||
if gameStore.games.count == 0 {
|
||||
Text("No Games")
|
||||
}else {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(alignment: .top, spacing: 0) {
|
||||
ForEach(gameStore.games) { game in
|
||||
NavigationLink(destination: GameDetailView(game: game)) {
|
||||
VStack(alignment: .leading) {
|
||||
Group {
|
||||
/*game.cover?.image.map {
|
||||
Image(uiImage: $0)
|
||||
.resizable()
|
||||
.padding(10)
|
||||
.cornerRadius(5)
|
||||
}*/
|
||||
Text("\(self.gameStore.fetchLimit)")
|
||||
}
|
||||
.frame(width: 100, height: 100)
|
||||
.background(Color(UIColor.lightGray))
|
||||
.cornerRadius(5)
|
||||
|
||||
Text("\(game.name!)")
|
||||
.font(.caption)
|
||||
.frame(width: 100)
|
||||
|
||||
}.padding(.leading, 15)
|
||||
}.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
}.padding(.trailing, 15)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var GameSeriesOverview : some View {
|
||||
VStack(alignment: .leading) {
|
||||
OverviewHeader(title: "Spielserien", destination: GameSeriesAllView())
|
||||
|
||||
if gameSeriesStore.gameSeries.count == 0 {
|
||||
Text("No game series")
|
||||
}else{
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(alignment: .top, spacing: 0) {
|
||||
ForEach(gameSeriesStore.gameSeries) { gameSeries in
|
||||
NavigationLink(destination: GameSeriesLibraryView(gameSeries: gameSeries)) {
|
||||
VStack(alignment: .leading) {
|
||||
Group {
|
||||
/*game.cover?.image.map {
|
||||
Image(uiImage: $0)
|
||||
.resizable()
|
||||
.padding(10)
|
||||
.cornerRadius(5)
|
||||
}*/
|
||||
Text("S")
|
||||
}
|
||||
.frame(width: 100, height: 100)
|
||||
.background(Color(UIColor.lightGray))
|
||||
.cornerRadius(5)
|
||||
|
||||
Text("\(gameSeries.name)")
|
||||
.font(.caption)
|
||||
.frame(width: 100)
|
||||
|
||||
}.padding(.leading, 15)
|
||||
}.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
}.padding(.trailing, 15)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var featured : some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Text("Gerade Aktuell")
|
||||
.font(.headline)
|
||||
.padding(.leading, 15)
|
||||
.padding(.top, 5)
|
||||
Spacer()
|
||||
}
|
||||
HStack {
|
||||
Spacer()
|
||||
if featuredStore.featuredConsole != nil {
|
||||
NavigationLink(destination: ConsoleLibraryView(console: featuredStore.featuredConsole!)) {
|
||||
if featuredStore.featuredConsole?.logo?.image != nil {
|
||||
featuredStore.featuredConsole?.logo?.image.map {
|
||||
Image(uiImage: $0).resizable().frame(width: 200, height: 200)
|
||||
}
|
||||
}else{
|
||||
//TODO: Symbol für fehlendes Bild
|
||||
Image(systemName: "cave").frame(width: 200, height: 200)
|
||||
}
|
||||
}.buttonStyle(PlainButtonStyle())
|
||||
}else {
|
||||
Text("No featured console")
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
ScrollView(.vertical, showsIndicators: true) {
|
||||
VStack {
|
||||
featured
|
||||
Divider()
|
||||
ConsolesOverview
|
||||
Divider()
|
||||
GamesOverview
|
||||
Divider()
|
||||
GameSeriesOverview
|
||||
}.navigationBarTitle("Zockerhöhle")
|
||||
}.navigationBarItems(trailing:
|
||||
NavigationLink(destination: SettingsView(), label: { Image(systemName: "gear") })
|
||||
)
|
||||
}.navigationViewStyle(StackNavigationViewStyle())
|
||||
|
||||
}
|
||||
}
|
||||
54
Zockerhoehle/Views/SettingsView.swift
Normal file
54
Zockerhoehle/Views/SettingsView.swift
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Settings.swift
|
||||
// Zockerhoehle
|
||||
//
|
||||
// Created by Julian-Steffen Müller on 20.11.19.
|
||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
//extension String: Identifiable {
|
||||
// public var id: String {
|
||||
// return self
|
||||
// }
|
||||
//}
|
||||
|
||||
struct SettingsView: View {
|
||||
@State var backupImportFileIndex = -1
|
||||
@State var backupImportUpdateExistingEntrys = false
|
||||
@State var importFiles : [String] = LibraryImport().backupFiles()
|
||||
|
||||
func exportLibrary() {
|
||||
let games = GameStore().games
|
||||
let consoles = ConsoleStore().consoles
|
||||
let gameSeries = GameSeriesStore().gameSeries
|
||||
let accessories = AccessoryStore().accessories
|
||||
|
||||
let libExport = LibraryExporter(games: games, consoles: consoles, gameSeries: gameSeries, accessories: accessories)
|
||||
|
||||
libExport.export(name: Date().formattedInTimeZone())
|
||||
importFiles = LibraryImport().backupFiles()
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section(header: Text("Backup Library")) {
|
||||
Button(action: { self.exportLibrary() }, label: { Text("Do Backup") })
|
||||
}
|
||||
|
||||
Section(header: Text("Restore Library")) {
|
||||
Picker(selection: $backupImportFileIndex, label: Text("Choose Backup")) {
|
||||
Text("None").tag(-1)
|
||||
ForEach(0 ..< (importFiles.count), id: \.self) {
|
||||
Text(LibraryImport.backupName(from: self.importFiles[$0]) ?? "n/a").tag($0)
|
||||
}.navigationBarTitle("Backups")
|
||||
}
|
||||
Toggle("Yes, I want to reset my Database", isOn: $backupImportUpdateExistingEntrys)
|
||||
Button(action: {
|
||||
LibraryImport().importLIB(from: self.importFiles[self.backupImportFileIndex])
|
||||
}, label: { Text("Reset & Import") }).disabled(backupImportFileIndex < 0 || !backupImportUpdateExistingEntrys)
|
||||
}
|
||||
}.navigationBarTitle("Einstellungen")
|
||||
}
|
||||
}
|
||||
16
Zockerhoehle/Zockerhoehle.entitlements
Normal file
16
Zockerhoehle/Zockerhoehle.entitlements
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.icloud-container-identifiers</key>
|
||||
<array>
|
||||
<string>iCloud.Zockerhoehle</string>
|
||||
</array>
|
||||
<key>com.apple.developer.icloud-services</key>
|
||||
<array>
|
||||
<string>CloudKit</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,20 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="14865.6" systemVersion="18F132" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="18154" systemVersion="20B29" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier="">
|
||||
<entity name="Accessory" representedClassName="Accessory" syncable="YES">
|
||||
<attribute name="circumstances" optional="YES" attributeType="String"/>
|
||||
<attribute name="color" optional="YES" attributeType="String"/>
|
||||
<attribute name="inWishlist" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="lentTo" optional="YES" attributeType="String"/>
|
||||
<attribute name="manufacturer" optional="YES" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="uuid" optional="YES" attributeType="UUID" defaultValueString="00000000-0000-0000-0000-000000000000" usesScalarValueType="NO"/>
|
||||
<relationship name="console" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Console" inverseName="accessories" inverseEntity="Console"/>
|
||||
</entity>
|
||||
<entity name="Console" representedClassName="Console" syncable="YES">
|
||||
<attribute name="circumstances" optional="YES" attributeType="String"/>
|
||||
<attribute name="generation" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="manufacturer" optional="YES" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<relationship name="accessories" toMany="YES" deletionRule="Nullify" destinationEntity="Accessory" inverseName="console" inverseEntity="Accessory"/>
|
||||
<relationship name="games" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="console" inverseEntity="Game"/>
|
||||
<attribute name="name" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="shortName" optional="YES" attributeType="String"/>
|
||||
<attribute name="uuid" optional="YES" attributeType="UUID" defaultValueString="00000000-0000-0000-0000-000000000000" usesScalarValueType="NO"/>
|
||||
<relationship name="accessories" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Accessory" inverseName="console" inverseEntity="Accessory"/>
|
||||
<relationship name="games" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="console" inverseEntity="Game"/>
|
||||
<relationship name="logo" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Logo" inverseName="console" inverseEntity="Logo"/>
|
||||
</entity>
|
||||
<entity name="Cover" representedClassName="Cover" syncable="YES">
|
||||
@@ -23,12 +27,15 @@
|
||||
</entity>
|
||||
<entity name="Game" representedClassName="Game" syncable="YES">
|
||||
<attribute name="circumstances" optional="YES" attributeType="String"/>
|
||||
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="inWishlist" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="isDigital" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="isFinished" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<attribute name="lentTo" optional="YES" attributeType="String"/>
|
||||
<attribute name="name" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="notes" optional="YES" attributeType="String"/>
|
||||
<attribute name="publisher" optional="YES" attributeType="String"/>
|
||||
<attribute name="uuid" optional="YES" attributeType="UUID" defaultValueString="00000000-0000-0000-0000-000000000000" usesScalarValueType="NO"/>
|
||||
<relationship name="console" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Console" inverseName="games" inverseEntity="Console"/>
|
||||
<relationship name="cover" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Cover" inverseName="game" inverseEntity="Cover"/>
|
||||
<relationship name="series" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="GameSeries" inverseName="games" inverseEntity="GameSeries"/>
|
||||
@@ -37,20 +44,26 @@
|
||||
</fetchedProperty>
|
||||
</entity>
|
||||
<entity name="GameSeries" representedClassName="GameSeries" syncable="YES">
|
||||
<attribute name="cover" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" allowsExternalBinaryDataStorage="YES"/>
|
||||
<attribute name="name" optional="YES" attributeType="String"/>
|
||||
<relationship name="games" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="series" inverseEntity="Game"/>
|
||||
<attribute name="name" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="uuid" optional="YES" attributeType="UUID" defaultValueString="00000000-0000-0000-0000-000000000000" usesScalarValueType="NO"/>
|
||||
<relationship name="cover" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="GameSeriesCover" inverseName="gameSeries" inverseEntity="GameSeriesCover"/>
|
||||
<relationship name="games" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="series" inverseEntity="Game"/>
|
||||
</entity>
|
||||
<entity name="GameSeriesCover" representedClassName="GameSeriesCover" syncable="YES">
|
||||
<attribute name="image" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData"/>
|
||||
<relationship name="gameSeries" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="GameSeries" inverseName="cover" inverseEntity="GameSeries"/>
|
||||
</entity>
|
||||
<entity name="Logo" representedClassName="Logo" syncable="YES">
|
||||
<attribute name="image" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData"/>
|
||||
<relationship name="console" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Console" inverseName="logo" inverseEntity="Console"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="Accessory" positionX="-265.9140625" positionY="29.15625" width="128" height="133"/>
|
||||
<element name="Console" positionX="-535.7890625" positionY="56.03515625" width="128" height="148"/>
|
||||
<element name="Cover" positionX="-66.69921875" positionY="223.48046875" width="128" height="73"/>
|
||||
<element name="Game" positionX="-288.828125" positionY="276.7421875" width="128" height="221"/>
|
||||
<element name="GameSeries" positionX="-686.828125" positionY="359.20703125" width="128" height="88"/>
|
||||
<element name="Accessory" positionX="-265.9140625" positionY="29.15625" width="128" height="149"/>
|
||||
<element name="Console" positionX="-535.7890625" positionY="56.03515625" width="128" height="164"/>
|
||||
<element name="Cover" positionX="-66.69921875" positionY="223.48046875" width="128" height="59"/>
|
||||
<element name="Game" positionX="-288.828125" positionY="276.7421875" width="128" height="245"/>
|
||||
<element name="GameSeries" positionX="-686.828125" positionY="359.20703125" width="128" height="89"/>
|
||||
<element name="GameSeriesCover" positionX="-477" positionY="180" width="128" height="59"/>
|
||||
<element name="Logo" positionX="-66.7109375" positionY="110.9765625" width="128" height="73"/>
|
||||
</elements>
|
||||
</model>
|
||||
Reference in New Issue
Block a user