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;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 50;
|
objectVersion = 52;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
B926F12D2149B264004D36B7 /* FlockeEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F12C2149B264004D36B7 /* FlockeEntry.swift */; };
|
B90E03EB238557D900E79643 /* LibraryImport.swift in Sources */ = {isa = PBXBuildFile; fileRef = B90E03EA238557D900E79643 /* LibraryImport.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 */; };
|
|
||||||
B926F14721502D53004D36B7 /* CodableExtensionAny.swift in Sources */ = {isa = PBXBuildFile; fileRef = B926F14621502D53004D36B7 /* CodableExtensionAny.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 */; };
|
B93C1B9D21496BFD0014FD6E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93C1B9C21496BFD0014FD6E /* AppDelegate.swift */; };
|
||||||
B93C1BA421496BFE0014FD6E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B93C1BA321496BFE0014FD6E /* Assets.xcassets */; };
|
B93C1BA421496BFE0014FD6E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B93C1BA321496BFE0014FD6E /* Assets.xcassets */; };
|
||||||
B93D60CE22D88F5700DD390F /* AccessoryDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */; };
|
B93D60CE22D88F5700DD390F /* AccessoryDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */; };
|
||||||
B93D60D122E5009700DD390F /* GameViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93D60D022E5009700DD390F /* GameViewModel.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 */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
B94CB50A22D1352F0029BFAD /* Logo+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB4FE22D1352F0029BFAD /* Logo+CoreDataProperties.swift */; };
|
||||||
B94CB53722D3B3CC0029BFAD /* GameDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94CB53622D3B3CC0029BFAD /* GameDetailView.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 */; };
|
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 */; };
|
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 */; };
|
B9BCF4CA2168ACB600ECBAAC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B9BCF4C92168ACB600ECBAAC /* LaunchScreen.storyboard */; };
|
||||||
B9D2C6F722E98ED800797F67 /* AccessoryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D2C6F622E98ED800797F67 /* AccessoryViewModel.swift */; };
|
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 */; };
|
B9F44ABA22F312E600FC6B29 /* ConsoleLibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AB922F312E600FC6B29 /* ConsoleLibraryView.swift */; };
|
||||||
B9F44ABE22F31DEF00FC6B29 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44ABD22F31DEF00FC6B29 /* SceneDelegate.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 */; };
|
B9F44AE522F418F600FC6B29 /* ConsoleStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AE422F418F600FC6B29 /* ConsoleStore.swift */; };
|
||||||
B9F44AE722F429D300FC6B29 /* GameStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AE622F429D300FC6B29 /* GameStore.swift */; };
|
B9F44AE722F429D300FC6B29 /* GameStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AE622F429D300FC6B29 /* GameStore.swift */; };
|
||||||
B9F44AE922F4655600FC6B29 /* AccessoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AE822F4655600FC6B29 /* AccessoryStore.swift */; };
|
B9F44AE922F4655600FC6B29 /* AccessoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F44AE822F4655600FC6B29 /* AccessoryStore.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* 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 */
|
/* Begin PBXFileReference section */
|
||||||
B926F12C2149B264004D36B7 /* FlockeEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlockeEntry.swift; sourceTree = "<group>"; };
|
B90E03EA238557D900E79643 /* LibraryImport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryImport.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>"; };
|
|
||||||
B926F14621502D53004D36B7 /* CodableExtensionAny.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableExtensionAny.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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
B9F44AE822F4655600FC6B29 /* AccessoryStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessoryStore.swift; sourceTree = "<group>"; };
|
||||||
@@ -90,6 +131,9 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
B98CBBD2264E933A00B1B7AC /* CloudKit.framework in Frameworks */,
|
||||||
|
B9EC098523854C24004BC9AB /* QGrid in Frameworks */,
|
||||||
|
B97AD2E0244CE4B4004AF00D /* Disk in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -99,36 +143,26 @@
|
|||||||
B90B64A12235909900E54BA3 /* Frameworks */ = {
|
B90B64A12235909900E54BA3 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
B98CBBD1264E933A00B1B7AC /* CloudKit.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
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 */ = {
|
B926F136214AE2E3004D36B7 /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
B94CB53622D3B3CC0029BFAD /* GameDetailView.swift */,
|
B9E2A07A233B6A8F00EAEB14 /* GameSeriesEditView.swift */,
|
||||||
|
B9A0550422F8CB400054D9A0 /* GameSeriesLibraryView.swift */,
|
||||||
|
B9A0550022F8C22D0054D9A0 /* GameSeriesAllView.swift */,
|
||||||
B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */,
|
B93D60CD22D88F5700DD390F /* AccessoryDetailView.swift */,
|
||||||
|
B94CB53622D3B3CC0029BFAD /* GameDetailView.swift */,
|
||||||
|
B94112E3233B597D00159AE4 /* ConsoleEditView.swift */,
|
||||||
B9F44AB922F312E600FC6B29 /* ConsoleLibraryView.swift */,
|
B9F44AB922F312E600FC6B29 /* ConsoleLibraryView.swift */,
|
||||||
B9F44AE222F3216F00FC6B29 /* ConsolesListView.swift */,
|
B9E2A07C233B6E4F00EAEB14 /* ConsoleAllView.swift */,
|
||||||
|
B94112DF233A4EF800159AE4 /* GamePickupsView.swift */,
|
||||||
|
B9A0550222F8C2740054D9A0 /* MainView.swift */,
|
||||||
|
B9EC0986238555BF004BC9AB /* SettingsView.swift */,
|
||||||
|
B9839982233A086A002F9946 /* Overview.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -136,20 +170,15 @@
|
|||||||
B926F13A214AF21B004D36B7 /* Utils */ = {
|
B926F13A214AF21B004D36B7 /* Utils */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
B926F138214AE884004D36B7 /* FlockeWS.swift */,
|
B926F14621502D53004D36B7 /* CodableExtensionAny.swift */,
|
||||||
B9F002E42187AA3200E12B0A /* FlockeConnector.swift */,
|
B94112DD233A37DD00159AE4 /* DateConversion.swift */,
|
||||||
|
B98B2FAB232C0F8C00606DC4 /* ImagePicker.swift */,
|
||||||
|
B9EC09812383F94B004BC9AB /* LibraryExport.swift */,
|
||||||
|
B90E03EA238557D900E79643 /* LibraryImport.swift */,
|
||||||
);
|
);
|
||||||
path = Utils;
|
path = Utils;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
B926F14821502D7F004D36B7 /* Lib */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
B926F14621502D53004D36B7 /* CodableExtensionAny.swift */,
|
|
||||||
);
|
|
||||||
path = Lib;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
B93C1B9021496BFD0014FD6E = {
|
B93C1B9021496BFD0014FD6E = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -171,13 +200,11 @@
|
|||||||
B93C1B9B21496BFD0014FD6E /* Zockerhoehle */ = {
|
B93C1B9B21496BFD0014FD6E /* Zockerhoehle */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
B98CBBD0264E933400B1B7AC /* Zockerhoehle.entitlements */,
|
||||||
B93D60CF22E5006F00DD390F /* ViewModel */,
|
B93D60CF22E5006F00DD390F /* ViewModel */,
|
||||||
B98A734622BACA9C00FB3410 /* CDModel */,
|
B98A734622BACA9C00FB3410 /* CDModel */,
|
||||||
B926F14821502D7F004D36B7 /* Lib */,
|
|
||||||
B926F13A214AF21B004D36B7 /* Utils */,
|
B926F13A214AF21B004D36B7 /* Utils */,
|
||||||
B926F136214AE2E3004D36B7 /* Views */,
|
B926F136214AE2E3004D36B7 /* Views */,
|
||||||
B926F135214AE2D4004D36B7 /* ViewController */,
|
|
||||||
B926F134214AE2C0004D36B7 /* Model */,
|
|
||||||
B93C1B9C21496BFD0014FD6E /* AppDelegate.swift */,
|
B93C1B9C21496BFD0014FD6E /* AppDelegate.swift */,
|
||||||
B9F44ABD22F31DEF00FC6B29 /* SceneDelegate.swift */,
|
B9F44ABD22F31DEF00FC6B29 /* SceneDelegate.swift */,
|
||||||
B9BCF4C92168ACB600ECBAAC /* LaunchScreen.storyboard */,
|
B9BCF4C92168ACB600ECBAAC /* LaunchScreen.storyboard */,
|
||||||
@@ -192,11 +219,15 @@
|
|||||||
B93D60CF22E5006F00DD390F /* ViewModel */ = {
|
B93D60CF22E5006F00DD390F /* ViewModel */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
B94112E1233B55B100159AE4 /* ConsoleViewModel.swift */,
|
||||||
B93D60D022E5009700DD390F /* GameViewModel.swift */,
|
B93D60D022E5009700DD390F /* GameViewModel.swift */,
|
||||||
|
B9E2A078233B69D400EAEB14 /* GameSeriesViewModel.swift */,
|
||||||
B9D2C6F622E98ED800797F67 /* AccessoryViewModel.swift */,
|
B9D2C6F622E98ED800797F67 /* AccessoryViewModel.swift */,
|
||||||
B9F44AE422F418F600FC6B29 /* ConsoleStore.swift */,
|
B9F44AE422F418F600FC6B29 /* ConsoleStore.swift */,
|
||||||
B9F44AE622F429D300FC6B29 /* GameStore.swift */,
|
B9F44AE622F429D300FC6B29 /* GameStore.swift */,
|
||||||
B9F44AE822F4655600FC6B29 /* AccessoryStore.swift */,
|
B9F44AE822F4655600FC6B29 /* AccessoryStore.swift */,
|
||||||
|
B98B2FA92328DF3400606DC4 /* GameSeriesStore.swift */,
|
||||||
|
B9E2A080233BA62100EAEB14 /* FeaturedStore.swift */,
|
||||||
);
|
);
|
||||||
path = ViewModel;
|
path = ViewModel;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -204,6 +235,11 @@
|
|||||||
B98A734622BACA9C00FB3410 /* CDModel */ = {
|
B98A734622BACA9C00FB3410 /* CDModel */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
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 */,
|
B94CB4F322D1352F0029BFAD /* Accessory+CoreDataClass.swift */,
|
||||||
B94CB4F422D1352F0029BFAD /* Accessory+CoreDataProperties.swift */,
|
B94CB4F422D1352F0029BFAD /* Accessory+CoreDataProperties.swift */,
|
||||||
B94CB4F522D1352F0029BFAD /* Cover+CoreDataClass.swift */,
|
B94CB4F522D1352F0029BFAD /* Cover+CoreDataClass.swift */,
|
||||||
@@ -212,8 +248,6 @@
|
|||||||
B94CB4F822D1352F0029BFAD /* Game+CoreDataProperties.swift */,
|
B94CB4F822D1352F0029BFAD /* Game+CoreDataProperties.swift */,
|
||||||
B94CB4F922D1352F0029BFAD /* Console+CoreDataClass.swift */,
|
B94CB4F922D1352F0029BFAD /* Console+CoreDataClass.swift */,
|
||||||
B94CB4FA22D1352F0029BFAD /* Console+CoreDataProperties.swift */,
|
B94CB4FA22D1352F0029BFAD /* Console+CoreDataProperties.swift */,
|
||||||
B94CB4FB22D1352F0029BFAD /* GameSeries+CoreDataClass.swift */,
|
|
||||||
B94CB4FC22D1352F0029BFAD /* GameSeries+CoreDataProperties.swift */,
|
|
||||||
B94CB4FD22D1352F0029BFAD /* Logo+CoreDataClass.swift */,
|
B94CB4FD22D1352F0029BFAD /* Logo+CoreDataClass.swift */,
|
||||||
B94CB4FE22D1352F0029BFAD /* Logo+CoreDataProperties.swift */,
|
B94CB4FE22D1352F0029BFAD /* Logo+CoreDataProperties.swift */,
|
||||||
);
|
);
|
||||||
@@ -231,12 +265,17 @@
|
|||||||
B93C1B9621496BFD0014FD6E /* Frameworks */,
|
B93C1B9621496BFD0014FD6E /* Frameworks */,
|
||||||
B93C1B9721496BFD0014FD6E /* Resources */,
|
B93C1B9721496BFD0014FD6E /* Resources */,
|
||||||
B90B64A4223590DA00E54BA3 /* ShellScript */,
|
B90B64A4223590DA00E54BA3 /* ShellScript */,
|
||||||
|
B983997A233A0295002F9946 /* Embed Watch Content */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = Zockerhoehle;
|
name = Zockerhoehle;
|
||||||
|
packageProductDependencies = (
|
||||||
|
B9EC098423854C24004BC9AB /* QGrid */,
|
||||||
|
B97AD2DF244CE4B4004AF00D /* Disk */,
|
||||||
|
);
|
||||||
productName = Zockerhoehle;
|
productName = Zockerhoehle;
|
||||||
productReference = B93C1B9921496BFD0014FD6E /* Zockerhoehle.app */;
|
productReference = B93C1B9921496BFD0014FD6E /* Zockerhoehle.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
@@ -247,8 +286,8 @@
|
|||||||
B93C1B9121496BFD0014FD6E /* Project object */ = {
|
B93C1B9121496BFD0014FD6E /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 0940;
|
LastSwiftUpdateCheck = 1100;
|
||||||
LastUpgradeCheck = 0940;
|
LastUpgradeCheck = 1250;
|
||||||
ORGANIZATIONNAME = "Julian-Steffen Müller";
|
ORGANIZATIONNAME = "Julian-Steffen Müller";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
B93C1B9821496BFD0014FD6E = {
|
B93C1B9821496BFD0014FD6E = {
|
||||||
@@ -266,6 +305,10 @@
|
|||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
mainGroup = B93C1B9021496BFD0014FD6E;
|
mainGroup = B93C1B9021496BFD0014FD6E;
|
||||||
|
packageReferences = (
|
||||||
|
B9EC098323854C24004BC9AB /* XCRemoteSwiftPackageReference "QGrid" */,
|
||||||
|
B97AD2DE244CE4B4004AF00D /* XCRemoteSwiftPackageReference "Disk" */,
|
||||||
|
);
|
||||||
productRefGroup = B93C1B9A21496BFD0014FD6E /* Products */;
|
productRefGroup = B93C1B9A21496BFD0014FD6E /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
@@ -296,7 +339,6 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"$(SRCROOT)/Carthage/Build/iOS/Disk.framework",
|
|
||||||
);
|
);
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
);
|
);
|
||||||
@@ -304,7 +346,8 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/usr/local/bin/carthage copy-frameworks\n";
|
shellScript = "
|
||||||
|
";
|
||||||
};
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
@@ -313,39 +356,50 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
B926F139214AE884004D36B7 /* FlockeWS.swift in Sources */,
|
B98CBBDD264E98F300B1B7AC /* Console+CoreDataClass.swift in Sources */,
|
||||||
B926F13C214C44FE004D36B7 /* Attachment.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 */,
|
B93C1B9D21496BFD0014FD6E /* AppDelegate.swift in Sources */,
|
||||||
B94CB53722D3B3CC0029BFAD /* GameDetailView.swift in Sources */,
|
B94CB53722D3B3CC0029BFAD /* GameDetailView.swift in Sources */,
|
||||||
B94CB50322D1352F0029BFAD /* Game+CoreDataClass.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 */,
|
B9F44ABA22F312E600FC6B29 /* ConsoleLibraryView.swift in Sources */,
|
||||||
B9F44ABE22F31DEF00FC6B29 /* SceneDelegate.swift in Sources */,
|
B9F44ABE22F31DEF00FC6B29 /* SceneDelegate.swift in Sources */,
|
||||||
|
B9A0550322F8C2740054D9A0 /* MainView.swift in Sources */,
|
||||||
B9D2C6F722E98ED800797F67 /* AccessoryViewModel.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 */,
|
B94CB50A22D1352F0029BFAD /* Logo+CoreDataProperties.swift in Sources */,
|
||||||
B94CB4FF22D1352F0029BFAD /* Accessory+CoreDataClass.swift in Sources */,
|
B94CB4FF22D1352F0029BFAD /* Accessory+CoreDataClass.swift in Sources */,
|
||||||
B98A734D22BAD27D00FB3410 /* Zockerhoehle.xcdatamodeld in Sources */,
|
B98A734D22BAD27D00FB3410 /* Zockerhoehle.xcdatamodeld in Sources */,
|
||||||
B93D60D122E5009700DD390F /* GameViewModel.swift in Sources */,
|
B93D60D122E5009700DD390F /* GameViewModel.swift in Sources */,
|
||||||
B9F44AE722F429D300FC6B29 /* GameStore.swift in Sources */,
|
B9F44AE722F429D300FC6B29 /* GameStore.swift in Sources */,
|
||||||
B926F12D2149B264004D36B7 /* FlockeEntry.swift in Sources */,
|
B90E03EB238557D900E79643 /* LibraryImport.swift in Sources */,
|
||||||
B98A735E22BFAA4B00FB3410 /* ConsoleLibraryViewController.swift in Sources */,
|
|
||||||
B94CB50522D1352F0029BFAD /* Console+CoreDataClass.swift in Sources */,
|
|
||||||
B94CB50922D1352F0029BFAD /* Logo+CoreDataClass.swift in Sources */,
|
B94CB50922D1352F0029BFAD /* Logo+CoreDataClass.swift in Sources */,
|
||||||
B94CB50622D1352F0029BFAD /* Console+CoreDataProperties.swift in Sources */,
|
B98CBBDC264E98DE00B1B7AC /* GameSeries+CoreDataClass.swift in Sources */,
|
||||||
B926F131214AD9E4004D36B7 /* GameCollection.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 */,
|
B93D60CE22D88F5700DD390F /* AccessoryDetailView.swift in Sources */,
|
||||||
B926F14A21502DE1004D36B7 /* ConsoleEntry.swift in Sources */,
|
B9EC09822383F94B004BC9AB /* LibraryExport.swift in Sources */,
|
||||||
B94CB50722D1352F0029BFAD /* GameSeries+CoreDataClass.swift in Sources */,
|
|
||||||
B94CB50022D1352F0029BFAD /* Accessory+CoreDataProperties.swift in Sources */,
|
B94CB50022D1352F0029BFAD /* Accessory+CoreDataProperties.swift in Sources */,
|
||||||
|
B9E2A07B233B6A8F00EAEB14 /* GameSeriesEditView.swift in Sources */,
|
||||||
B926F14721502D53004D36B7 /* CodableExtensionAny.swift in Sources */,
|
B926F14721502D53004D36B7 /* CodableExtensionAny.swift in Sources */,
|
||||||
B94CB50422D1352F0029BFAD /* Game+CoreDataProperties.swift in Sources */,
|
B94CB50422D1352F0029BFAD /* Game+CoreDataProperties.swift in Sources */,
|
||||||
B9F44AE922F4655600FC6B29 /* AccessoryStore.swift in Sources */,
|
B9F44AE922F4655600FC6B29 /* AccessoryStore.swift in Sources */,
|
||||||
B98A736022C1738800FB3410 /* CDManager.swift in Sources */,
|
B98A736022C1738800FB3410 /* CDManager.swift in Sources */,
|
||||||
B94CB50222D1352F0029BFAD /* Cover+CoreDataProperties.swift in Sources */,
|
B94CB50222D1352F0029BFAD /* Cover+CoreDataProperties.swift in Sources */,
|
||||||
B9F44AE322F3216F00FC6B29 /* ConsolesListView.swift in Sources */,
|
B9E2A07E233B6E4F00EAEB14 /* ConsoleAllView.swift in Sources */,
|
||||||
B94CB50122D1352F0029BFAD /* Cover+CoreDataClass.swift in Sources */,
|
B9EC0987238555BF004BC9AB /* SettingsView.swift in Sources */,
|
||||||
B9F44AE522F418F600FC6B29 /* ConsoleStore.swift in Sources */,
|
B9F44AE522F418F600FC6B29 /* ConsoleStore.swift in Sources */,
|
||||||
|
B9E2A079233B69D400EAEB14 /* GameSeriesViewModel.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -379,6 +433,7 @@
|
|||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
@@ -440,6 +495,7 @@
|
|||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
@@ -472,10 +528,10 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = "";
|
CODE_SIGN_ENTITLEMENTS = Zockerhoehle/Zockerhoehle.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = M9N7K3KZX9;
|
DEVELOPMENT_TEAM = 85J8CBD673;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)/Carthage/Build/iOS",
|
"$(PROJECT_DIR)/Carthage/Build/iOS",
|
||||||
@@ -485,7 +541,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "de.mm-neuemedien.Zockerhoehle";
|
PRODUCT_BUNDLE_IDENTIFIER = haus.mueller.zockerhoehle;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -497,7 +553,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = "";
|
CODE_SIGN_ENTITLEMENTS = Zockerhoehle/Zockerhoehle.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = M9N7K3KZX9;
|
DEVELOPMENT_TEAM = M9N7K3KZX9;
|
||||||
@@ -510,7 +566,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "de.mm-neuemedien.Zockerhoehle";
|
PRODUCT_BUNDLE_IDENTIFIER = haus.mueller.zockerhoehle;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -541,6 +597,38 @@
|
|||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* 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 */
|
/* Begin XCVersionGroup section */
|
||||||
B98A731722BA9E4600FB3410 /* Zockerhoehle.xcdatamodeld */ = {
|
B98A731722BA9E4600FB3410 /* Zockerhoehle.xcdatamodeld */ = {
|
||||||
isa = XCVersionGroup;
|
isa = XCVersionGroup;
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
<Workspace
|
<Workspace
|
||||||
version = "1.0">
|
version = "1.0">
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "self:Zockerhoehle.xcodeproj">
|
location = "self:">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
</Workspace>
|
</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>
|
<key>orderHint</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</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>
|
</dict>
|
||||||
<key>SuppressBuildableAutocreation</key>
|
<key>SuppressBuildableAutocreation</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
@@ -23,8 +23,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
print("disFinishLaunchung")
|
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
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 KiB |
@@ -2,7 +2,7 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"filename" : "star.png",
|
"filename" : "Image.png",
|
||||||
"scale" : "1x"
|
"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" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"filename" : "basket-supermarket.png",
|
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
|
"filename" : "Image.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
|
"filename" : "Image-1.png",
|
||||||
"scale" : "3x"
|
"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
|
application to it. This property is optional since there are legitimate
|
||||||
error conditions that could cause the creation of the store to fail.
|
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
|
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
|
||||||
if let error = error as NSError? {
|
if let error = error as NSError? {
|
||||||
// Replace this implementation with code to handle the error appropriately.
|
// Replace this implementation with code to handle the error appropriately.
|
||||||
@@ -43,6 +44,7 @@ class CDManager {
|
|||||||
fatalError("Unresolved error \(error), \(error.userInfo)")
|
fatalError("Unresolved error \(error), \(error.userInfo)")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
container.viewContext.automaticallyMergesChangesFromParent = true
|
||||||
return container
|
return container
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -53,10 +55,13 @@ class CDManager {
|
|||||||
// MARK: - Core Data Saving support
|
// MARK: - Core Data Saving support
|
||||||
|
|
||||||
func saveContext () {
|
func saveContext () {
|
||||||
persistentContainer.performBackgroundTask({(context) in
|
print("CHANGES: \(self.persistentContainer.viewContext.hasChanges)")
|
||||||
|
self.persistentContainer.performBackgroundTask({(context) in
|
||||||
|
print("Context \(context.hasChanges)")
|
||||||
if context.hasChanges {
|
if context.hasChanges {
|
||||||
do {
|
do {
|
||||||
try context.save()
|
try context.save()
|
||||||
|
print("--------------------saved-------")
|
||||||
} catch {
|
} catch {
|
||||||
// Replace this implementation with code to handle the error appropriately.
|
// 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.
|
// 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
|
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 name: String
|
||||||
@NSManaged public var inWishlist: Bool
|
@NSManaged public var inWishlist: Bool
|
||||||
@NSManaged public var console: Console?
|
@NSManaged public var console: Console?
|
||||||
|
@NSManaged public var lentTo : String?
|
||||||
|
@NSManaged public var uuid : UUID
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,96 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import CoreData
|
import CoreData
|
||||||
|
import SwiftUI
|
||||||
|
import UIKit
|
||||||
|
|
||||||
@objc(Console)
|
@objc(Console)
|
||||||
public class Console: NSManagedObject, Identifiable {
|
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 {
|
public var id : NSManagedObjectID {
|
||||||
get {
|
get {
|
||||||
return self.objectID
|
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
|
// Console+CoreDataProperties.swift
|
||||||
// Zockerhoehle
|
// Zockerhoehle
|
||||||
//
|
//
|
||||||
// Created by Julian-Steffen Müller on 06.07.19.
|
// Created by Julian-Steffen Müller on 14.05.21.
|
||||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
// Copyright © 2021 Julian-Steffen Müller. All rights reserved.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
@@ -17,11 +17,14 @@ extension Console {
|
|||||||
return NSFetchRequest<Console>(entityName: "Console")
|
return NSFetchRequest<Console>(entityName: "Console")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NSManaged public var circumstances: String?
|
||||||
@NSManaged public var generation: Int64
|
@NSManaged public var generation: Int64
|
||||||
@NSManaged public var manufacturer: String?
|
@NSManaged public var manufacturer: String?
|
||||||
@NSManaged public var name: String
|
@NSManaged public var name: String?
|
||||||
@NSManaged public var accessories: NSSet
|
@NSManaged public var shortName: String?
|
||||||
@NSManaged public var games: NSSet
|
@NSManaged public var uuid: UUID?
|
||||||
|
@NSManaged public var accessories: NSSet?
|
||||||
|
@NSManaged public var games: NSSet?
|
||||||
@NSManaged public var logo: Logo?
|
@NSManaged public var logo: Logo?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,5 +12,4 @@ import CoreData
|
|||||||
|
|
||||||
@objc(Cover)
|
@objc(Cover)
|
||||||
public class Cover: NSManagedObject {
|
public class Cover: NSManagedObject {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ extension Cover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NSManaged public var image: UIImage?
|
@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
|
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
|
// Game+CoreDataProperties.swift
|
||||||
// Zockerhoehle
|
// Zockerhoehle
|
||||||
//
|
//
|
||||||
// Created by Julian-Steffen Müller on 06.07.19.
|
// Created by Julian-Steffen Müller on 14.05.21.
|
||||||
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
// Copyright © 2021 Julian-Steffen Müller. All rights reserved.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
@@ -11,20 +11,24 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
extension Game{
|
extension Game {
|
||||||
|
|
||||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<Game> {
|
@nonobjc public class func fetchRequest() -> NSFetchRequest<Game> {
|
||||||
return NSFetchRequest<Game>(entityName: "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 inWishlist: Bool
|
||||||
@NSManaged public var isDigital: 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 notes: String?
|
||||||
@NSManaged public var publisher: String?
|
@NSManaged public var publisher: String?
|
||||||
|
@NSManaged public var uuid: UUID?
|
||||||
@NSManaged public var console: Console?
|
@NSManaged public var console: Console?
|
||||||
@NSManaged public var series: GameSeries?
|
|
||||||
@NSManaged public var cover: Cover?
|
@NSManaged public var cover: Cover?
|
||||||
|
@NSManaged public var series: GameSeries?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,65 @@
|
|||||||
// GameSeries+CoreDataClass.swift
|
// GameSeries+CoreDataClass.swift
|
||||||
// Zockerhoehle
|
// 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.
|
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import CoreData
|
import CoreData
|
||||||
|
import UIKit
|
||||||
|
|
||||||
@objc(GameSeries)
|
@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
|
// GameSeries+CoreDataProperties.swift
|
||||||
// Zockerhoehle
|
// 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.
|
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@@ -17,9 +17,10 @@ extension GameSeries {
|
|||||||
return NSFetchRequest<GameSeries>(entityName: "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 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>
|
<string>1.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
|
<key>LSApplicationCategoryType</key>
|
||||||
|
<string></string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
@@ -46,6 +48,12 @@
|
|||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>UIBackgroundModes</key>
|
||||||
|
<array>
|
||||||
|
<string>remote-notification</string>
|
||||||
|
</array>
|
||||||
|
<key>UIFileSharingEnabled</key>
|
||||||
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIRequiredDeviceCapabilities</key>
|
<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 {
|
class SceneDelegate: UIResponder, UIWindowSceneDelegate, UIApplicationDelegate {
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
|
||||||
let gameStore = GameStore(console: .none)
|
let consolesStore = ConsoleStore()
|
||||||
let consoleStore = ConsoleStore()
|
let gameSeriesStore = GameSeriesStore()
|
||||||
|
|
||||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
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`.
|
// 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
|
// Use a UIHostingController as window root view controller
|
||||||
if let windowScene = scene as? UIWindowScene {
|
if let windowScene = scene as? UIWindowScene {
|
||||||
let window = UIWindow(windowScene: windowScene)
|
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
|
self.window = window
|
||||||
window.makeKeyAndVisible()
|
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
|
self.consoleFilter = console
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||||
print("GameStore::controllerDidChangeContent")
|
print("GameStore::controllerDidChangeContent")
|
||||||
self.objectWillChange.send()
|
self.objectWillChange.send()
|
||||||
|
|||||||
@@ -10,52 +10,62 @@ import Foundation
|
|||||||
import UIKit
|
import UIKit
|
||||||
import Combine
|
import Combine
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import CoreData
|
||||||
|
|
||||||
class AccessoryViewModel : ObservableObject {
|
class AccessoryViewModel : ObservableObject {
|
||||||
var objectWillChange = ObservableObjectPublisher()
|
var objectWillChange = ObservableObjectPublisher()
|
||||||
|
|
||||||
var inWishlist : Bool {
|
var inWishlist : Bool {
|
||||||
didSet {
|
didSet {
|
||||||
if let accessory = self.accessory {
|
guard let accessory = self.accessory else { return }
|
||||||
accessory.inWishlist = inWishlist
|
|
||||||
}
|
accessory.inWishlist = inWishlist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var manufacturer : String? {
|
var manufacturer : String? {
|
||||||
didSet {
|
didSet {
|
||||||
if let accessory = self.accessory {
|
guard let accessory = self.accessory else { return }
|
||||||
accessory.manufacturer = manufacturer
|
|
||||||
}
|
accessory.manufacturer = manufacturer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var color : String? {
|
var color : String? {
|
||||||
didSet {
|
didSet {
|
||||||
if let accessory = self.accessory {
|
guard let accessory = self.accessory else { return }
|
||||||
accessory.color = color
|
|
||||||
}
|
accessory.color = color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var name : String {
|
var name : String {
|
||||||
didSet {
|
didSet {
|
||||||
if let accessory = self.accessory {
|
guard let accessory = self.accessory else { return }
|
||||||
accessory.name = name
|
|
||||||
}
|
accessory.name = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var accessory : Accessory? {
|
var lentTo : String? {
|
||||||
didSet {
|
didSet {
|
||||||
if accessory != nil {
|
guard let accessory = self.accessory else { return }
|
||||||
self.name = accessory!.name
|
|
||||||
self.inWishlist = accessory!.inWishlist
|
accessory.lentTo = lentTo;
|
||||||
self.color = accessory!.color
|
|
||||||
self.manufacturer = accessory!.manufacturer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private var accessory : Accessory? {
|
||||||
|
didSet {
|
||||||
|
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) {
|
init(accessory : Accessory) {
|
||||||
self.accessory = accessory
|
self.accessory = accessory
|
||||||
@@ -65,11 +75,24 @@ class AccessoryViewModel : ObservableObject {
|
|||||||
self.color = accessory.color
|
self.color = accessory.color
|
||||||
self.manufacturer = accessory.manufacturer
|
self.manufacturer = accessory.manufacturer
|
||||||
|
|
||||||
_ = NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange, object: CDManager.shared.viewContext).sink {
|
self.NSManagedObjectChangedObserver = NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange, object: CDManager.shared.viewContext).first().sink { notification in
|
||||||
//TODO
|
guard let accessory = self.accessory else { return }
|
||||||
self.objectWillChange.send()
|
guard let userInfo = notification.userInfo else { return }
|
||||||
if let accessory = self.accessory {
|
|
||||||
print("Accessory: \(accessory.name) Notification: \($0.description)")
|
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()
|
||||||
|
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 {
|
class GameStore : NSObject, ObservableObject, NSFetchedResultsControllerDelegate {
|
||||||
var objectWillChange = PassthroughSubject<Void , Never>()
|
var objectWillChange = PassthroughSubject<Void , Never>()
|
||||||
var consoleFilter : Console?
|
var consoleFilter : Console?
|
||||||
|
var gameSeriesFilter : GameSeries?
|
||||||
|
var sortDescriptors : [NSSortDescriptor] = [NSSortDescriptor(key: "name", ascending: true)]
|
||||||
|
var fetchLimit : Int = 0
|
||||||
|
|
||||||
var games : [Game] {
|
var games : [Game] {
|
||||||
get {
|
get {
|
||||||
if self.fetchResultsController.fetchedObjects == nil {
|
if self.fetchResultsController.fetchedObjects == nil {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try fetchResultsController.performFetch()
|
try fetchResultsController.performFetch()
|
||||||
}catch {
|
}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()
|
var gamesFetch : NSFetchRequest<Game> = Game.fetchRequest()
|
||||||
if let console = consoleFilter {
|
if let console = consoleFilter {
|
||||||
gamesFetch = Game.fetchRequest(console: console)
|
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)
|
let gamesFetchRC = NSFetchedResultsController(fetchRequest: gamesFetch, managedObjectContext: CDManager.shared.viewContext, sectionNameKeyPath: nil, cacheName: nil)
|
||||||
|
|
||||||
@@ -44,13 +67,30 @@ class GameStore : NSObject, ObservableObject, NSFetchedResultsControllerDelegate
|
|||||||
return gamesFetchRC
|
return gamesFetchRC
|
||||||
}()
|
}()
|
||||||
|
|
||||||
init(console : Console?) {
|
init(console : Console?, fetchLimit : Int = 0) {
|
||||||
super.init()
|
super.init()
|
||||||
self.consoleFilter = console
|
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>) {
|
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
|
||||||
print("GameStore::controllerDidChangeContent")
|
|
||||||
self.objectWillChange.send()
|
self.objectWillChange.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,64 +13,133 @@ import CoreData
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
class GameViewModel : ObservableObject {
|
class GameViewModel : ObservableObject {
|
||||||
var objectWillChange = ObservableObjectPublisher()
|
var objectWillChange = ObservableObjectPublisher()
|
||||||
|
|
||||||
private var game : Game? {
|
private var game : Game? {
|
||||||
didSet {
|
didSet {
|
||||||
if game != nil {
|
guard let game = game else { return }
|
||||||
self.name = game!.name
|
|
||||||
self.inWishlist = game!.inWishlist
|
self.name = game.name!
|
||||||
self.isDigital = game!.isDigital
|
self.inWishlist = game.inWishlist
|
||||||
self.isFinished = game!.isFinished
|
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 {
|
var name : String {
|
||||||
didSet {
|
didSet {
|
||||||
if let game = self.game {
|
guard let game = self.game else { return }
|
||||||
game.name = name
|
|
||||||
}
|
game.name = name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var inWishlist : Bool {
|
var inWishlist : Bool {
|
||||||
didSet {
|
didSet {
|
||||||
if let game = self.game {
|
guard let game = self.game else { return }
|
||||||
game.inWishlist = inWishlist
|
|
||||||
}
|
game.inWishlist = inWishlist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isDigital : Bool {
|
var isDigital : Bool {
|
||||||
didSet {
|
didSet {
|
||||||
if let game = self.game {
|
guard let game = self.game else { return }
|
||||||
game.isDigital = isDigital
|
|
||||||
}
|
game.isDigital = isDigital
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isFinished : Bool {
|
var isFinished : Bool {
|
||||||
didSet {
|
didSet {
|
||||||
if let game = self.game {
|
guard let game = self.game else { return }
|
||||||
game.isFinished = isFinished
|
|
||||||
|
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) {
|
init(game : Game) {
|
||||||
self.game = game
|
self.game = game
|
||||||
|
|
||||||
self.name = game.name
|
self.name = game.name!
|
||||||
self.inWishlist = game.inWishlist
|
self.inWishlist = game.inWishlist
|
||||||
self.isDigital = game.isDigital
|
self.isDigital = game.isDigital
|
||||||
self.isFinished = game.isFinished
|
self.isFinished = game.isFinished
|
||||||
|
self.gameSeries = game.series?.id ?? ""
|
||||||
|
self.lentTo = game.lentTo ?? ""
|
||||||
|
|
||||||
_ = NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange, object: CDManager.shared.viewContext).sink {
|
self.NSManagedObjectChangedObserver = NotificationCenter.default.publisher(for: .NSManagedObjectContextObjectsDidChange, object: CDManager.shared.viewContext).first().sink { notification in
|
||||||
//TODO
|
|
||||||
self.objectWillChange.send()
|
guard let game = self.game else { return }
|
||||||
if let game = self.game {
|
guard let userInfo = notification.userInfo else { return }
|
||||||
print("Game: \(game.name) Notification: \($0.description)")
|
|
||||||
|
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()
|
||||||
|
print("GameViewModel::NSMangedObjectChanged Update of \(game.name)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,3 @@ struct AccessoryDetailView : View {
|
|||||||
self.accessoryVM = accessoryVM!
|
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
|
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 {
|
struct ConsoleLibraryView : View {
|
||||||
@State var isVideogamesSelected = true
|
@State var isVideogamesSelected = true
|
||||||
@@ -16,19 +78,8 @@ struct ConsoleLibraryView : View {
|
|||||||
@ObservedObject var accessoryStore : AccessoryStore
|
@ObservedObject var accessoryStore : AccessoryStore
|
||||||
|
|
||||||
@State var showWishlist = false
|
@State var showWishlist = false
|
||||||
|
@State var showAddToConsoleLibraryModal: Bool = false
|
||||||
@State var isModal: Bool = false
|
@State var showLogoImagePicker = 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") })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
@@ -44,14 +95,29 @@ struct ConsoleLibraryView : View {
|
|||||||
if self.isVideogamesSelected {
|
if self.isVideogamesSelected {
|
||||||
List {
|
List {
|
||||||
ForEach(gameStore.games.filter({$0.inWishlist == self.showWishlist})) { game in
|
ForEach(gameStore.games.filter({$0.inWishlist == self.showWishlist})) { game in
|
||||||
NavigationLink(destination: GameDetailView(gameVM: GameViewModel(game: game))) {
|
NavigationLink(destination: GameDetailView(game: game)) {
|
||||||
Text("\(game.name)")
|
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 {
|
}else {
|
||||||
List {
|
List {
|
||||||
|
|
||||||
ForEach(accessoryStore.accessories.filter({$0.inWishlist == self.showWishlist})) { accessory in
|
ForEach(accessoryStore.accessories.filter({$0.inWishlist == self.showWishlist})) { accessory in
|
||||||
NavigationLink(destination: AccessoryDetailView(accessoryVM: AccessoryViewModel(accessory: accessory))) {
|
NavigationLink(destination: AccessoryDetailView(accessoryVM: AccessoryViewModel(accessory: accessory))) {
|
||||||
Text("\(accessory.name)")
|
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:
|
.navigationBarItems(trailing:
|
||||||
HStack {
|
HStack {
|
||||||
Button(action: {
|
NavigationLink(destination: ConsoleEditView(self.console!)) {
|
||||||
self.isModal = true
|
Image(systemName: "pencil.and.ellipsis.rectangle")
|
||||||
}) {
|
}
|
||||||
Image(systemName: "plus")
|
|
||||||
}.padding(5)
|
Button(action: { self.showAddToConsoleLibraryModal = true },
|
||||||
Button(action: {
|
label: { Image(systemName: "plus")})
|
||||||
self.showWishlist.toggle()
|
.padding(5)
|
||||||
}) {
|
|
||||||
Image(systemName: "star")
|
Button(action: { self.showWishlist.toggle()},
|
||||||
}.accentColor(self.showWishlist ? Color.red : Color.blue)
|
label: { Image("wishlist")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
})
|
||||||
|
.accentColor(self.showWishlist ? Color.red : Color.blue)
|
||||||
})
|
})
|
||||||
.sheet(isPresented: $isModal, onDismiss: {}, content: {
|
.sheet(isPresented: $showAddToConsoleLibraryModal) {
|
||||||
self.modal
|
if self.console != nil {
|
||||||
})
|
ModalAddToConsoleLibrary(modalAddToWishlist: self.showWishlist, isVideogamesSelected: true, console: self.console!)
|
||||||
|
}else{
|
||||||
|
Text("Fehler: Keine Konsole übergeben")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(console : Console?) {
|
init(console : Console?) {
|
||||||
@@ -84,11 +160,3 @@ struct ConsoleLibraryView : View {
|
|||||||
self.accessoryStore = AccessoryStore(console: console)
|
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,54 +9,146 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct GameDetailView : View {
|
struct GameDetailView : View {
|
||||||
//@Binding var g : Game
|
|
||||||
@ObservedObject var gameVM : GameViewModel
|
@ObservedObject var gameVM : GameViewModel
|
||||||
|
|
||||||
|
@State private var showDeleteAlert : Bool = false
|
||||||
@State var hasFinishedDate : Bool = false
|
@State var hasFinishedDate : Bool = false
|
||||||
@State var playthroughDate : Date = Date()
|
@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 {
|
var body: some View {
|
||||||
Form {
|
Form {
|
||||||
TextField("Videogame name", text: $gameVM.name)
|
Section {
|
||||||
|
TextField("Videogame name", text: $gameVM.name)
|
||||||
|
|
||||||
Toggle(isOn: $gameVM.isDigital, label: {
|
//Gray color should indicate immutable data
|
||||||
Text("Nur Digital")
|
Text("\(gameVM.console?.name ?? "No console")").foregroundColor(.gray)
|
||||||
})
|
|
||||||
|
|
||||||
Toggle(isOn: $gameVM.inWishlist, label: {
|
Toggle(isOn: $gameVM.isDigital, label: {
|
||||||
Text("In Wunschliste")
|
Text("Nur Digital")
|
||||||
})
|
|
||||||
|
|
||||||
Toggle(isOn: $gameVM.isFinished , label: {
|
|
||||||
Text("Durchgezockt")
|
|
||||||
})
|
|
||||||
|
|
||||||
if gameVM.isFinished {
|
|
||||||
Toggle(isOn: $hasFinishedDate, label: {
|
|
||||||
Text("Gibts ein Datum")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Toggle(isOn: $gameVM.inWishlist, label: {
|
||||||
|
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")
|
||||||
|
})
|
||||||
|
|
||||||
|
if gameVM.isFinished {
|
||||||
|
Toggle(isOn: $hasFinishedDate, label: {
|
||||||
|
Text("Gibts ein Datum")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasFinishedDate && gameVM.isFinished {
|
||||||
|
DatePicker("Durchgezockt am",
|
||||||
|
selection: $playthroughDate,
|
||||||
|
in: ...Date(),
|
||||||
|
displayedComponents: [.date])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasFinishedDate && gameVM.isFinished {
|
imageCoverSection
|
||||||
DatePicker("Durchgezockt am",
|
|
||||||
selection: $playthroughDate,
|
Section{
|
||||||
in: ...Date(),
|
gameDeleteButton
|
||||||
displayedComponents: [.date])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}.navigationBarTitle(Text("\(gameVM.name)"), displayMode: .automatic)
|
}
|
||||||
|
.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?) {
|
init(gameVM : GameViewModel?) {
|
||||||
self.gameVM = gameVM!
|
self.gameVM = gameVM!
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
init(game : Game) {
|
||||||
struct GameDetailView_Previews : PreviewProvider {
|
self.gameVM = GameViewModel(game: game)
|
||||||
static var previews: some View {
|
|
||||||
GameDetailView(gameVM: nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#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"?>
|
<?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">
|
<entity name="Accessory" representedClassName="Accessory" syncable="YES">
|
||||||
<attribute name="circumstances" optional="YES" attributeType="String"/>
|
<attribute name="circumstances" optional="YES" attributeType="String"/>
|
||||||
<attribute name="color" optional="YES" attributeType="String"/>
|
<attribute name="color" optional="YES" attributeType="String"/>
|
||||||
<attribute name="inWishlist" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
<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="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"/>
|
<relationship name="console" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Console" inverseName="accessories" inverseEntity="Console"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="Console" representedClassName="Console" syncable="YES">
|
<entity name="Console" representedClassName="Console" syncable="YES">
|
||||||
<attribute name="circumstances" optional="YES" attributeType="String"/>
|
<attribute name="circumstances" optional="YES" attributeType="String"/>
|
||||||
<attribute name="generation" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
<attribute name="generation" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
|
||||||
<attribute name="manufacturer" optional="YES" attributeType="String"/>
|
<attribute name="manufacturer" optional="YES" attributeType="String"/>
|
||||||
<attribute name="name" attributeType="String"/>
|
<attribute name="name" attributeType="String" defaultValueString=""/>
|
||||||
<relationship name="accessories" toMany="YES" deletionRule="Nullify" destinationEntity="Accessory" inverseName="console" inverseEntity="Accessory"/>
|
<attribute name="shortName" optional="YES" attributeType="String"/>
|
||||||
<relationship name="games" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="console" inverseEntity="Game"/>
|
<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"/>
|
<relationship name="logo" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Logo" inverseName="console" inverseEntity="Logo"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="Cover" representedClassName="Cover" syncable="YES">
|
<entity name="Cover" representedClassName="Cover" syncable="YES">
|
||||||
@@ -23,12 +27,15 @@
|
|||||||
</entity>
|
</entity>
|
||||||
<entity name="Game" representedClassName="Game" syncable="YES">
|
<entity name="Game" representedClassName="Game" syncable="YES">
|
||||||
<attribute name="circumstances" optional="YES" attributeType="String"/>
|
<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="inWishlist" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||||
<attribute name="isDigital" 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="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="notes" optional="YES" attributeType="String"/>
|
||||||
<attribute name="publisher" 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="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="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"/>
|
<relationship name="series" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="GameSeries" inverseName="games" inverseEntity="GameSeries"/>
|
||||||
@@ -37,20 +44,26 @@
|
|||||||
</fetchedProperty>
|
</fetchedProperty>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="GameSeries" representedClassName="GameSeries" syncable="YES">
|
<entity name="GameSeries" representedClassName="GameSeries" syncable="YES">
|
||||||
<attribute name="cover" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" allowsExternalBinaryDataStorage="YES"/>
|
<attribute name="name" attributeType="String" defaultValueString=""/>
|
||||||
<attribute name="name" optional="YES" attributeType="String"/>
|
<attribute name="uuid" optional="YES" attributeType="UUID" defaultValueString="00000000-0000-0000-0000-000000000000" usesScalarValueType="NO"/>
|
||||||
<relationship name="games" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="series" inverseEntity="Game"/>
|
<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>
|
||||||
<entity name="Logo" representedClassName="Logo" syncable="YES">
|
<entity name="Logo" representedClassName="Logo" syncable="YES">
|
||||||
<attribute name="image" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData"/>
|
<attribute name="image" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData"/>
|
||||||
<relationship name="console" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Console" inverseName="logo" inverseEntity="Console"/>
|
<relationship name="console" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Console" inverseName="logo" inverseEntity="Console"/>
|
||||||
</entity>
|
</entity>
|
||||||
<elements>
|
<elements>
|
||||||
<element name="Accessory" positionX="-265.9140625" positionY="29.15625" width="128" height="133"/>
|
<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="148"/>
|
<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="73"/>
|
<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="221"/>
|
<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="88"/>
|
<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"/>
|
<element name="Logo" positionX="-66.7109375" positionY="110.9765625" width="128" height="73"/>
|
||||||
</elements>
|
</elements>
|
||||||
</model>
|
</model>
|
||||||
Reference in New Issue
Block a user