From b880199ed3dd2bfea9a2eafba81e10fa64854b49 Mon Sep 17 00:00:00 2001 From: Daniel Sarfati Date: Wed, 7 Nov 2018 22:53:36 -0700 Subject: [PATCH] Added iOS SDK 2.0.0 (objective-c) --- .gitignore | 6 - .../Editor/Xcode.Custom.meta => Plugins.meta} | 4 +- .../Properties.meta => Plugins/iOS.meta} | 4 +- .../PBX.meta => Plugins/iOS/Zapic.meta} | 4 +- Assets/Plugins/iOS/Zapic/Controllers.meta | 8 + .../iOS/Zapic/Controllers/ZPCBannerManager.h | 6 + .../Zapic/Controllers/ZPCBannerManager.h.meta | 30 + .../iOS/Zapic/Controllers/ZPCBannerManager.m | 40 + .../Zapic/Controllers/ZPCBannerManager.m.meta | 30 + .../Plugins/iOS/Zapic/Controllers/ZPCCore.h | 25 + .../iOS/Zapic/Controllers/ZPCCore.h.meta | 30 + .../Plugins/iOS/Zapic/Controllers/ZPCCore.m | 189 +++ .../iOS/Zapic/Controllers/ZPCCore.m.meta | 30 + .../Plugins/iOS/Zapic/Controllers/ZPCErrors.h | 8 + .../iOS/Zapic/Controllers/ZPCErrors.h.meta | 30 + .../Plugins/iOS/Zapic/Controllers/ZPCErrors.m | 8 + .../iOS/Zapic/Controllers/ZPCErrors.m.meta | 30 + .../iOS/Zapic/Controllers/ZPCMessageQueue.h | 17 + .../Zapic/Controllers/ZPCMessageQueue.h.meta | 30 + .../iOS/Zapic/Controllers/ZPCMessageQueue.m | 104 ++ .../Zapic/Controllers/ZPCMessageQueue.m.meta | 30 + .../Controllers/ZPCNotificationManager.h | 9 + .../Controllers/ZPCNotificationManager.h.meta | 30 + .../Controllers/ZPCNotificationManager.m | 104 ++ .../Controllers/ZPCNotificationManager.m.meta | 30 + .../iOS/Zapic/Controllers/ZPCPlayerManager.h | 10 + .../Zapic/Controllers/ZPCPlayerManager.h.meta | 30 + .../iOS/Zapic/Controllers/ZPCPlayerManager.m | 57 + .../Zapic/Controllers/ZPCPlayerManager.m.meta | 30 + .../iOS/Zapic/Controllers/ZPCQueryManager.h | 41 + .../Zapic/Controllers/ZPCQueryManager.h.meta | 30 + .../iOS/Zapic/Controllers/ZPCQueryManager.m | 162 ++ .../Zapic/Controllers/ZPCQueryManager.m.meta | 30 + .../iOS/Zapic/Controllers/ZPCSafariManager.h | 18 + .../Zapic/Controllers/ZPCSafariManager.h.meta | 30 + .../iOS/Zapic/Controllers/ZPCSafariManager.m | 46 + .../Zapic/Controllers/ZPCSafariManager.m.meta | 30 + .../Controllers/ZPCScriptMessageHandler.h | 21 + .../ZPCScriptMessageHandler.h.meta | 30 + .../Controllers/ZPCScriptMessageHandler.m | 236 +++ .../ZPCScriptMessageHandler.m.meta | 30 + .../iOS/Zapic/Controllers/ZPCShareManager.h | 14 + .../Zapic/Controllers/ZPCShareManager.h.meta | 30 + .../iOS/Zapic/Controllers/ZPCShareManager.m | 94 ++ .../Zapic/Controllers/ZPCShareManager.m.meta | 30 + Assets/Plugins/iOS/Zapic/Controllers/Zapic.h | 124 ++ .../iOS/Zapic/Controllers/Zapic.h.meta | 30 + Assets/Plugins/iOS/Zapic/Controllers/Zapic.m | 118 ++ .../iOS/Zapic/Controllers/Zapic.m.meta | 30 + Assets/Plugins/iOS/Zapic/Info.plist | 24 + Assets/Plugins/iOS/Zapic/Info.plist.meta | 7 + Assets/Plugins/iOS/Zapic/Models.meta | 8 + .../iOS/Zapic/Models/ZPCAppStatusMessage.h | 15 + .../Zapic/Models/ZPCAppStatusMessage.h.meta | 30 + .../iOS/Zapic/Models/ZPCAppStatusMessage.m | 11 + .../Zapic/Models/ZPCAppStatusMessage.m.meta | 30 + .../iOS/Zapic/Models/ZPCBannerMessage.h | 20 + .../iOS/Zapic/Models/ZPCBannerMessage.h.meta | 30 + .../iOS/Zapic/Models/ZPCBannerMessage.m | 30 + .../iOS/Zapic/Models/ZPCBannerMessage.m.meta | 30 + .../Plugins/iOS/Zapic/Models/ZPCChallenge.h | 104 ++ .../iOS/Zapic/Models/ZPCChallenge.h.meta | 30 + .../Plugins/iOS/Zapic/Models/ZPCChallenge.m | 59 + .../iOS/Zapic/Models/ZPCChallenge.m.meta | 30 + .../Plugins/iOS/Zapic/Models/ZPCCompetition.h | 121 ++ .../iOS/Zapic/Models/ZPCCompetition.h.meta | 30 + .../Plugins/iOS/Zapic/Models/ZPCCompetition.m | 88 + .../iOS/Zapic/Models/ZPCCompetition.m.meta | 30 + Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.h | 9 + .../Plugins/iOS/Zapic/Models/ZPCPlayer.h.meta | 30 + Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.m | 15 + .../Plugins/iOS/Zapic/Models/ZPCPlayer.m.meta | 30 + .../iOS/Zapic/Models/ZPCShareMessage.h | 16 + .../iOS/Zapic/Models/ZPCShareMessage.h.meta | 30 + .../iOS/Zapic/Models/ZPCShareMessage.m | 19 + .../iOS/Zapic/Models/ZPCShareMessage.m.meta | 30 + .../Plugins/iOS/Zapic/Models/ZPCStatistic.h | 50 + .../iOS/Zapic/Models/ZPCStatistic.h.meta | 30 + .../Plugins/iOS/Zapic/Models/ZPCStatistic.m | 28 + .../iOS/Zapic/Models/ZPCStatistic.m.meta | 30 + Assets/Plugins/iOS/Zapic/Utilities.meta | 8 + .../iOS/Zapic/Utilities/ZPCImageUtils.h | 7 + .../iOS/Zapic/Utilities/ZPCImageUtils.h.meta | 30 + .../iOS/Zapic/Utilities/ZPCImageUtils.m | 21 + .../iOS/Zapic/Utilities/ZPCImageUtils.m.meta | 30 + .../iOS/Zapic/Utilities/ZPCInjectedJS.h | 5 + .../iOS/Zapic/Utilities/ZPCInjectedJS.h.meta | 30 + .../iOS/Zapic/Utilities/ZPCInjectedJS.m | 78 + .../iOS/Zapic/Utilities/ZPCInjectedJS.m.meta | 30 + Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.h | 11 + .../Plugins/iOS/Zapic/Utilities/ZPCLog.h.meta | 30 + Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.m | 43 + .../Plugins/iOS/Zapic/Utilities/ZPCLog.m.meta | 30 + Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.h | 9 + .../iOS/Zapic/Utilities/ZPCQueue.h.meta | 30 + Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.m | 32 + .../iOS/Zapic/Utilities/ZPCQueue.m.meta | 30 + .../iOS/Zapic/Utilities/ZPCSelectorHelpers.h | 7 + .../Zapic/Utilities/ZPCSelectorHelpers.h.meta | 30 + .../iOS/Zapic/Utilities/ZPCSelectorHelpers.m | 81 + .../Zapic/Utilities/ZPCSelectorHelpers.m.meta | 30 + .../Plugins/iOS/Zapic/Utilities/ZPCStorage.h | 7 + .../iOS/Zapic/Utilities/ZPCStorage.h.meta | 30 + .../Plugins/iOS/Zapic/Utilities/ZPCStorage.m | 52 + .../iOS/Zapic/Utilities/ZPCStorage.m.meta | 30 + Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.h | 12 + .../iOS/Zapic/Utilities/ZPCUtils.h.meta | 30 + Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.m | 81 + .../iOS/Zapic/Utilities/ZPCUtils.m.meta | 30 + Assets/Plugins/iOS/Zapic/Views.meta | 8 + .../iOS/Zapic/Views/ZPCBackgroundView.h | 5 + .../iOS/Zapic/Views/ZPCBackgroundView.h.meta | 30 + .../iOS/Zapic/Views/ZPCBackgroundView.m | 49 + .../iOS/Zapic/Views/ZPCBackgroundView.m.meta | 30 + Assets/Plugins/iOS/Zapic/Views/ZPCBanner.h | 11 + .../Plugins/iOS/Zapic/Views/ZPCBanner.h.meta | 30 + Assets/Plugins/iOS/Zapic/Views/ZPCBanner.m | 204 +++ .../Plugins/iOS/Zapic/Views/ZPCBanner.m.meta | 30 + Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.h | 8 + .../iOS/Zapic/Views/ZPCBaseView.h.meta | 30 + Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.m | 108 ++ .../iOS/Zapic/Views/ZPCBaseView.m.meta | 30 + Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.h | 6 + .../iOS/Zapic/Views/ZPCErrorView.h.meta | 30 + Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.m | 11 + .../iOS/Zapic/Views/ZPCErrorView.m.meta | 30 + .../Plugins/iOS/Zapic/Views/ZPCGradientBar.h | 5 + .../iOS/Zapic/Views/ZPCGradientBar.h.meta | 30 + .../Plugins/iOS/Zapic/Views/ZPCGradientBar.m | 47 + .../iOS/Zapic/Views/ZPCGradientBar.m.meta | 30 + .../Plugins/iOS/Zapic/Views/ZPCLoadingView.h | 6 + .../iOS/Zapic/Views/ZPCLoadingView.h.meta | 30 + .../Plugins/iOS/Zapic/Views/ZPCLoadingView.m | 11 + .../iOS/Zapic/Views/ZPCLoadingView.m.meta | 30 + Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.h | 16 + .../Plugins/iOS/Zapic/Views/ZPCWebApp.h.meta | 30 + Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.m | 195 +++ .../Plugins/iOS/Zapic/Views/ZPCWebApp.m.meta | 30 + .../Zapic/Editor/Xcode.Custom/AssetCatalog.cs | 834 ---------- .../Editor/Xcode.Custom/AssetCatalog.cs.meta | 13 - .../Zapic/Editor/Xcode.Custom/JsonParser.cs | 261 --- .../Editor/Xcode.Custom/JsonParser.cs.meta | 13 - .../Zapic/Editor/Xcode.Custom/PBX/Elements.cs | 109 -- Assets/Zapic/Editor/Xcode.Custom/PBX/Lexer.cs | 246 --- .../Editor/Xcode.Custom/PBX/Lexer.cs.meta | 13 - .../Zapic/Editor/Xcode.Custom/PBX/Objects.cs | 1022 ------------ .../Editor/Xcode.Custom/PBX/Objects.cs.meta | 13 - .../Zapic/Editor/Xcode.Custom/PBX/Parser.cs | 173 -- .../Editor/Xcode.Custom/PBX/Parser.cs.meta | 13 - .../Zapic/Editor/Xcode.Custom/PBX/Sections.cs | 126 -- .../Editor/Xcode.Custom/PBX/Sections.cs.meta | 13 - .../Editor/Xcode.Custom/PBX/Serializer.cs | 263 --- .../Xcode.Custom/PBX/Serializer.cs.meta | 13 - Assets/Zapic/Editor/Xcode.Custom/PBX/Utils.cs | 308 ---- .../Editor/Xcode.Custom/PBX/Utils.cs.meta | 13 - .../Editor/Xcode.Custom/PBXCapabilityType.cs | 129 -- .../Xcode.Custom/PBXCapabilityType.cs.meta | 13 - Assets/Zapic/Editor/Xcode.Custom/PBXPath.cs | 110 -- .../Zapic/Editor/Xcode.Custom/PBXPath.cs.meta | 13 - .../Zapic/Editor/Xcode.Custom/PBXProject.cs | 1425 ----------------- .../Editor/Xcode.Custom/PBXProject.cs.meta | 13 - .../Editor/Xcode.Custom/PBXProjectData.cs | 719 --------- .../Xcode.Custom/PBXProjectData.cs.meta | 13 - .../Xcode.Custom/PBXProjectExtensions.cs | 423 ----- .../Xcode.Custom/PBXProjectExtensions.cs.meta | 13 - .../Zapic/Editor/Xcode.Custom/PlistParser.cs | 423 ----- .../Editor/Xcode.Custom/PlistParser.cs.meta | 13 - .../Xcode.Custom/ProjectCapabilityManager.cs | 681 -------- .../ProjectCapabilityManager.cs.meta | 13 - .../Xcode.Custom/Properties/AssemblyInfo.cs | 35 - .../Properties/AssemblyInfo.cs.meta | 13 - Assets/Zapic/Editor/Xcode.Custom/XcScheme.cs | 71 - .../Editor/Xcode.Custom/XcScheme.cs.meta | 13 - Assets/Zapic/Editor/ZapicPostProcessBuild.cs | 69 + ....cs.meta => ZapicPostProcessBuild.cs.meta} | 4 +- Assets/Zapic/Editor/iOSBuildSettings.cs | 185 --- Assets/Zapic/Editor/iOSBuildSettings.cs.meta | 12 - Assets/Zapic/IZapicInterface.cs | 6 +- Assets/Zapic/Plugins.meta | 8 + Assets/Zapic/Plugins/iOS.meta | 8 + Assets/Zapic/Plugins/iOS/ZapicInterface.mm | 108 ++ .../Zapic/Plugins/iOS/ZapicInterface.mm.meta | 34 + Assets/Zapic/Zapic.cs | 11 +- Assets/Zapic/ZapicAndroidInterface.cs | 47 +- Assets/Zapic/ZapicEditorInterface.cs | 4 +- Assets/Zapic/ZapiciOSInterface.cs | 84 +- Scripts/install-ios-sdk.sh | 41 + 187 files changed, 5496 insertions(+), 7869 deletions(-) rename Assets/{Zapic/Editor/Xcode.Custom.meta => Plugins.meta} (62%) rename Assets/{Zapic/Editor/Xcode.Custom/Properties.meta => Plugins/iOS.meta} (62%) rename Assets/{Zapic/Editor/Xcode.Custom/PBX.meta => Plugins/iOS/Zapic.meta} (62%) create mode 100644 Assets/Plugins/iOS/Zapic/Controllers.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/Zapic.h create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/Zapic.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/Zapic.m create mode 100644 Assets/Plugins/iOS/Zapic/Controllers/Zapic.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Info.plist create mode 100644 Assets/Plugins/iOS/Zapic/Info.plist.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.h create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.m create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.h create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.m create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.h create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.m create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.h create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.m create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.h create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.m create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.h create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.m create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.h create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.m create mode 100644 Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.h create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.m create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.h create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.m create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.h create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.m create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.h create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.m create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.h create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.m create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.h create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.m create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.h create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.m create mode 100644 Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.h create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.m create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBanner.h create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBanner.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBanner.m create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBanner.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.h create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.m create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.h create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.m create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.h create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.m create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.h create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.m create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.m.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.h create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.h.meta create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.m create mode 100644 Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.m.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/AssetCatalog.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/AssetCatalog.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/JsonParser.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/JsonParser.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Elements.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Lexer.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Lexer.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Objects.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Objects.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Parser.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Parser.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Sections.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Sections.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Serializer.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Serializer.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Utils.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBX/Utils.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXCapabilityType.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXCapabilityType.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXPath.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXPath.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXProject.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXProject.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXProjectData.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXProjectData.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXProjectExtensions.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PBXProjectExtensions.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PlistParser.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/PlistParser.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/ProjectCapabilityManager.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/ProjectCapabilityManager.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/Properties/AssemblyInfo.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/Properties/AssemblyInfo.cs.meta delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/XcScheme.cs delete mode 100644 Assets/Zapic/Editor/Xcode.Custom/XcScheme.cs.meta create mode 100755 Assets/Zapic/Editor/ZapicPostProcessBuild.cs rename Assets/Zapic/Editor/{Xcode.Custom/PBX/Elements.cs.meta => ZapicPostProcessBuild.cs.meta} (71%) delete mode 100644 Assets/Zapic/Editor/iOSBuildSettings.cs delete mode 100644 Assets/Zapic/Editor/iOSBuildSettings.cs.meta create mode 100644 Assets/Zapic/Plugins.meta create mode 100644 Assets/Zapic/Plugins/iOS.meta create mode 100644 Assets/Zapic/Plugins/iOS/ZapicInterface.mm create mode 100644 Assets/Zapic/Plugins/iOS/ZapicInterface.mm.meta create mode 100755 Scripts/install-ios-sdk.sh diff --git a/.gitignore b/.gitignore index 13588a9..056c476 100644 --- a/.gitignore +++ b/.gitignore @@ -41,12 +41,6 @@ Carthage/ \.vscode/ -Assets/Plugins/iOS/ - -Assets/Plugins/ - -Assets/Plugins\.meta - unity\.log ICSharpCode\.SharpZipLib\.dll diff --git a/Assets/Zapic/Editor/Xcode.Custom.meta b/Assets/Plugins.meta similarity index 62% rename from Assets/Zapic/Editor/Xcode.Custom.meta rename to Assets/Plugins.meta index c3ea26c..efcfac5 100644 --- a/Assets/Zapic/Editor/Xcode.Custom.meta +++ b/Assets/Plugins.meta @@ -1,8 +1,6 @@ fileFormatVersion: 2 -guid: 864fe16e4560641909016963cbb6526a +guid: 606f231f0cbb54ab7853c818b6e345c3 folderAsset: yes -timeCreated: 1522126362 -licenseType: Free DefaultImporter: externalObjects: {} userData: diff --git a/Assets/Zapic/Editor/Xcode.Custom/Properties.meta b/Assets/Plugins/iOS.meta similarity index 62% rename from Assets/Zapic/Editor/Xcode.Custom/Properties.meta rename to Assets/Plugins/iOS.meta index e5ddd82..a683810 100644 --- a/Assets/Zapic/Editor/Xcode.Custom/Properties.meta +++ b/Assets/Plugins/iOS.meta @@ -1,8 +1,6 @@ fileFormatVersion: 2 -guid: 4e06bf4f1d16f4d398b90f32799a1ca0 +guid: 506768d1943294e739a974caea2bd5f7 folderAsset: yes -timeCreated: 1522126362 -licenseType: Free DefaultImporter: externalObjects: {} userData: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX.meta b/Assets/Plugins/iOS/Zapic.meta similarity index 62% rename from Assets/Zapic/Editor/Xcode.Custom/PBX.meta rename to Assets/Plugins/iOS/Zapic.meta index 2ebde26..c47c054 100644 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX.meta +++ b/Assets/Plugins/iOS/Zapic.meta @@ -1,8 +1,6 @@ fileFormatVersion: 2 -guid: eaa6dc2451adb4a0496e2348bdde1c74 +guid: 7eb99bc9a31444daebb5857fc9cd893e folderAsset: yes -timeCreated: 1522126362 -licenseType: Free DefaultImporter: externalObjects: {} userData: diff --git a/Assets/Plugins/iOS/Zapic/Controllers.meta b/Assets/Plugins/iOS/Zapic/Controllers.meta new file mode 100644 index 0000000..33b3c28 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a3abd6e62db7a4a0dac2e712e8f1f3c0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.h new file mode 100644 index 0000000..79a0d63 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.h @@ -0,0 +1,6 @@ +#import +#import "ZPCScriptMessageHandler.h" + +@interface ZPCBannerManager : NSObject +@property (nonatomic) ZPCScriptMessageHandler *messageHandler; +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.h.meta new file mode 100644 index 0000000..4862467 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 8b4a5f10ec43d44579a233809e02db10 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.m new file mode 100644 index 0000000..6ca8e7d --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.m @@ -0,0 +1,40 @@ +#import "ZPCBannerManager.h" +#import "ZPCBanner.h" +#import "ZPCImageUtils.h" +#import "ZPCUtils.h" +#import "Zapic.h" + +@implementation ZPCBannerManager + +- (void)setMessageHandler:(ZPCScriptMessageHandler *)messageHandler { + [messageHandler addBannerHandler:^(ZPCBannerMessage *message) { + UIImage *icon = message.icon; + + if (!icon) { + icon = [ZPCImageUtils getZapicLogo]; + } + + ZPCBanner *banner = [[ZPCBanner alloc] initWithTitle:message.title subtitle:message.subtitle image:icon]; + + if (message.data) { + banner.callback = ^{ + [Zapic handleInteraction:message.data]; + }; + } + + [banner show:3.0]; + }]; +} + ++ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize { + //UIGraphicsBeginImageContext(newSize); + // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution). + // Pass 1.0 to force exact pixel size. + UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0); + [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newImage; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.m.meta new file mode 100644 index 0000000..ebc222e --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCBannerManager.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 266d2dfb69b134654beae75b22a1fb9f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.h new file mode 100644 index 0000000..a518e22 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.h @@ -0,0 +1,25 @@ +#import "ZPCBackgroundView.h" +#import "ZPCNotificationManager.h" +#import "ZPCPlayerManager.h" +#import "ZPCQueryManager.h" +#import "ZPCWebApp.h" + +#import + +typedef NS_ENUM(NSUInteger, ZPCEventType) { + ZPCEventTypeGameplay, + ZPCEventTypeInteraction, +}; + +@interface ZPCCore : UIViewController +@property (readonly) ZPCPlayerManager *playerManager; +@property (readonly) ZPCNotificationManager *notificationManager; +@property (readonly, strong) ZPCScriptMessageHandler *messageHandler; +@property (nonnull, readonly) ZPCQueryManager *queryManager; + +- (void)start; +- (void)showPage:(NSString *)pageName; +- (void)showDefaultPage; +- (void)submitEvent:(ZPCEventType)eventType withPayload:(NSObject *)payload; +- (void)closePage; +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.h.meta new file mode 100644 index 0000000..4c239b5 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: ed27cd45b82d146829b1fa83c4351163 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.m new file mode 100644 index 0000000..35f4e8a --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.m @@ -0,0 +1,189 @@ +#import "ZPCCore.h" +#import "ZPCBannerManager.h" +#import "ZPCErrorView.h" +#import "ZPCLoadingView.h" +#import "ZPCLog.h" +#import "ZPCMessageQueue.h" +#import "ZPCSafariManager.h" +#import "ZPCShareManager.h" +#import "ZPCUtils.h" + +@interface ZPCCore () +@property BOOL isVisible; +@property BOOL started; +@property BOOL pageReady; +@property (readonly) ZPCErrorView *errorView; +@property (readonly) ZPCLoadingView *loadingView; +@property (readonly, strong) ZPCBannerManager *bannerManager; +@property (readonly, strong) ZPCSafariManager *safariManager; +@property (readonly, strong) ZPCShareManager *shareManager; +@property (readonly, strong) ZPCMessageQueue *messageQueue; +@property (nonatomic, strong) ZPCBackgroundView *backgroundView; +@property (nonatomic, strong) ZPCWebApp *webApp; +@end + +@implementation ZPCCore + +- (instancetype)init { + if (self = [super init]) { + _safariManager = [[ZPCSafariManager alloc] initWithController:self]; + _shareManager = [[ZPCShareManager alloc] init]; + + //Initialize the background view that will hold onto the webview + _backgroundView = [[ZPCBackgroundView alloc] init]; + _backgroundView.backgroundColor = [UIColor clearColor]; + [_backgroundView placeViewToBackground]; + + _messageHandler = [[ZPCScriptMessageHandler alloc] init]; + _messageQueue = [[ZPCMessageQueue alloc] init]; + + //Update the notifications so they can send content to the web app + _notificationManager = [[ZPCNotificationManager alloc] initWithMessageQueue:_messageQueue]; + + //Initialize the loading view + _loadingView = [[ZPCLoadingView alloc] init]; + _loadingView.viewController = self; + + //Initialize the error view + _errorView = [[ZPCErrorView alloc] init]; + _errorView.viewController = self; + + //Initialize the web app + _webApp = [[ZPCWebApp alloc] initWithHandler:_messageHandler]; + _webApp.safariManager = _safariManager; + [_backgroundView addSubview:_webApp]; + + _messageQueue.webApp = _webApp; + + //Initialize the query manager + _queryManager = [[ZPCQueryManager alloc] initWithMessageHandler:_messageHandler messageQueue:_messageQueue]; + + //Setup the banners + _bannerManager = [[ZPCBannerManager alloc] init]; + _bannerManager.messageHandler = _messageHandler; + + _playerManager = [[ZPCPlayerManager alloc] initWithHandler:_messageHandler]; + + __weak ZPCCore *weakSelf = self; + + [_messageHandler addAppStatusHandler:^(ZPCAppStatusMessage *msg) { + if (msg.status == ZPCAppStatusReady) { + [weakSelf.messageQueue sendQueuedMessages]; + self->_pageReady = YES; + } else if (msg.status == ZPCAppStatusFailed) { + //Notify the query manager that things are broken + weakSelf.queryManager.isReady = NO; + } + }]; + + [_messageHandler addClosePageHandler:^{ + [weakSelf closePage]; + }]; + + [_messageHandler addPageReadyHandler:^{ + weakSelf.view = weakSelf.webApp; + }]; + + [_messageHandler addShowPageHandler:^{ + [weakSelf showPage:@"current"]; + }]; + + [_messageHandler addShowShareHandler:^(ZPCShareMessage *msg) { + [weakSelf.shareManager share:msg]; + }]; + + _webApp.loadErrorHandler = ^{ + //Show the error page + weakSelf.view = weakSelf.errorView; + //Notify the query manager that things are broken + weakSelf.queryManager.isReady = NO; + }; + } + return self; +} + +- (void)start { + if (_started) { + [ZPCLog info:@"Zapic is already started. Start should only be called once"]; + return; + } + _started = true; + + [ZPCLog info:@"Starting Zapic"]; + + //Start loading the Zapic web app + [_webApp loadUrl:@"https://app.zapic.net"]; +} + +- (BOOL)prefersStatusBarHidden { + //Only show the status bar on iPhoneX + return UIScreen.mainScreen.nativeBounds.size.height != 2436; +} + +- (void)closePage { + [super dismissViewControllerAnimated:YES + completion:^{ + [self->_messageQueue sendMessage:ZPCWebFunctionClosePage withPayload:@""]; + [self->_backgroundView addSubview:self->_webApp]; + }]; + _isVisible = false; +} + +- (void)showDefaultPage { + [self showPage:@"default"]; +} + +- (void)showPage:(NSString *)pageName { + [ZPCLog info:@"Showing %@ page", pageName]; + + if (_pageReady) { + self.view = _webApp; + } else if (_webApp.errorLoading) { + self.view = _errorView; + } else { + self.view = _loadingView; + } + + //Trigger the web to update + [_messageQueue sendMessage:ZPCWebFunctionOpenPage withPayload:pageName]; + + if (_isVisible) { + [ZPCLog info:@"Zapic already visible"]; + return; + } + + _isVisible = true; + + [self.view.topAnchor constraintEqualToAnchor:self.topLayoutGuide.topAnchor].active = YES; + [self.view.bottomAnchor constraintEqualToAnchor:self.bottomLayoutGuide.bottomAnchor].active = YES; + + self.modalPresentationStyle = UIModalPresentationOverCurrentContext; + + UIViewController *root = [ZPCUtils getTopViewController]; + [root presentViewController:self animated:true completion:nil]; +} + +- (void)submitEvent:(ZPCEventType)eventType withPayload:(NSObject *)payload { + [ZPCLog info:@"Submitting an event to the web client"]; + + NSDictionary *msg = @{ + @"type": [ZPCCore getEventTypeName:eventType], + @"params": payload, + @"timestamp": [ZPCUtils getIsoNow], + }; + + [_messageQueue sendMessage:ZPCWebFunctionSubmitEvent withPayload:msg]; +} + ++ (NSString *)getEventTypeName:(ZPCEventType)eventType { + if (eventType == ZPCEventTypeGameplay) { + return @"gameplay"; + } else if (eventType == ZPCEventTypeInteraction) { + return @"interaction"; + } else { + [ZPCLog error:@"Unknow event type"]; + return @""; + } +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.m.meta new file mode 100644 index 0000000..a28633f --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCCore.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 5fe790d653cab442d9c2155c166c97e6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.h new file mode 100644 index 0000000..68c6a89 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.h @@ -0,0 +1,8 @@ +#import + +FOUNDATION_EXPORT NSInteger const ZPCFailedToStartError; +FOUNDATION_EXPORT NSInteger const ZPCInvalidResponseError; +FOUNDATION_EXPORT NSInteger const ZPCVersionNotSupportedError; +FOUNDATION_EXPORT NSInteger const ZPCInvalidQueryError; +FOUNDATION_EXPORT NSInteger const ZPCNetworkError; +FOUNDATION_EXPORT NSInteger const ZPCLoginRequiredError; diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.h.meta new file mode 100644 index 0000000..c528290 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: e8e72027dba234058ab40ab4c2c15806 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.m new file mode 100644 index 0000000..57ce67a --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.m @@ -0,0 +1,8 @@ +#import "ZPCErrors.h" + +NSInteger const ZPCFailedToStartError = 2600; +NSInteger const ZPCInvalidResponseError = 2601; +NSInteger const ZPCVersionNotSupportedError = 2650; +NSInteger const ZPCInvalidQueryError = 2651; +NSInteger const ZPCNetworkError = 2652; +NSInteger const ZPCLoginRequiredError = 2653; diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.m.meta new file mode 100644 index 0000000..df3e342 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCErrors.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 4a3ab28b6d55b470d9b4bfbf5b3be9b5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.h new file mode 100644 index 0000000..146e313 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.h @@ -0,0 +1,17 @@ +#import +#import "ZPCWebApp.h" + +static NSString *const ZPCWebFunctionSubmitEvent = @"SUBMIT_EVENT"; +static NSString *const ZPCWebFunctionOpenPage = @"OPEN_PAGE"; +static NSString *const ZPCWebFunctionClosePage = @"CLOSE_PAGE"; +static NSString *const ZPCWebFunctionSetDeviceToken = @"DEVICE_TOKEN"; +static NSString *const ZPCWebFunctionNotificationOpened = @"NOTIFICATION_OPENED"; +static NSString *const ZPCWebFunctionNotificationReceived = @"NOTIFICATION_RECEIVED"; +static NSString *const ZPCWebFunctionQuery = @"QUERY"; + +@interface ZPCMessageQueue : NSObject +@property (nonatomic, strong) ZPCWebApp *webApp; +- (void)sendMessage:(NSString *)function withPayload:(NSObject *)payload; +- (void)sendMessage:(NSString *)function withPayload:(NSObject *)payload isError:(BOOL)isError; +- (void)sendQueuedMessages; +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.h.meta new file mode 100644 index 0000000..79c0ec9 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 1a0a4a263cef4416fad3f303a1d6faf1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.m new file mode 100644 index 0000000..5a81a06 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.m @@ -0,0 +1,104 @@ +#import "ZPCMessageQueue.h" +#import "ZPCLog.h" +#import "ZPCQueue.h" +#import "ZPCStorage.h" + +@interface ZPCMessageQueue () +@property (strong) ZPCQueue *queue; +@property (readonly) ZPCStorage *storage; +@property NSString *queuedPageEvent; +@property BOOL readyToSend; +@end + +@implementation ZPCMessageQueue + +- (instancetype)init { + if (self = [super init]) { + _queue = [[ZPCQueue alloc] init]; + _storage = [[ZPCStorage alloc] init]; + + NSArray *savedItems = [_storage retrieve]; + + if (savedItems) { + [_queue enqueueMany:savedItems]; + } + } + return self; +} + +- (void)sendMessage:(NSString *)function withPayload:(NSObject *)payload { + [self sendMessage:function withPayload:payload isError:NO]; +} + +- (void)sendMessage:(NSString *)function withPayload:(NSObject *)payload isError:(BOOL)isError { + [ZPCLog info:@"Dispatching JS event type %@", function]; + + NSMutableDictionary *msg = [[NSMutableDictionary alloc] init]; + msg[@"type"] = function; + msg[@"payload"] = payload; + + if (isError) { + msg[@"error"] = @true; + } + + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:msg options:0 error:nil]; + NSString *json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + NSString *js = [[NSString alloc] initWithFormat:@"zapic.dispatch(%@);", json]; + + //Send the message to the web app if it's ready + if (_readyToSend) { + [self runJavaScript:js]; + } + //Queue up messages + else { + [ZPCLog info:@"Web client is not ready to run JS. Adding to queue"]; + + if (function == ZPCWebFunctionOpenPage) { + _queuedPageEvent = js; + } else if (function == ZPCWebFunctionClosePage) { + _queuedPageEvent = nil; + } else { + [_queue enqueue:js]; + + if (_queue.count > 1000) { + [_queue dequeue]; + } + + //Save the events to storage + [_storage store:_queue.data]; + } + } +} + +- (void)sendQueuedMessages { + _readyToSend = YES; + + //If there is a queued page, send it + if (_queuedPageEvent) { + [ZPCLog info:@"Resending page open request"]; + [self runJavaScript:_queuedPageEvent]; + _queuedPageEvent = nil; + } + + [ZPCLog info:@"Starting to resend %lu events", (unsigned long)_queue.count]; + + //Clears any stored events from disk + [_storage clear]; + + while (_queue.count > 0) { + NSString *jsEvent = [_queue dequeue]; + + [self runJavaScript:jsEvent]; + } + + [ZPCLog info:@"Done resending queued messages"]; +} + +- (void)runJavaScript:(NSString *)js { + if (!js) { + return; + } + [_webApp evaluateJavaScript:js]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.m.meta new file mode 100644 index 0000000..7588a1d --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCMessageQueue.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: f646890cd354e4b2fbd9339ddf645417 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.h new file mode 100644 index 0000000..d0b37f2 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.h @@ -0,0 +1,9 @@ +#import +#import "ZPCMessageQueue.h" + +@interface ZPCNotificationManager : NSObject +- (instancetype)initWithMessageQueue:(ZPCMessageQueue *)messageQueue; +- (void)registerForPushNotifications; +- (void)setDeviceToken:(NSData *)deviceToken; +- (void)receivedNotification:(NSDictionary *)userInfo; +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.h.meta new file mode 100644 index 0000000..93c16bf --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 7cfc817c181b444d6ae4aead17c4331a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.m new file mode 100644 index 0000000..7006905 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.m @@ -0,0 +1,104 @@ +#import "ZPCNotificationManager.h" +#import +#import "ZPCLog.h" +#import "Zapic.h" + +static BOOL registered = NO; +static ZPCMessageQueue *_messageQueue; + +@interface ZPCNotificationManager () +@property (readonly) ZPCMessageQueue *messageQueue; +@end + +@implementation ZPCNotificationManager + +- (instancetype)initWithMessageQueue:(ZPCMessageQueue *)messageQueue { + if (self = [super init]) { + _messageQueue = messageQueue; + } + return self; +} + +- (void)registerForPushNotifications { + if (registered) { + [ZPCLog warn:@"Already registered for push notifications, ignoring"]; + return; + } + + registered = YES; + + [ZPCLog info:@"Registering for push notifications"]; + + //iOS 10 and above + if (@available(iOS 10.0, *)) { + id callback = ^(BOOL granted, NSError *_Nullable error) { + //If the user accepts the push notifications + if (granted) { + [ZPCLog info:@"Notifications permission are granted"]; + + [UNUserNotificationCenter.currentNotificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *_Nonnull settings) { + [ZPCLog info:@"Notification authorization status %ld", (long)settings.authorizationStatus]; + + if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) { + dispatch_async(dispatch_get_main_queue(), ^(void) { + [UIApplication.sharedApplication registerForRemoteNotifications]; + }); + } + }]; + } else { + [ZPCLog info:@"Notifications permission are not granted"]; + } + }; + + //Request permission to send push notifications, aka the popup + [UNUserNotificationCenter.currentNotificationCenter requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge) completionHandler:callback]; + } else { + //iOS 9 + // let settings = UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge], categories: nil) + // UIApplication.sharedApplication().registerUserNotificationSettings(settings) + UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]; + [UIApplication.sharedApplication registerUserNotificationSettings:settings]; + + // This is an asynchronous method to retrieve a Device Token + // Callbacks are in AppDelegate.swift + // Success = didRegisterForRemoteNotificationsWithDeviceToken + // Fail = didFailToRegisterForRemoteNotificationsWithError + // UIApplication.sharedApplication().registerForRemoteNotifications() + [UIApplication.sharedApplication registerForRemoteNotifications]; + } +} + +- (void)setDeviceToken:(NSData *)deviceToken { + if (!_messageQueue) { + [ZPCLog error:@"No message queue, unable to update the device token"]; + return; + } + + const unsigned *tokenBytes = [deviceToken bytes]; + + NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x", + ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]), + ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]), + ntohl(tokenBytes[6]), ntohl(tokenBytes[7])]; + + NSDictionary *msg = @{ + @"deviceToken": hexToken, + }; + + [_messageQueue sendMessage:ZPCWebFunctionSetDeviceToken withPayload:msg]; +} + +- (void)receivedNotification:(NSDictionary *)userInfo { + UIApplicationState state = UIApplication.sharedApplication.applicationState; + NSDictionary *aps = [userInfo objectForKey:@"aps"]; + + // user tapped notification while app was in background or closed + if (state == UIApplicationStateInactive || state == UIApplicationStateBackground) { + [_messageQueue sendMessage:ZPCWebFunctionNotificationOpened withPayload:aps]; + } else { + // App is in UIApplicationStateActive (running in foreground) + [_messageQueue sendMessage:ZPCWebFunctionNotificationReceived withPayload:aps]; + } +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.m.meta new file mode 100644 index 0000000..8b98bd8 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCNotificationManager.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: dbcf24638f72d40f9989efbb9a8a6e3a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.h new file mode 100644 index 0000000..54c418d --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.h @@ -0,0 +1,10 @@ +#import +#import "ZPCPlayer.h" +#import "ZPCScriptMessageHandler.h" + +@interface ZPCPlayerManager : NSObject +@property (readonly) ZPCPlayer *player; +- (instancetype)initWithHandler:(ZPCScriptMessageHandler *)handler; +- (void)addLoginHandler:(void (^)(ZPCPlayer *))handler; +- (void)addLogoutHandler:(void (^)(ZPCPlayer *))handler; +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.h.meta new file mode 100644 index 0000000..6af04b5 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 50010322a41744d708b05c5658cf9882 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.m new file mode 100644 index 0000000..7cd68d9 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.m @@ -0,0 +1,57 @@ +#import "ZPCPlayerManager.h" + +@interface ZPCPlayerManager () +@property (nonatomic, strong) NSMutableArray *loginHandlers; +@property (nonatomic, strong) NSMutableArray *logoutHandlers; +@end + +@implementation ZPCPlayerManager + +- (instancetype)initWithHandler:(ZPCScriptMessageHandler *)handler { + if (self = [super init]) { + _loginHandlers = [[NSMutableArray alloc] init]; + _logoutHandlers = [[NSMutableArray alloc] init]; + + [handler addLoginHandler:^(ZPCPlayer *player) { + //If there is already a player logged in, log them out + if (self->_player) { + [self playerLoggedOut]; + } + + self->_player = player; + [self playerLoggedIn:player]; + }]; + + [handler addLogoutHandler:^{ + [self playerLoggedOut]; + }]; + } + return self; +} + +- (void)playerLoggedIn:(ZPCPlayer *)newPlayer { + for (id (^handler)(ZPCPlayer *) in _loginHandlers) { + handler(newPlayer); + } +} + +- (void)playerLoggedOut { + if (!_player) { + return; + } + + for (id (^handler)(ZPCPlayer *) in _logoutHandlers) { + handler(_player); + } + _player = nil; +} + +- (void)addLoginHandler:(void (^)(ZPCPlayer *))handler { + [_loginHandlers addObject:handler]; +} + +- (void)addLogoutHandler:(void (^)(ZPCPlayer *))handler { + [_logoutHandlers addObject:handler]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.m.meta new file mode 100644 index 0000000..d95f5a2 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCPlayerManager.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 5e9ece64cc93b484e8c06b36084ecb0f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.h new file mode 100644 index 0000000..3f8bbef --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.h @@ -0,0 +1,41 @@ +#import +#import "ZPCChallenge.h" +#import "ZPCCompetition.h" +#import "ZPCMessageQueue.h" +#import "ZPCScriptMessageHandler.h" +#import "ZPCStatistic.h" + +@interface ZPCQueryManager : NSObject + +@property (nonatomic) BOOL isReady; + +- (instancetype)initWithMessageHandler:(ZPCScriptMessageHandler *)messageHandler messageQueue:(ZPCMessageQueue *)messageQueue; + +/** + Gets the list of competitions. + + @param completionHandler Callback handler. + */ +- (void)getCompetitions:(void (^)(NSArray *competitions, NSError *error))completionHandler; + +/** + Gets the list of competitions. + + @param completionHandler Callback handler. + */ +- (void)getStatistics:(void (^)(NSArray *statistics, NSError *error))completionHandler; + +/** + Gets the list of challenges. + + @param completionHandler Callback handler. + */ +- (void)getChallenges:(void (^)(NSArray *statistics, NSError *error))completionHandler; + +/** + Gets the player. + + @param completionHandler Callback handler. + */ +- (void)getPlayer:(void (^)(ZPCPlayer *player, NSError *error))completionHandler; +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.h.meta new file mode 100644 index 0000000..d4b8de7 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 2244a2ef4a9dd40ae867d6b564d249ef +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.m new file mode 100644 index 0000000..ad2dcd1 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.m @@ -0,0 +1,162 @@ +#import "ZPCQueryManager.h" +#import "ZPCErrors.h" +#import "ZPCLog.h" + +typedef void (^ResponseBlock)(id response, NSError *error); + +@interface ZPCQueryManager () +@property (readonly) ZPCScriptMessageHandler *messageHandler; +@property (readonly) ZPCMessageQueue *messageQueue; +@property (nonnull, readonly) NSMutableDictionary *requests; +@property (nonnull, readonly) NSMutableDictionary *requestTypes; +@end + +@implementation ZPCQueryManager +static NSString *const CompetitionQuery = @"competitions"; +static NSString *const StatisticsQuery = @"statistics"; +static NSString *const ChallengeQuery = @"challenges"; +static NSString *const PlayerQuery = @"player"; + +static NSString *const ZPCErrorDomain = @"com.Zapic"; + +- (void)setIsReady:(BOOL)isReady { + if (isReady == _isReady) { + return; + } + + _isReady = isReady; + + //If the manager is not available, close all pending queries + if (!_isReady) { + [self failAllQueries]; + } +} + +- (instancetype)initWithMessageHandler:(ZPCScriptMessageHandler *)messageHandler messageQueue:(ZPCMessageQueue *)messageQueue { + if (self = [super init]) { + _messageQueue = messageQueue; + _messageHandler = messageHandler; + _requests = [[NSMutableDictionary alloc] init]; + _requestTypes = [[NSMutableDictionary alloc] init]; + _isReady = YES; + + __weak ZPCQueryManager *weakSelf = self; + + [_messageHandler addQueryResponseHandler:^(NSDictionary *message) { + [weakSelf handleResponse:message]; + }]; + } + return self; +} + +- (void)handleResponse:(NSDictionary *)data { + NSDictionary *payload = data[@"payload"]; + BOOL error = [data[@"error"] boolValue]; + NSString *requestId = payload[@"requestId"]; + + //Gets the callback for this request + ResponseBlock handler = [_requests objectForKey:requestId]; + NSString *dataType = [_requestTypes objectForKey:requestId]; + + if (!handler) { + [ZPCLog warn:@"Unable to find handler for requestId: %@", requestId]; + return; + } + + [_requests removeObjectForKey:requestId]; + [_requestTypes removeObjectForKey:requestId]; + + //If this is an error response, trigger the callback right away + if (error) { + NSString *msg = payload[@"errorMessage"]; + id codeObj = payload[@"errorCode"]; + NSError *error; + if (codeObj == nil) { + error = [NSError errorWithDomain:ZPCErrorDomain code:ZPCFailedToStartError userInfo:@{@"errorMsg": @"Unknown error"}]; + } else { + error = [NSError errorWithDomain:ZPCErrorDomain code:[codeObj intValue] userInfo:@{@"errorMsg": msg}]; + } + + handler(nil, error); + return; + } + + id response = nil; + id responseData = payload[@"response"]; + + if ([dataType isEqualToString:CompetitionQuery]) { + response = [ZPCCompetition decodeList:responseData]; + } else if ([dataType isEqualToString:StatisticsQuery]) { + response = [ZPCStatistic decodeList:responseData]; + } else if ([dataType isEqualToString:ChallengeQuery]) { + response = [ZPCChallenge decodeList:responseData]; + } else if ([dataType isEqualToString:PlayerQuery]) { + response = [[ZPCPlayer alloc] initWithData:responseData]; + } + + //Trigger the callback with the reponse data + handler(response, nil); +} + +- (void)sendQuery:(NSString *)dataType withCompletionHandler:(ResponseBlock)completionHandler { + //If requests cant be processed now, cancel immediately + if (!_isReady) { + NSError *error = [NSError errorWithDomain:ZPCErrorDomain + code:ZPCFailedToStartError + userInfo:nil]; + + completionHandler(nil, error); + return; + } + + //Generate a new unique id + NSString *requestId = [NSUUID UUID].UUIDString; + + //Save the callback for this request id + [_requests setObject:completionHandler forKey:requestId]; + [_requestTypes setObject:dataType forKey:requestId]; + + NSDictionary *msg = @{ + @"requestId": requestId, + @"dataType": dataType, + @"dataTypeVersion": @1 + }; + + //Send the query to JS + [_messageQueue sendMessage:ZPCWebFunctionQuery withPayload:msg]; +} + +- (void)failAllQueries { + for (NSString *requestId in _requests) { + NSError *error = [NSError errorWithDomain:ZPCErrorDomain + code:ZPCFailedToStartError + userInfo:nil]; + + //Gets the handler + ResponseBlock handler = [_requests objectForKey:requestId]; + + //Trigger the handler with the error + handler(nil, error); + } + + [_requests removeAllObjects]; + [_requestTypes removeAllObjects]; +} + +- (void)getCompetitions:(void (^)(NSArray *competitions, NSError *error))completionHandler { + [self sendQuery:CompetitionQuery withCompletionHandler:completionHandler]; +} + +- (void)getStatistics:(void (^)(NSArray *statistics, NSError *error))completionHandler { + [self sendQuery:StatisticsQuery withCompletionHandler:completionHandler]; +} + +- (void)getChallenges:(void (^)(NSArray *statistics, NSError *error))completionHandler { + [self sendQuery:ChallengeQuery withCompletionHandler:completionHandler]; +} + +- (void)getPlayer:(void (^)(ZPCPlayer *player, NSError *error))completionHandler { + [self sendQuery:PlayerQuery withCompletionHandler:completionHandler]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.m.meta new file mode 100644 index 0000000..21ff404 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCQueryManager.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 637a05a9f34e44e4882f733bc1f152e5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.h new file mode 100644 index 0000000..45b9022 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.h @@ -0,0 +1,18 @@ +#import + +@interface ZPCSafariManager : NSObject + +/** + Initialize and configure the manager with the root view controller + + @param viewController The view controller that will hold the Safari view. + @return The newly created manager. + */ +- (instancetype)initWithController:(UIViewController *)viewController; + +/** + Opens the given url in an embedded safari window + @param url The url to open. + */ +- (void)openUrl:(NSURL *)url; +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.h.meta new file mode 100644 index 0000000..e50e051 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 46a56756e4fca412385750cf9b11d35e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.m new file mode 100644 index 0000000..6d43d2f --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.m @@ -0,0 +1,46 @@ +#import "ZPCSafariManager.h" +#import +#import "ZPCLog.h" + +@interface ZPCSafariManager () +@property (readonly) UIViewController *viewController; +@end + +@implementation ZPCSafariManager + +- (instancetype)initWithController:(UIViewController *)viewController { + if (self = [super init]) { + _viewController = viewController; + } + return self; +} + +- (void)openUrl:(NSURL *)url { + if (![url.scheme isEqualToString:@"http"] && ![url.scheme isEqualToString:@"https"]) { + [ZPCLog warn:@"Unable to open scheme %@ in Safari", url.scheme]; + return; + } + + [ZPCLog info:@"Opening url %@ in safari", url.absoluteString]; + + SFSafariViewController *svc = [[SFSafariViewController alloc] initWithURL:url]; + + if (!svc) { + [ZPCLog error:@"Unable to create SFSafariViewController"]; + return; + } + + [svc setValue:self forKey:@"delegate"]; + [_viewController presentViewController:svc animated:YES completion:nil]; +} + +/** + Callback with the embedded safari view is "Done" + + @param controller The controller that is done + */ +- (void)safariViewControllerDidFinish:(id)controller { + [controller dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.m.meta new file mode 100644 index 0000000..c801850 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCSafariManager.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 36af4962af9be401f81ac1bdcfa4010f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.h new file mode 100644 index 0000000..e5e8f8d --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.h @@ -0,0 +1,21 @@ +#import +#import +#import "ZPCAppStatusMessage.h" +#import "ZPCBannerMessage.h" +#import "ZPCPlayer.h" +#import "ZPCShareMessage.h" + +static NSString *const ZPCScriptMethodName = @"dispatch"; + +@interface ZPCScriptMessageHandler : NSObject +- (void)userContentController:(id)userContentController didReceiveScriptMessage:(id)message; +- (void)addAppStatusHandler:(void (^)(ZPCAppStatusMessage *))handler; +- (void)addBannerHandler:(void (^)(ZPCBannerMessage *))handler; +- (void)addLoginHandler:(void (^)(ZPCPlayer *))handler; +- (void)addLogoutHandler:(void (^)(void))handler; +- (void)addClosePageHandler:(void (^)(void))handler; +- (void)addPageReadyHandler:(void (^)(void))handler; +- (void)addShowPageHandler:(void (^)(void))handler; +- (void)addShowShareHandler:(void (^)(ZPCShareMessage *))handler; +- (void)addQueryResponseHandler:(void (^)(NSDictionary *))handler; +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.h.meta new file mode 100644 index 0000000..363e16d --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: c94da285536a04bc59de94b17096f358 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.m new file mode 100644 index 0000000..9ad53b2 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.m @@ -0,0 +1,236 @@ +#import "ZPCScriptMessageHandler.h" +#import "ZPCLog.h" +#import "ZPCUtils.h" + +@interface ZPCScriptMessageHandler () + +@property (nonatomic, strong) NSMutableArray *bannerHandlers; +@property (nonatomic, strong) NSMutableArray *statusHandlers; +@property (nonatomic, strong) NSMutableArray *loginHandlers; +@property (nonatomic, strong) NSMutableArray *logoutHandlers; +@property (nonatomic, strong) NSMutableArray *closePageHandlers; +@property (nonatomic, strong) NSMutableArray *pageReadyHandlers; +@property (nonatomic, strong) NSMutableArray *showPageHandlers; +@property (nonatomic, strong) NSMutableArray *showShareHandlers; +@property (nonatomic, strong) NSMutableArray *queryResponseHandlers; +@end + +@implementation ZPCScriptMessageHandler + +static NSString *const AppStarted = @"APP_STARTED"; +static NSString *const AppFailed = @"APP_FAILED"; +static NSString *const ShowBanner = @"SHOW_BANNER"; +static NSString *const ShowPage = @"SHOW_PAGE"; +static NSString *const ShowShare = @"SHOW_SHARE_MENU"; +static NSString *const PageReady = @"PAGE_READY"; +static NSString *const ClosePageRequest = @"CLOSE_PAGE_REQUESTED"; +static NSString *const LoggedIn = @"LOGGED_IN"; +static NSString *const LoggedOut = @"LOGGED_OUT"; +static NSString *const QueryResponse = @"QUERY_RESPONSE"; + +- (instancetype)init { + if (self = [super init]) { + _bannerHandlers = [[NSMutableArray alloc] init]; + _statusHandlers = [[NSMutableArray alloc] init]; + _loginHandlers = [[NSMutableArray alloc] init]; + _logoutHandlers = [[NSMutableArray alloc] init]; + _closePageHandlers = [[NSMutableArray alloc] init]; + _pageReadyHandlers = [[NSMutableArray alloc] init]; + _showPageHandlers = [[NSMutableArray alloc] init]; + _showShareHandlers = [[NSMutableArray alloc] init]; + _queryResponseHandlers = [[NSMutableArray alloc] init]; + } + return self; +} + +- (void)userContentController:(id)userContentController didReceiveScriptMessage:(id)message { + NSString *name = [message valueForKey:@"name"]; + if (![name isEqualToString:ZPCScriptMethodName]) { + [ZPCLog warn:@"Received unknown method from JS"]; + return; + } + + NSDictionary *json = [message valueForKey:@"body"]; + + if (json == nil || ![json isKindOfClass:[NSDictionary class]]) { + [ZPCLog warn:@"Received invalid message format"]; + return; + } + + NSString *type = [[json valueForKey:@"type"] uppercaseString]; + + if (!type.length) { + [ZPCLog warn:@"Received a message with a missing message type"]; + return; + } + + [ZPCUtils cleanDictionary:json]; + + [self handleMessage:type withData:json]; +} + +- (void)addAppStatusHandler:(void (^)(ZPCAppStatusMessage *))handler { + [_statusHandlers addObject:handler]; +} + +- (void)addBannerHandler:(void (^)(ZPCBannerMessage *))handler { + [_bannerHandlers addObject:handler]; +} + +- (void)addClosePageHandler:(void (^)(void))handler { + [_closePageHandlers addObject:handler]; +} + +- (void)addPageReadyHandler:(void (^)(void))handler { + [_pageReadyHandlers addObject:handler]; +} + +- (void)addLoginHandler:(void (^)(ZPCPlayer *))handler { + [_loginHandlers addObject:handler]; +} + +- (void)addLogoutHandler:(void (^)(void))handler { + [_logoutHandlers addObject:handler]; +} + +- (void)addShowPageHandler:(void (^)(void))handler { + [_showPageHandlers addObject:handler]; +} + +- (void)addShowShareHandler:(void (^)(ZPCShareMessage *))handler { + [_showShareHandlers addObject:handler]; +} + +- (void)addQueryResponseHandler:(void (^)(NSDictionary *))handler { + [_queryResponseHandlers addObject:handler]; +} + +- (void)handleMessage:(nonnull NSString *)type + withData:(nonnull NSDictionary *)data { + [ZPCLog info:@"Received %@ from JS", type]; + + if ([type isEqualToString:AppStarted]) { + [self handleStatusUpdated:ZPCAppStatusReady]; + } else if ([type isEqualToString:AppFailed]) { + [self handleStatusUpdated:ZPCAppStatusFailed]; + } else if ([type isEqualToString:ClosePageRequest]) { + [self handleClosePageRequested]; + } else if ([type isEqualToString:LoggedIn]) { + [self handleLogin:data]; + } else if ([type isEqualToString:LoggedOut]) { + [self handleLogout]; + } else if ([type isEqualToString:PageReady]) { + [self handlePageReady]; + } else if ([type isEqualToString:ShowBanner]) { + [self handleBanner:data]; + } else if ([type isEqualToString:ShowPage]) { + [self handleShowPage]; + } else if ([type isEqualToString:ShowShare]) { + [self handleShowShare:data]; + } else if ([type isEqualToString:QueryResponse]) { + [self handleQueryResponse:data]; + } else { + [ZPCLog info:@"Recevied unhandled message type: %@", type]; + } +} + +- (void)handleBanner:(nonnull NSDictionary *)data { + NSDictionary *msg = data[@"payload"]; + NSString *title = msg[@"title"]; + NSString *subtitle = msg[@"subtitle"]; + NSString *metadata = msg[@"data"]; + UIImage *img = [self decodeBase64ToImage:msg[@"icon"]]; + + ZPCBannerMessage *bannerMessage = [ZPCBannerMessage bannerWithTitle:title withSubtitle:subtitle withData:metadata withIcon:img]; + + for (id (^handler)(ZPCBannerMessage *) in _bannerHandlers) { + handler(bannerMessage); + } +} + +- (void)handleShowPage { + for (id (^handler)(void) in _showPageHandlers) { + handler(); + } +} + +- (void)handleShowShare:(nonnull NSDictionary *)data { + NSDictionary *msg = data[@"payload"]; + NSString *text = msg[@"text"]; + NSString *urlStr = msg[@"url"]; + NSString *imgStr = msg[@"image"]; + NSString *target = msg[@"target"]; + NSString *subject = msg[@"subject"]; + + NSURL *url; + UIImage *img; + + if (urlStr && urlStr != (id)[NSNull null]) { + url = [NSURL URLWithString:urlStr]; + } + + if (imgStr) { + img = [self decodeBase64ToImage:imgStr]; + } + + if (!text) { + text = msg[@"body"]; + } + + ZPCShareMessage *shareMsg = [[ZPCShareMessage alloc] initWithText:text target:target subject:subject withImage:img withURL:url]; + + for (id (^handler)(ZPCShareMessage *) in _showShareHandlers) { + handler(shareMsg); + } +} + +- (void)handleLogin:(nonnull NSDictionary *)data { + NSDictionary *msg = data[@"payload"]; + ZPCPlayer *player = [[ZPCPlayer alloc] initWithData:msg]; + + for (id (^handler)(ZPCPlayer *) in _loginHandlers) { + handler(player); + } +} + +- (void)handleLogout { + for (id (^handler)(void) in _logoutHandlers) { + handler(); + } +} + +- (void)handleStatusUpdated:(ZPCAppStatus)status { + ZPCAppStatusMessage *statusMessage = [[ZPCAppStatusMessage alloc] initWithStatus:status]; + + for (id (^handler)(ZPCAppStatusMessage *) in _statusHandlers) { + handler(statusMessage); + } +} + +- (void)handleClosePageRequested { + for (id (^handler)(void) in _closePageHandlers) { + handler(); + } +} + +- (void)handlePageReady { + for (id (^handler)(void) in _pageReadyHandlers) { + handler(); + } +} + +- (void)handleQueryResponse:(nonnull NSDictionary *)data { + for (id (^handler)(NSDictionary *) in _queryResponseHandlers) { + handler(data); + } +} + +- (UIImage *)decodeBase64ToImage:(NSString *)strEncodeData { + if (!strEncodeData.length) { + return nil; + } + NSData *data = [[NSData alloc] initWithBase64EncodedString:strEncodeData options:NSDataBase64DecodingIgnoreUnknownCharacters]; + return [UIImage imageWithData:data]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.m.meta new file mode 100644 index 0000000..fcb406b --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCScriptMessageHandler.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 0e4caf90d05a7451187f3dc0968cc0f0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.h b/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.h new file mode 100644 index 0000000..e471c2e --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.h @@ -0,0 +1,14 @@ +#import +#import +#import "ZPCShareMessage.h" + +@interface ZPCShareManager : NSObject + +/** + Shows the share sheet, allowing the user to share. + + @param message Content to share + */ +- (void)share:(ZPCShareMessage *)message; + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.h.meta new file mode 100644 index 0000000..a3b6f04 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: e9c64a8b5adc24a6dbdd92b3ad1fd482 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.m b/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.m new file mode 100644 index 0000000..5fe3954 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.m @@ -0,0 +1,94 @@ +#import "ZPCShareManager.h" +#import "ZPCLog.h" +#import "ZPCUtils.h" + +@interface ZPCShareManager () +@end + +@implementation ZPCShareManager + +- (void)share:(ZPCShareMessage *)message { + NSString *target = message.target; + UIViewController *viewController = [ZPCUtils getTopViewController]; + + if (!target || [target isEqual:@"sheet"]) { + NSMutableArray *objectsToShare = [NSMutableArray array]; + + if (message.text) { + [objectsToShare addObject:message.text]; + } + + if (message.image) { + [objectsToShare addObject:message.image]; + } + + if (message.url) { + [objectsToShare addObject:message.url]; + } + + UIActivityViewController *shareController = [[UIActivityViewController alloc] initWithActivityItems:objectsToShare applicationActivities:nil]; + + [viewController presentViewController:shareController animated:YES completion:nil]; + + } else if ([target isEqual:@"sms"]) { + if (![MFMessageComposeViewController canSendText]) { + [ZPCLog error:@"Message services are not available."]; + } else { + MFMessageComposeViewController *composeVC = [[MFMessageComposeViewController alloc] init]; + composeVC.messageComposeDelegate = self; + + NSString *body = message.text; + + if (message.url) { + body = [body stringByAppendingString:[NSString stringWithFormat:@"\n%@", message.url.absoluteString]]; + } + + if (message.image) { + //Add the image as attachment + NSData *dataImg = UIImagePNGRepresentation(message.image); + [composeVC addAttachmentData:dataImg typeIdentifier:@"public.data" filename:@"Image.png"]; + } + + composeVC.body = body; + composeVC.subject = message.subject; + + // Present the view controller modally. + [viewController presentViewController:composeVC animated:YES completion:nil]; + } + } else if ([target isEqual:@"email"]) { + if (![MFMailComposeViewController canSendMail]) { + [ZPCLog error:@"Mail services are not available."]; + return; + } else { + MFMailComposeViewController *composeVC = [[MFMailComposeViewController alloc] init]; + composeVC.mailComposeDelegate = self; + + NSString *body = message.text; + + if (message.url) { + body = [body stringByAppendingString:[NSString stringWithFormat:@"\n%@", message.url.absoluteString]]; + } + + [composeVC setSubject:message.subject]; + [composeVC setMessageBody:body isHTML:YES]; + + // Present the view controller modally. + [viewController presentViewController:composeVC animated:YES completion:nil]; + } + } +} + +- (void)messageComposeViewController:(MFMessageComposeViewController *)controller + didFinishWithResult:(MessageComposeResult)result { + // Check the result or perform other tasks. // Dismiss the message compose view controller. + [controller dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)mailComposeController:(MFMailComposeViewController *)controller + didFinishWithResult:(MFMailComposeResult)result + error:(NSError *)error { + // Dismiss the mail compose view controller. + [controller dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.m.meta new file mode 100644 index 0000000..442ed28 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/ZPCShareManager.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: aef9009dc498940f0a443b00da487652 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/Zapic.h b/Assets/Plugins/iOS/Zapic/Controllers/Zapic.h new file mode 100644 index 0000000..b33ebc2 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/Zapic.h @@ -0,0 +1,124 @@ +#import +#import "ZPCChallenge.h" +#import "ZPCCompetition.h" +#import "ZPCErrors.h" +#import "ZPCPlayer.h" +#import "ZPCStatistic.h" + +@interface Zapic : NSObject + +#pragma mark - Page names + +/// The current competition +extern NSString *const ZPCPageCompetition; + +/// The challenges page with a list of all the player's challenges +extern NSString *const ZPCPageChallenges; + +/// The page that allows a player to create a new challenge +extern NSString *const ZPCPageCreateChallenge; + +/// A login and registration page +extern NSString *const ZPCPageLogin; + +/// The user's profile page +extern NSString *const ZPCPageProfile; + +/// The list of all the player's stats +extern NSString *const ZPCPageStats; + +#pragma mark - Login callbacks + +/** + The handler when a player logs in to Zapic. + */ +@property (class, nonatomic, copy, nullable) void (^loginHandler)(ZPCPlayer *); + +/** + The handler when a player logs out of Zapic. + */ +@property (class, nonatomic, copy, nullable) void (^logoutHandler)(ZPCPlayer *); + +/** + Gets the current player. nil if the player is not logged in. + Deprecated in favor of getPlayer:, this will be removed in a future version. + */ +@property (class, nonatomic, copy, nullable, readonly) ZPCPlayer *player DEPRECATED_MSG_ATTRIBUTE("Please use getPlayer:"); + +#pragma mark - Zapic Methods + +/** + Starts Zapic. + @discussion This should be called once from the AppDelegate. + Subsequent calls to this method will be ignored. + */ ++ (void)start; + +/** + Shows the specific Zapic UI page. Please check with https://www.zapic.com/docs + for a complete listing of the available pages. + + @param pageName The page to display. + */ ++ (void)showPage:(NSString *)pageName; + +/** + Show the default Zapic UI page. This should be called + from the Z button on your main menu. + */ ++ (void)showDefaultPage; + +/** + Handles an interaction event. Depending on the event parameters, Zapic may open and show + contextual information related to the specific interaction. + + @param data Dictionary that that contains a "zapic" key. + */ ++ (void)handleInteractionData:(NSDictionary *)data; + +/** + Handles an interaction event. Depending on the event parameters, Zapic may open and show + contextual information related to the specific interaction. + + @param string The zapic data string. + */ ++ (void)handleInteraction:(NSString *)string; + +/** + Handles a gameplay event with 1-N parameters. + + @param parameters Parameters + */ ++ (void)submitEvent:(NSDictionary *)parameters; + +#pragma mark - Data Queries + +/** + Gets the player. + + @param completionHandler The block to be called when the player is retrieved + */ ++ (void)getPlayer:(void (^)(ZPCPlayer *player, NSError *error))completionHandler; + +/** + Gets the list of competitions. + + @param completionHandler The block to be called when the competitions are retrieved + */ ++ (void)getCompetitions:(void (^)(NSArray *competitions, NSError *error))completionHandler; + +/** + Gets the list of statistics. + + @param completionHandler The block to be called when the statistics are retrieved + */ ++ (void)getStatistics:(void (^)(NSArray *statistics, NSError *error))completionHandler; + +/** + Gets the list of challenges. + + @param completionHandler The block to be called when the statistics are retrieved + */ ++ (void)getChallenges:(void (^)(NSArray *challenges, NSError *error))completionHandler; + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/Zapic.h.meta b/Assets/Plugins/iOS/Zapic/Controllers/Zapic.h.meta new file mode 100644 index 0000000..f24e975 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/Zapic.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: fa2123ff1db254e909b0788f7e120a12 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Controllers/Zapic.m b/Assets/Plugins/iOS/Zapic/Controllers/Zapic.m new file mode 100644 index 0000000..cc40c36 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/Zapic.m @@ -0,0 +1,118 @@ +#import "Zapic.h" +#import +#import "ZPCCore.h" +#import "ZPCLog.h" +#import "ZPCSelectorHelpers.h" + +static ZPCCore *_core; +static void (^_loginHandler)(ZPCPlayer *); +static void (^_logoutHandler)(ZPCPlayer *); + +@implementation Zapic : NSObject + +#pragma mark - Page names + +NSString *const ZPCPageChallenges = @"challenges"; +NSString *const ZPCPageCompetition = @"competition"; +NSString *const ZPCPageCreateChallenge = @"createChallenge"; +NSString *const ZPCPageLogin = @"login"; +NSString *const ZPCPageProfile = @"profile"; +NSString *const ZPCPageStats = @"stats"; + +#pragma mark - Login callbacks + ++ (void (^)(ZPCPlayer *))loginHandler { + return _loginHandler; +} + ++ (void (^)(ZPCPlayer *))logoutHandler { + return _logoutHandler; +} + ++ (void)setLoginHandler:(void (^)(ZPCPlayer *))loginHandler { + _loginHandler = loginHandler; +} + ++ (void)setLogoutHandler:(void (^)(ZPCPlayer *))logoutHandler { + _logoutHandler = logoutHandler; +} + ++ (void)initialize { + if (self == [Zapic self]) { + _core = [[ZPCCore alloc] init]; + + [_core.playerManager addLoginHandler:^(ZPCPlayer *player) { + if (_loginHandler) { + _loginHandler(player); + } + }]; + + [_core.playerManager addLogoutHandler:^(ZPCPlayer *player) { + if (_logoutHandler) { + _logoutHandler(player); + } + }]; + } +} + ++ (ZPCPlayer *)player { + return _core.playerManager.player; +} + +#pragma mark - Zapic Methods + ++ (void)start { + [_core start]; +} + ++ (void)showPage:(NSString *)pageName { + [_core showPage:pageName]; +} + ++ (void)showDefaultPage { + [_core showDefaultPage]; +} + ++ (void)handleInteractionData:(NSDictionary *)data { + if (!data) { + [ZPCLog warn:@"Missing data, unable to handleInteraction"]; + return; + } + + NSString *zapic = [data objectForKey:@"zapic"]; + + [self handleInteraction:zapic]; +} + ++ (void)handleInteraction:(NSString *)string { + if (!string) { + [ZPCLog warn:@"Interaction string must be valid string"]; + return; + } + + [_core submitEvent:ZPCEventTypeInteraction withPayload:string]; +} + ++ (void)submitEvent:(NSDictionary *)parameters { + [_core submitEvent:ZPCEventTypeGameplay withPayload:parameters]; +} + +#pragma mark - Data Queries + ++ (void)getPlayer:(void (^)(ZPCPlayer *, NSError *))completionHandler { + [_core.queryManager getPlayer:completionHandler]; +} + ++ (void)getCompetitions:(void (^)(NSArray *competitions, NSError *error))completionHandler { + [_core.queryManager getCompetitions:completionHandler]; +} + ++ (void)getStatistics:(void (^)(NSArray *statistics, NSError *error))completionHandler { + [_core.queryManager getStatistics:completionHandler]; +} + ++ (void)getChallenges:(void (^)(NSArray *challenges, NSError *error))completionHandler { + [_core.queryManager getChallenges:completionHandler]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Controllers/Zapic.m.meta b/Assets/Plugins/iOS/Zapic/Controllers/Zapic.m.meta new file mode 100644 index 0000000..e461d62 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Controllers/Zapic.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 57ba9733af96140629e02240626a3120 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Info.plist b/Assets/Plugins/iOS/Zapic/Info.plist new file mode 100644 index 0000000..d749896 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.0.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Assets/Plugins/iOS/Zapic/Info.plist.meta b/Assets/Plugins/iOS/Zapic/Info.plist.meta new file mode 100644 index 0000000..e5510ca --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Info.plist.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: af6ee0a935c28439f950bf75f944c1aa +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models.meta b/Assets/Plugins/iOS/Zapic/Models.meta new file mode 100644 index 0000000..ca4ce6d --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b5d716bb52eae4c3a9815fe4c84886c7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.h b/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.h new file mode 100644 index 0000000..a0a03a2 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.h @@ -0,0 +1,15 @@ +#import + +typedef NS_ENUM(NSInteger, ZPCAppStatus) { + ZPCAppStatusNone, + ZPCAppStatusReady, + ZPCAppStatusFailed, +}; + +@interface ZPCAppStatusMessage : NSObject + +@property (readonly, nonatomic) ZPCAppStatus status; + +- (instancetype)initWithStatus:(ZPCAppStatus)status; + +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.h.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.h.meta new file mode 100644 index 0000000..4507fac --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: a80befbff127d426e8bfdff1bd837847 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.m b/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.m new file mode 100644 index 0000000..f1a5392 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.m @@ -0,0 +1,11 @@ +#import "ZPCAppStatusMessage.h" + +@implementation ZPCAppStatusMessage + +- (instancetype)initWithStatus:(ZPCAppStatus)status { + if (self = [super init]) { + _status = status; + } + return self; +} +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.m.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.m.meta new file mode 100644 index 0000000..d9c6b98 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCAppStatusMessage.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 75e5dc82e9bdf46929c208d0f587998e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.h b/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.h new file mode 100644 index 0000000..dce7705 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.h @@ -0,0 +1,20 @@ +#import +#import + +@interface ZPCBannerMessage : NSObject + +@property (readonly, strong) NSString *title; +@property (readonly, strong) NSString *subtitle; +@property (readonly, strong) NSString *data; +@property (readonly, strong) UIImage *icon; + +- (instancetype)initWithTitle:(nonnull NSString *)title + withSubtitle:(nonnull NSString *)subtitle + withData:(nonnull NSString *)data + withIcon:(nonnull UIImage *)icon; + ++ (instancetype)bannerWithTitle:(nonnull NSString *)title + withSubtitle:(nonnull NSString *)subtitle + withData:(nonnull NSString *)data + withIcon:(nonnull UIImage *)icon; +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.h.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.h.meta new file mode 100644 index 0000000..9133ee3 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 40457627f4e574097b7eb1a4c88670e3 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.m b/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.m new file mode 100644 index 0000000..0e37830 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.m @@ -0,0 +1,30 @@ +#import "ZPCBannerMessage.h" + +@implementation ZPCBannerMessage + +- (instancetype)initWithTitle:(NSString *)title + withSubtitle:(nonnull NSString *)subtitle + withData:(nonnull NSString *)data + withIcon:(nonnull UIImage *)icon { + if (self = [super init]) { + _title = title; + _subtitle = subtitle; + _data = data; + _icon = icon; + } + return self; +} + ++ (instancetype)bannerWithTitle:(nonnull NSString *)title + withSubtitle:(nonnull NSString *)subtitle + withData:(nonnull NSString *)data + withIcon:(nonnull UIImage *)icon { + ZPCBannerMessage *message = [[ZPCBannerMessage alloc] initWithTitle:title + withSubtitle:subtitle + withData:data + withIcon:icon]; + + return message; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.m.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.m.meta new file mode 100644 index 0000000..af9980e --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCBannerMessage.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 9690189eaaec84946bd592816c18415d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.h b/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.h new file mode 100644 index 0000000..9e47655 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.h @@ -0,0 +1,104 @@ +#import + +typedef NS_ENUM(NSUInteger, ZPCChallengeStatus) { + ZPCChallengeStatusInvited, + ZPCChallengeStatusIgnored, + ZPCChallengeStatusAccepted, +}; + +@interface ZPCChallenge : NSObject + +/** + The unique id for the statistic. + */ +@property (nonnull, readonly) NSString *identifier; + +/** + The title for the challenge. + */ +@property (nullable, readonly) NSString *title; + +/** + The flag indicating if the challenge is active. + */ +@property (readonly) BOOL active; + +/** + The description. + */ +@property (nullable, readonly) NSString *textDescription; + +/** + When the challenge started. + */ +@property (nullable, readonly) NSDate *start; + +/** + When the competition ends. + */ +@property (nullable, readonly) NSDate *end; + +/** + The current player's score, formatted as defined in the portal. + */ +@property (nullable, readonly) NSString *formattedScore; + +/** + The current player's score. + */ +@property (nullable, readonly) NSNumber *score; + +/** + The developer defined metadata. + */ +@property (nullable, readonly) NSString *metadata; + +/** + The player's rank on the leaderboard (ex. Top 100). If the player + is not on the leaderboard this value will be nil. + */ +@property (nullable, readonly) NSNumber *rank; + +/** + The current player's status. + */ +@property (readonly) ZPCChallengeStatus status; + +/** +The total number of players in the challenge. + */ +@property (nullable, readonly) NSNumber *totalUsers; + +/** + Initialize a new instance from json data + + @param data Data + @return The new instance. + */ +- (instancetype)initWithData:(nonnull NSDictionary *)data; + +/** + Decode a collection of json data. + + @param data Array of json data. + @return The new challenges. + */ ++ (NSArray *)decodeList:(nonnull NSArray *)data; + +/** + Converts the status to a string. + + @param status The status. + @return The string. + */ ++ (NSString *)statusToString:(ZPCChallengeStatus)status; + +/** + Parse a status string + + @param string The string. + @return The status. + */ ++ (ZPCChallengeStatus)stringToStatus:(NSString *)string; + +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.h.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.h.meta new file mode 100644 index 0000000..6e918a3 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: f4ff3a0232f704716804cf5365f8da70 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.m b/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.m new file mode 100644 index 0000000..dede649 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.m @@ -0,0 +1,59 @@ +#import "ZPCChallenge.h" +#import "ZPCLog.h" +#import "ZPCUtils.h" + +@implementation ZPCChallenge + +- (instancetype)initWithData:(nonnull NSDictionary *)data { + if (self = [super init]) { + _identifier = data[@"id"]; + _title = data[@"title"]; + _active = [data[@"active"] boolValue]; + _textDescription = data[@"description"]; + _start = [ZPCUtils parseDateIso:data[@"start"]]; + _end = [ZPCUtils parseDateIso:data[@"end"]]; + _formattedScore = data[@"formattedScore"]; + _score = data[@"score"]; + _status = [ZPCChallenge stringToStatus:data[@"status"]]; + _metadata = data[@"metadata"]; + _rank = data[@"rank"]; + _totalUsers = data[@"totalUsers"]; + } + return self; +} + ++ (NSArray *)decodeList:(nonnull NSArray *)data { + NSMutableArray *challenges = [NSMutableArray arrayWithCapacity:data.count]; + + for (id compData in data) { + ZPCChallenge *challenge = [[ZPCChallenge alloc] initWithData:compData]; + [challenges addObject:challenge]; + } + + return challenges; +} + ++ (NSString *)statusToString:(ZPCChallengeStatus)status { + switch (status) { + case ZPCChallengeStatusIgnored: + return @"ignored"; + case ZPCChallengeStatusAccepted: + return @"ignored"; + default: + return @"invited"; + } +} ++ (ZPCChallengeStatus)stringToStatus:(NSString *)string { + if ([string isEqualToString:@"invited"]) { + return ZPCChallengeStatusInvited; + } else if ([string isEqualToString:@"accepted"]) { + return ZPCChallengeStatusAccepted; + } else if ([string isEqualToString:@"ignored"]) { + return ZPCChallengeStatusIgnored; + } else { + [ZPCLog error:@"Unknown challenge status %@", string]; + return ZPCChallengeStatusInvited; + } +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.m.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.m.meta new file mode 100644 index 0000000..8340077 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCChallenge.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 6bd2157dfc73f4b42861367540538918 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.h b/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.h new file mode 100644 index 0000000..7ea0357 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.h @@ -0,0 +1,121 @@ +#import + +typedef NS_ENUM(NSUInteger, ZPCCompetitionStatus) { + ZPCCompetitionStatusInvited, + ZPCCompetitionStatusIgnored, + ZPCCompetitionStatusAccepted, +}; + +@interface ZPCCompetition : NSObject + +#pragma mark - Competition Definition + +/** + The unique id for the competition. + */ +@property (nonnull, readonly) NSString *identifier; + +/** + The title for the competition. + */ +@property (nullable, readonly) NSString *title; + +/** + The description for the competition. + */ +@property (nullable, readonly) NSString *text; + +/** + The developer defined metadata for this competition. + */ +@property (nullable, readonly) NSString *metadata; + +/** + Flag indicating if the competition is currently active. + */ +@property (readonly) BOOL active; + +/** + When the competition starts. + */ +@property (nullable, readonly) NSDate *start; + +/** + When the competition ends. + */ +@property (nullable, readonly) NSDate *end; + +/** + The total number of users that have joined the competition. + */ +@property (nullable, readonly) NSNumber *totalUsers; + +#pragma mark - Player data + +/** + The current player's score, formatted as defined in the portal. + */ +@property (readonly) ZPCCompetitionStatus status; + +/** + The current player's score, formatted as defined in the portal. + */ +@property (nullable, readonly) NSString *formattedScore; + +/** + The current player's score. + */ +@property (nullable, readonly) NSNumber *score; + +/** + The player's rank on the leaderboard (ex. Top 100). If the player + is not on the leaderboard this value will be nil. + */ +@property (nullable, readonly) NSNumber *leaderboardRank; + +/** + The player's rank in their league. If the player + is not in a league yet this value will be nil. + */ +@property (nullable, readonly) NSNumber *leagueRank; + +- (instancetype)initWithId:(nonnull NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text + metadata:(nullable NSString *)metadata + active:(BOOL)active + start:(nullable NSDate *)start + end:(nullable NSDate *)end + totalUsers:(nullable NSNumber *)totalUsers + status:(ZPCCompetitionStatus)status + formattedScore:(nullable NSString *)formattedScore + score:(nullable NSNumber *)score + leaderboardRank:(nullable NSNumber *)leaderboardRank + leagueRank:(nullable NSNumber *)leagueRank; + +- (instancetype)initWithData:(NSDictionary *)data; + +/** + Decodes a collection of competitions + + @param data Array of competition data + @return Array of competitions + */ ++ (NSArray *)decodeList:(NSArray *)data; + +/** + Converts the status to a string. + + @param status The status. + @return The string. + */ ++ (NSString *)statusToString:(ZPCCompetitionStatus)status; + +/** + Parse a status string + + @param string The string. + @return The status. + */ ++ (ZPCCompetitionStatus)stringToStatus:(NSString *)string; +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.h.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.h.meta new file mode 100644 index 0000000..ae72a29 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: fde0a96fa20214e01a4c7c089f12720e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.m b/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.m new file mode 100644 index 0000000..41a66b7 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.m @@ -0,0 +1,88 @@ +#import "ZPCCompetition.h" +#import "ZPCLog.h" +#import "ZPCUtils.h" + +@implementation ZPCCompetition + +- (instancetype)initWithId:(nonnull NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text + metadata:(nullable NSString *)metadata + active:(BOOL)active + start:(nullable NSDate *)start + end:(nullable NSDate *)end + totalUsers:(nullable NSNumber *)totalUsers + status:(ZPCCompetitionStatus)status + formattedScore:(nullable NSString *)formattedScore + score:(nullable NSNumber *)score + leaderboardRank:(nullable NSNumber *)leaderboardRank + leagueRank:(nullable NSNumber *)leagueRank { + if (self = [super init]) { + _identifier = identifier; + _title = title; + _text = text; + _metadata = metadata; + _active = active; + _start = start; + _end = end; + _totalUsers = totalUsers; + _status = status; + _formattedScore = formattedScore; + _score = score; + _leaderboardRank = leaderboardRank; + _leagueRank = leagueRank; + } + return self; +} + +- (instancetype)initWithData:(NSDictionary *)data { + return [self initWithId:data[@"id"] + title:data[@"title"] + text:data[@"description"] + metadata:data[@"metadata"] + active:[data[@"active"] boolValue] + start:[ZPCUtils parseDateIso:data[@"start"]] + end:[ZPCUtils parseDateIso:data[@"end"]] + totalUsers:data[@"totalUsers"] + status:[ZPCCompetition stringToStatus:data[@"status"]] + formattedScore:data[@"formattedScore"] + score:data[@"score"] + leaderboardRank:data[@"leaderboardRank"] + leagueRank:data[@"leagueRank"]]; +} + ++ (NSArray *)decodeList:(NSArray *)data { + NSMutableArray *competitions = [NSMutableArray arrayWithCapacity:data.count]; + + for (id compData in data) { + ZPCCompetition *competition = [[ZPCCompetition alloc] initWithData:compData]; + [competitions addObject:competition]; + } + + return competitions; +} + ++ (NSString *)statusToString:(ZPCCompetitionStatus)status { + switch (status) { + case ZPCCompetitionStatusIgnored: + return @"ignored"; + case ZPCCompetitionStatusAccepted: + return @"ignored"; + default: + return @"invited"; + } +} ++ (ZPCCompetitionStatus)stringToStatus:(NSString *)string { + if ([string isEqualToString:@"invited"]) { + return ZPCCompetitionStatusInvited; + } else if ([string isEqualToString:@"accepted"]) { + return ZPCCompetitionStatusAccepted; + } else if ([string isEqualToString:@"ignored"]) { + return ZPCCompetitionStatusIgnored; + } else { + [ZPCLog error:@"Unknown competition status %@", string]; + return ZPCCompetitionStatusInvited; + } +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.m.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.m.meta new file mode 100644 index 0000000..d338378 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCCompetition.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: bc94e4b85a1554c7d919e4b53758db84 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.h b/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.h new file mode 100644 index 0000000..6a0f799 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.h @@ -0,0 +1,9 @@ +#import + +@interface ZPCPlayer : NSObject +@property (readonly) NSString *identifier; +@property (readonly) NSString *notificationToken; +@property (readonly) NSString *name; +@property (readonly) NSURL *iconUrl; +- (instancetype)initWithData:(NSDictionary *)data; +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.h.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.h.meta new file mode 100644 index 0000000..c506d5f --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: f9fe4755488044b97bf5f9b0be9ede9d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.m b/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.m new file mode 100644 index 0000000..1daed43 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.m @@ -0,0 +1,15 @@ +#import "ZPCPlayer.h" + +@implementation ZPCPlayer + +- (instancetype)initWithData:(NSDictionary *)data { + if (self = [super init]) { + _identifier = data[@"id"]; + _name = data[@"name"]; + _notificationToken = data[@"notificationToken"]; + _iconUrl = [NSURL URLWithString:data[@"iconUrl"]]; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.m.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.m.meta new file mode 100644 index 0000000..4c62a59 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCPlayer.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: b00af0afa71b94e61b116de847cb131c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.h b/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.h new file mode 100644 index 0000000..2d601cc --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.h @@ -0,0 +1,16 @@ +#import +#import + +@interface ZPCShareMessage : NSObject +@property (readonly, strong) NSString *text; +@property (readonly, strong) NSString *target; +@property (readonly, strong) NSString *subject; +@property (readonly, strong) NSURL *url; +@property (readonly, strong) UIImage *image; + +- (instancetype)initWithText:(nullable NSString *)text + target:(nullable NSString *)target + subject:(nullable NSString *)subject + withImage:(nullable UIImage *)image + withURL:(nullable NSURL *)url; +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.h.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.h.meta new file mode 100644 index 0000000..84c2738 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 502a46a5b6e884a97a0bdf4390132b88 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.m b/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.m new file mode 100644 index 0000000..a326496 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.m @@ -0,0 +1,19 @@ +#import "ZPCShareMessage.h" + +@implementation ZPCShareMessage + +- (instancetype)initWithText:(nullable NSString *)text + target:(nullable NSString *)target + subject:(nullable NSString *)subject + withImage:(nullable UIImage *)image + withURL:(nullable NSURL *)url { + if (self = [super init]) { + _text = text; + _target = target; + _subject = subject; + _image = image; + _url = url; + } + return self; +} +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.m.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.m.meta new file mode 100644 index 0000000..09c479e --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCShareMessage.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 33697a01b7dde483796589eaecafcebd +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.h b/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.h new file mode 100644 index 0000000..acda191 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.h @@ -0,0 +1,50 @@ +#import + +@interface ZPCStatistic : NSObject +/** + The unique id for the statistic. + */ +@property (nonnull, readonly) NSString *identifier; + +/** + The title for the statistic. + */ +@property (nullable, readonly) NSString *title; + +/** + The developer defined metadata for this statistic. + */ +@property (nullable, readonly) NSString *metadata; + +/** + The current player's score, formatted as defined in the portal. + */ +@property (nullable, readonly) NSString *formattedScore; + +/** + The current player's score. + */ +@property (nullable, readonly) NSNumber *score; + +/** + The current player's percentile rank + */ +@property (nullable, readonly) NSNumber *percentile; + +/** + Initialize a new statistic with json data + + @param data Data + @return The new instance. + */ +- (instancetype)initWithData:(nonnull NSDictionary *)data; + +/** + Decode a collection of json data. + + @param data Array of statistic data. + @return The new statistics. + */ ++ (NSArray *)decodeList:(nonnull NSArray *)data; + +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.h.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.h.meta new file mode 100644 index 0000000..8b79e2d --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 5617e7613b0f545eabf97edf993b3a2c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.m b/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.m new file mode 100644 index 0000000..3fa5ae2 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.m @@ -0,0 +1,28 @@ +#import "ZPCStatistic.h" + +@implementation ZPCStatistic + +- (instancetype)initWithData:(nonnull NSDictionary *)data { + if (self = [super init]) { + _identifier = data[@"id"]; + _title = data[@"title"]; + _metadata = data[@"metadata"]; + _formattedScore = data[@"formattedScore"]; + _score = data[@"score"]; + _percentile = data[@"percentile"]; + } + return self; +} + ++ (NSArray *)decodeList:(nonnull NSArray *)data { + NSMutableArray *stats = [NSMutableArray arrayWithCapacity:data.count]; + + for (id compData in data) { + ZPCStatistic *stat = [[ZPCStatistic alloc] initWithData:compData]; + [stats addObject:stat]; + } + + return stats; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.m.meta b/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.m.meta new file mode 100644 index 0000000..f072333 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Models/ZPCStatistic.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 9c514b6927a81471aaac3bc6c394a593 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities.meta b/Assets/Plugins/iOS/Zapic/Utilities.meta new file mode 100644 index 0000000..f7bc36b --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 84ce2949394b049f3bd1118c139719ea +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.h b/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.h new file mode 100644 index 0000000..9cc83d6 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.h @@ -0,0 +1,7 @@ +#import +#import + +@interface ZPCImageUtils : NSObject ++ (UIImage *)getZapicLogo; ++ (UIImage *)decodeBase64ToImage:(NSString *)strEncodeData; +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.h.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.h.meta new file mode 100644 index 0000000..80dc93c --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 501919f1e8d784d9cae92172730969e7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.m b/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.m new file mode 100644 index 0000000..b56b966 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.m @@ -0,0 +1,21 @@ +#import "ZPCImageUtils.h" + +@implementation ZPCImageUtils + ++ (UIImage *)decodeBase64ToImage:(NSString *)strEncodeData { + if (!strEncodeData.length) { + return nil; + } + NSData *data = [[NSData alloc] initWithBase64EncodedString:strEncodeData options:NSDataBase64DecodingIgnoreUnknownCharacters]; + return [UIImage imageWithData:data]; +} + ++ (UIImage *)getZapicLogo { + NSString *img64 = @"iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAABJ1AAASdQBKEbOYwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7d13mBRV9vDx76meSFLMrmtaZUVRcpLokKNgQhiCYg4rhh+s7rPsu7huEF0jKipGojYieWBITQZhAFFHRVRMu2sGJMwM013n/WMGRRhgpqq6q8P9PI9Lb3f1uWdm+p66VV33FhjGkYz6bzX++dXv/U7DiA7L7wSMOPbol9lk2n/j3NM+8TsVIzpMATAq9uTWTEqYitiz6CcRv9MxosMUAONQowoz2JM1DdjOfWcs9zsdI3rS/E7AiDOjCjPIrDUNaIeldf1Ox4guUwCMX4wqzCCz5htAL1RHcO8Z//U7JSO6zCGAUWZUYQaZx0wF6Q1spUbJGL9TMqLPFAADnitIJ6vm64h9KaIg3MmwOiV+p2VEnykAqS6oAXacNAHoW/7MDO47fZ6fKRmxY84BpLKgBvj0y4nA1eXPFBGw7/EzJSO2TAFIVUEN8NmX4xH6//KkPsSIs7b5l5QRa+YQIBUFNcC2L15FyT3g2S+xMh/2LSfDF2YEkGqCGuCzL14BBoIe8ILexYhT9viUleET8TsBI4ZGqUX1L15BGXzQK4v545mdfMnJ8JU5BEgVZZ3/pQo6fxiRu3zJyfCdKQCpQFWo9sUzKNcc+qI8wYgz3ot9UkY8MOcAkp2q8PAXzyDcfOhrfINd+oAPWRlxwhSAZKYq/PvzpxBuqXgD+SP3nbMztkkZ8cScBExWqsIjn49Buf0wW6xh+JmtEdHDvG6kADMCSEaqwqOfPwncfpgSb4N1p+n8hjkJmGzK9vxPoPzh8NvIOIafsT6GWRlxyowAks2jn/0LuOMIW2xHSkbGKh0jvpkCkEwe3fYvlHuPeGZHZCT3nPd9zHIy4po5BEgWj376D5T7jryRvMdP256PTUJGIjDfAiSDRz79O8ifj7KVIuRwz9nLYpKTkRDMIUCie/SzB0CP1vlBdTL3/M50fuNXTAFIZI9+cj/YlTmhtxtJvzfq+RgJxxSARPXYJ6NA/l/lNpYHuPv0/0Q1HyMhmZOAiejxT0eA/LWSW39MIPxEVPMxEpYZASSaxz4djvJQ5d9gDWPY78wKv0aFTAFIJI99cg9C5ZftUmZy91lmhV/jsEwBSBSPf3I38Mivl/E6ohIsRkQxIyMJmHMAieCxT+4CHq3iu0Zz5zlbo5GOkTzMCCDePfHJncBjVXqP8CUl1atwnsBIVWYEEM8e//RGqtr5AWzuNiv8GpVhLgWOV49/eiOiz1HVv5GyhLvO6RidpIxkYw4B4tGYrdej9rNUvUCHscwKv0blmUOAePPkJ9eh8jyO/jbyJHec867nORlJyxSAeDLmk6Gg43D2d/mGTP7mdUpGcjOHAPHiyY+vBX0BcViUhXu52azwa1SNKQDxYMzHV4O+QJX3/D+fIijg+3MmeJyVkQJMAfDbU1v7oToRCFT9zQpgo/btjBLb48yMFGAKgJ/GbL0KmIS4+TvoC9xx3jrPcjJSijkJ6Jent16JMBl3RXg7tpgVfg3HTAHww5iPrkCZgvsR2F8YVuc7L1IyUpM5BIi1pz+6HJgC6vZ3X8h3/3nOi5SM1GUuBY6lp7b0QORNINN1LFtyuKPOUtdxjJRmDgFi5Zkt3T3r/Mpk0/kNL5hDgFh4+uNuYE9HPOj8sBtL/+hBHMMwBSDqxm7titrT8WLPD4D8nVt/b1b4NTxhCkA0Pb21C2rPALI8ivgxYXnco1iGYQpA1Dz7UWePOz8IdzKsjlnh1/CMOQkYDc9+1A5bpwPZ3gWVWdxyXp538QzDjAC898yWtqBzsajuWUylBAkP9yyeYZQzBcBLz21pg5IH1PA0rujD3HKBWeHX8JwpAF4Z+2FrVL3v/PAl1Uoe9DimYQCmAHjj+Q9aocwDanoeW7mHIQ3MCr9GVJhLgd169oOLEcknOp1/CbfUNSv8GlFjRgBujHu/JbbMJxqdH0qxIsOiENeIV6NCaZx0fNlnKV0yKM0sO5GcVpqNWGVfJys1IJAOgB2phUj5QjJau+xfCaDUKntIBlJ+MtomC5Gyb6VUqyNkAFNNAXDqufcbo1YeUv7L9pw+xU31CqMTOwU9+mU2WdvLOlFmRjYl5R3qwM5lW9mIZGFHyv4FUMlG7LLHItnY5dd1iB6wDdlQ/hjNBrIOeZ9ywOv7t6Vs2zK1OHBVKBsIlC/ypIGDbglZ/rwcOICXCh/+/D454P8IRQh/4qa6pgA48kJhI2xZ+EvV9dy3pBfH/wq/B3eq/R0pfHCnipQ9tiSbSPmH37LLOoJKNtgHdDb5pYP93NkkG9EDOhsVdaCyTia/eq46kFH2cDdQtuMkopAWKd/EOqCT2D8/9UtnObDn6UFXzvzcoTjkpq0Hv+9XB9uVvsFrNBRiaX9uuOA9MOcAqm7cB01QFgLR6vwgejfhjMlk2mXfKETIhEi1shftaqjsn1dQE7XKi7h9DJZY2AiixwKgVhpSfniiZIKWxfhVh9IaIOU9g2PY/xHX8p9PCMDPo5wM8PD6BiOWFHic4rQ/HXg1qSkAVfHilgbY9mLgeL9TMTzi6844Zr5DdSg3XzD34BdMAaisss6/CDjB71QMo/JkMRZDuL7ufyt61cFS1Clo3If1UXsxpvNj9hkJIww8wH/q3sA9J/50uI3MX/NonttSl0AkBJzidypGEojNIcc2IJcbL1h7tA1NATiSFz88D7VDwKl+p2IYlTSBEr2N2+vtrszGpgAcjun8RmL5CdHbuL7epKq8yVwHUJHnP/g92EsQ0/mNhLCOQCSXay/6pKpvNCcBD/by+3UQXQr8xu9UjHgWF4NnBRlDeG9/bmj0vZMAcfFTxI0XCs9FWAqc5ncqhnEUXyHWIK47f5mbIKYA7PfC+2di6VLgLJ8zMYwjU2aQZt3ANef/4DaUKQAA4wvPIMwyTOc34lsxIvcx9IInvApoTgKOLzyDCEsxnd+Ib+8TsAdwzUXveBk0tQvAS++eTkRDwNlmLGTEL5nAvqJbuK7pXq8jp24BeOnd0xEJAb/zOxXDqJDwPcp1DK03O1pNpGYBGLf5t+Wd/xy/UzGMCikhrPBgrm0Y1dvApV4BGPfuyaTLAkznN+JTGNV/8MWFf2PU/hVKoie1CkBZ518CnO93KoZRgc+wdSDXXbQ6Vg2mzqmv8ZtPwrZCCBd4Ei81FpIwYkVkKnbpTQxttCOWzabGCGD85pNQWeJZ54dUKp1GdO1CuJ0hF07wo/HkLwAvbTwRtRYD9fxOxTAOUoBlDWBwvY/9SiC5C8BLG08kLX0xcKHfqXjCHHYkC0UYQ5Y1gn719vmZSPIOZCe9U5sIi4DGfqfiveT9s6WAbxDrWgbXm+93IpCsI4CXNx2LzUKSsvODGQokKGEB4cA1DK33teMYL286ll01ig5c2ttdSsnm5U3HkhZYCDT1O5WEZ+qMV4oRvY9B9Z9ExPlvdcK7lxDWrxla/0OvEkuuAhAsOIaSjIVAM79TMYxyH2AFchlY723HEV7elkXa7nuxIvMY2HCdh7n9+kZHCS1YcAzFmQswnd+IF6ITUG3mqvOPf/d80nZNR/RNrzs/JMsIYOLaWpC9AGjhdyqGB444SE6Ij+xORG5m0EWvu4oyYfMQRP5IWPo4We+vMhL/JOD4zdWB2ZjOnzyO2Mfj/cSELAUdzKD6XzkO8fKmY0m3ngXqE7E7R3NCUGIfAozfXB1hLtDO71SMlBdGuZ+MDzsxqIHzzj9h0yWkW+8C52KVtuMaMxuwYs8VVCNN5qDa3u9UjCTgbmDxBZYOJLfhSscRQqE0vjpuJMJIYBUU9Sa35WFv6eWVhDigOsRzBdWokT4HyPE7FSPlTQO5kYH1tzuOMGnjmRCYBLQG8kjfcyX9WhV5luERJF4BeK6gGjXSZgMd/E7FSGlFIH9iYAN3C3RO3Hwlos8DtYEZ1K7enx7eXORTGYl1CBBcnU1p2izEdH7DVxuwyKV/g48cRwiuzqa02oOgw8qfmcBvtl9HTsOwNylWTuKMAPK2ZrJj75ugPfxOxUhZijKG9HR3k3gmvdMEsacAdQAQnqJ/g2GurhJ0KDEKQLAwg3Dpm0BPv1MxUta3qA5lYKM8xxFUhcnvDEP0ISADAGE0Axre51GOVRb/BSBYmEGkdBrQy+9UjBSlsohI6RAGN/2f4xjjN59Euv0KSPf9UVFGkNvwEU9ydCi+zwEECzOwS94AMZ3f8EMp8E8+auBugc7Jmzoj9qvAqeXfN0ZQbiG30Qse5elY/BaAYGEGkX1TQXr7nYqRgpQtiAxgQMNNjmPkbc1k5677gRH8ctHdPlQGk9sw6EWabsXnIcBzBekcE5gK9PE7FSMVyQSs9NvoV2+34xCTC+piBSYDjQ54tgS4mv6NZrrN0CvxNwIo6/xBTOc3Yu8nRG/h6kZTXEV5beMQkGeA6gc8uxvVvgxovNhVbI/FVwEIBgPY1njQvn6nUrH4HDAZnniLSCCXgfU/dRwhWHAMkcBYYMBBr2wHuwcDmqx1lWEUxM8nOhgMoOdO4NBfnmFEUwT4Nzvsv3Bz01LHUV7b0BKsSYgefK/JrxG7C/2avusqyyiJjxFAMBhAz3kV0/mN2PoSGMTVjZc7jlC24xoOPACaftCrnyHamX5NfVv2+2j8LwDBYACp8wroQNex4n2quBFHZDqScQP96v3oOESw4AywJgJtD3lN+ZD0QGeucDE1OAb8LQDBYADOfRnVQZ7Ei58DGiN+lU3i6dfI3SSeqRsuR2UccFwFn7uNCN24osF3rtqIAf8KwCi10A0vITrYtxyMKkr4ClsI9gBXx+PB1dlI1oMoww6zxQqwe9Ov6U7HbcRQwJdWVYXvN45F5HoEEvY/I1EoMA5KrqBfC+cr7Lzxdj3UygcOd3HaEsjqTb+Guxy3EWOxHwGoCm9seAbk5pi37TVTBBLBd8B1XNVkjuMIqsLUDcPQyGiEzMNsNJPdu/oztEmx43Z8ENuPsKrwxsangNti2q6RqhYTliEMaPxfxxGCG09E9GWOPBN1Iif8NJScnJjO5fdC7AqAqvDmxqdQ0/ldM992HE0Y+AeFjd1N4pm6sSPoeOA3R9jqaQobD3PVjo9iUwBUhWkbnwT9Q0zaM1LZZ9hWLv0ar3EcIRRK4/saIxH5C79aOfug7iI6miua+jaX3wvRLwBlx/xPINwR9baMoylB2IvyU/njXajuQaUEix1AEarFqLUDS0uw2QPsKnssP2GxF7SEiBRj8Txwvr8/ziFexc7+g6tJPMG3zi6fxNPyCFspyh+5qum/HbcTJ6J/EvDNDf/CMp2/CoqBIqAYYTta/hgp65wi28EuQqUY0e2IFGFTjKXbQYqwpRixixApxrbLXk8LFJNe8wdPFpsMFtbAKp4OGk+d/yeQ27myyURXUaauH4LI00CNI2wVAbmVq5qMc9VWnIjuCODNgn+hJPQQ6TCKge1AEUIxyvaKOyhFoMWolHVEsYuxre0VdtBAWhE9L9rhx7pwlTbnndqU7MvjyHvHGJP1RMilXxPnl9tOXFuL7LRngKNdjRpG9HoubzbecVtxJnoFYFrBP4E/RS3+kR3cQcv2osr2sk4pxahur7CD7t+LWuV710ikmPS07QTSiqj+w65EPNPrieC6UwhY+UB9v1MpV7ZA5w8MdzWJZ/r65tgyGTjnKFuWoPTnyqYzHLcVh6JTAN5c/3fgz0fY4pdhLrIdtPxx+TBWKMamCDmoc6qUvW7ZxUTk0L1oSeb3rlZrNSo2beOZiL0QtE5M2z38WOgb1LqGK5vkO4+twrT1wxB5GDh4Es/B9gB9uaLZIsftxSnvC8D0Tcdih5siUoxIERY70UgJaVm7+c++3a6qtRF7b244H3Qh6Gl+pwKAMgOxb+DyFj84jjFt7W+RwESgMreV245aPbgi/ubye8Fcy2Yc3rSCxojOB070OxWgGNH76NvsSVfnSaYX9EX1BeD4Smz9DbbVhSubvOO4vTjn/3RgIz5NX98cdB5wnN+pgLyPJQPo46IjvhzKonb10agOO+pur6y8fI4d6cyVzbY6bjMBmBGAcaiZBTnYOosjfx0WKxNIk1vo3XSv4wgz1l6AHZiCVPIEpvAhaBf6Nv/ScZsJwhQA49dmrr8U1ddRsnzO5HssuZ4+zWa5ijLjrSGojAWqVfIdmyhN60q/xnE/l98L5hDA+MXMdQNRfQVI83fXICECpYPp3cr51N3ZBScQsV8CelfhZ1nHvnB3+jV3vkpQgrGOvomREmasuw1lPP7uFMKo3s++bZ1ddf6Za3OI2G9z+Hn7FZAQsq8T/VqlTOcHcwhgAMx4616QB/1NQj9HrIH0abbKcYhQKI0d1SqYxHNUszlmTz9ychJqLr8XTAFIZarCrHWjQUb4m4hMxU67icsa7XAcYvqas7ACk4BWVXznJGrtuTZVr/A0BSBVqQqz33oclcOtbRcLuxAdzqUtn3cVZeZbVwHPA8dW8Z1j2dT8D4k6l98LpgCkomAwQOaZLwLX+JhFAZbm0rul8+/ZZ66siaY/jVD1hWWV0fRtkYwT1arEFIBUk7c1k9IfpyBc5lMGCjqG4pojXM3bmPlWU4QpwLlVbl+4l94tHnbcdhIxBSCV5G+uTknJdNDOPmXwLVjXcmmzeY4jqAqz3hqGyENARlXfjchd9G7+pOP2k4wpAKlizora2OlzgYt9ymABAesaejb/2nGEmWtPRuQVoJuDd0dQrqdPi1cdt5+ETAFIBTPXnoxFPtAg9o1LCei99GrhbhLP7LVdgFeBUxzlIHYuvS5+03H7ScoUgGQ3u+AMCC8CYjuXv8yHWNYAejZ/23GEUCiL3dmjgTtw9nndg81l9Gm50HEOScwUgGQ2c/15WJGFwOk+tD6BjOxb6dpgj+MIc9acj8pkoKHDCDtAetC7hfMVgpOcKQDJata6elj2QuDUGLe8E7iFXi1fcxVl9ltDEH0GqO4wwjeodKV3i82u8khypgAko1mrmmFZ86jcohfeUdaiVi6XttjmOMbCgmPYV/ocytUuMvkCsTrTs8VHLmKkBDMZKNnMWZuDZS0mtp0/jHI/RV+2cdX5Z6+6mJLSTa46v8oWwoE2pvNXjhkBJJO8Nb1RghDTufxfoNYgerVY4ThCKJTG3qyRwEjc3LFatZCI3YU+bZzfCzDFmAKQLOauzgV5haOvcOulaWj4Rnq13e44wuyVZyCBSQhtXOaynhKru6vFQlOQKQDJYO6aW4Cnid0hXRHIn+jZ8glXUeauvQJ0HFDbVRxhKaWRS+nTZperOCnIFIBEl7cq1nP538PWAfRq/Z7jCMHV2VSXBxH1YibiHLJLrkrFufxeMAUgkc1dNQqRv8aoNUVlDLL9j/To4fweg3PWNsGKTAb5vQc5TeakjGtpau414ZQpAIlIVZi35jGEO2PU4neIDqVb67mOI6gKeWuGITiZxFORZ1l38e2pPJffC6YAJJpgMEDN014AuTZGLS5CwkPo1u5/jiPkrzoJ23oZtIcnGYmMptvFKT+X3wvOv3IxYi9YmEHNzNdBBsSgtVLQv/NWqxu54SznJ9fmr+mEkg809iYtGUX3i//iTSzDjAASRX5+dewabyJ0iUFrW8DKpdvFGx1HKChI57uSPyNUdYHOQ2n5/6rcQ49Wj7uKZfyKKQCJIBQ6lpKMuVR9wUsnJpC57zZycnY7jjBv5XmITAEaeZRTBLiRbq1f9iieUc4UgHi3aO3JhCPzcT4jrrJ+ArmVbq0mu4oyf/UQ0Kfx7rZi+4BcurWe5lE84wCmAMSzhSvPICILEbz4yuxI1hEhlx6tP3EcIW9tLazIswgenp+QPYheTpfWC7yLaRzIFIB4lb/sbAgsAn4XxVZs0Kc4Pnu4q+/S81e0AGsy3ua6A6QnXVut9jCmcRBzb8B4NH9lPWAB8JsotvIlyCC6tlnuOEIwGKDWqcNBHgD1cg7Ct4h0pUsr5ysJGZViCkC8WbSqGbZGey7/dGzrBrq5uA9e/rLTkcBEoJ13aQHwP2w607V1ocdxjQqYQ4B4snDFJSCzUGpGqYVi0Pvo0tbdJJ4FKy4DeQE4zpu0frYNSzvRqe2nHsc1DsOMAOJF/opeqEwlenP5CxFrAJ1bves4wurV2eyOPAhRuZ3Y+0BnOrU1c/ljyIwA4sGCFQMQXiU6c/kVGEdx9t30brrXcZQlK+sRYQroRd6l9rMCJKMbncxc/lgzIwC/LVp5M6rPEJ25/N9jcx1d2852HEFVWLzyRiL6OJDtXWo/W0a29KZNCzOX3wdmBOCnBSvuRfgX0fg7iCzBZjBdXCyPlbf8RNLlJaCXd4kdSOZS3bqKVq2KohPfOBozAvDL4hX3okRjIY8wyj9Y2fpvrqbKLljeEUvGE72vIl/j2KwhZi6/v8wIINZUhUUrHkXkLu+Dy2dIZCAd2zu/eCYUSiOcNtKTSTyH9xwr29xm5vL7zxSAWAoGA9Q+ZRzC0ChEn0ogchM5OTscRwiFziISmExUbyCqT9Kx3V2u7hNoeMYUgFgJFmZw/A+TgCs9jrwL5TY6tZvoKsqSFUNQTyfxVEBH07G9WcgjjpgCEAuzC6qRvfdNhK4eR16PFcklJ+djxxHy1tYic9/TwCDv0jqEIvwfHdo9FsU2DAdMAYi2UOhY7MAcoLWHURXVMfx4wgj61dvnOMqipc0QazJwrnepHSKCyE10aPtSFNswHDLfAkRT/qqT0HA+4uVcfvkG9Bo6ts93HEJVWLp8GCoPE90biexDGEhO2zei2IbhghkBRMvy5acS1gXAhR5GnYldej2dOjm/Ym7RopOx0l8Fzw9HDrYX5HI6tHNeqIyoMyOAaFi27GzCLATO8ShiMcJ9XNLuSVdnz5cs7wP6ItG/cehOkJ50aLcqyu0YLpkRgNcWLb+AgC4ATvMo4geoNYAObZ3f5z4UykKs0Sh3EO2/ufAjEelOx3brotqO4QkzAvBSKNQUdB5wgifxVCawp9otribxLFp+AaJTUOp7ktOR/Q+1u9Axx/ltw4yYMgXAK0uWtEdkFmgtD6LtQOQW2rd73V1Oy4Zg6ViUah7kdDTbsMOd6djR+bqCRsyZQwAvLFnSE8uaijez5ZaiOpicnK8cRwiFTkDkReBSD/KpjA+IRDrTseN/YtSe4ZFY3U46eYVC/bGs6bjv/GFU7+fbbzu56vxLl+Yg8jax6vwiG1BtZzp/YjKHAG4sW3YT6FjcFlLhc7AH0q6D87PmoVAaFiOBkcTilm9l30UsJzOzNy1b/hT19oyoMAXAqaVL7wB9AreHUcobWIGbaHvJdscxFi8+E8uaBOrl1YZHJuSRnnElLVuaufwJzJwDcGJZ6F5wPZd/F+hw2nd43lWUpUuvQvR54FiX+VTF61SvOdjM5U98ZgRQFarCitAjwN0uI21ArQG0b7/VcYSVK2sSCf8b0Ztc5lI1KuOx9XqaNg3HtF0jKswIoLKCwQAnn/Q8ote5iKKojOGEb0dQr5/zSTwrQ02xmQzUcZGLE0/R9pJhZi5/8jAFoDIKgxn8cKLLufzyLRbX0uaSeY5DqArLlw5D5CHQDOe5OGmb0bTPMXP5k4wpAEdTMLsaRTWmAd1cRFmIBq6hXbv/OY6wKv8k7IxXgO4u8nBCQYfTtsOjMW7XiAFTAI5k4cJjyArMAdo4jFAC8lfaLHsYGeV8/btVi7tgy6vAKY5jOBNB5Gba5LwY43aNGDEnAQ9n9fzjiATygBYOI3yIHcilfftNjnPIy8ukZub92DKC2F+0tQ90EG06TI1xu0YMmQJQkeXLT8UuzUdwdhccYQK7S2+la4c9jnNYHaqLrVPAy8VEKm0vKlfQtsN8H9o2YsgcAhxsTegsIroIZ3P5d6J6K207TnGVw4olQxCeAaq7iuPMbkT70LrjEh/aNmLMjAAOtGbZ+UQiC3E2l38tag+kbSfnd7YtWHgMRdazCP0dx3BnO0p32nR8y6f2jRgzI4D9VixpgqXzqfpc/gjwbzKP+YurK+NWhlpi6WRUz3Ycww3layy7C606O797sJFwTAEAWLW4HTAbqOpc/i9QHUSbTisctx0KpZFhx24ST8U+Q6zOtHKxvLiRkEwBWLmkB6JvUNXpvMKbUHojrbr96LzthWcg1kSgreMY7n1AwOpCSxdTkI2EldrnAFYv6gv6GpBZhXcVgf6JVp2ecNX2qiVXIDoOqO0qjjsbCKd3p3W773zMwfBR6haAVYsHg74EepTfwa8GSYWo1Z/WLta8W706G9n7IKrDHMfwxgqskl6062jm8qcwv445/bV60e0Iz1P5n18RxrBj31V07OLmct4LETsf6O04hjfmQbXeXOziOgUjKaTeCGDN4ntBqzCXX77DsofSovNcx22qCm8tHoYyGrQqhxveU2ayY9/V9OhU4mseRlxInZOAqsLaxQ8D/1f5N8liIpEhtOnyX8ftLs87kbSMlxF6Oo7hnYkUB4aSk2Pm8htAqhwCBIMBdn39HPCHSr4jDPoALVfewJnXOz9GXrOoE1ZgAUJjxzG8ojzNxStv5uyhEb9TMeJH8o8ACoMZ7K49AaVfJd+xDcilZee1jtssKEindPufEf5CPKy8LDKaFp3MXH7jEMldAPLyMjku/XWgTyXfMYGitNvIydntuM31S84jEpkMcbDXL5vLP4KWXR7xOxEjPiVvAQiFalAtPAPoWImtf0LkNpp3muSqzbcWDgGeBmrg/6JZEZRbubjzOL8TMeJXcn4LsGJObTLCeUDLo26ruo60QC5NXdzSam1eLSR9LJD783P+ltZShEE07xz0NYtUtXp1Nvbu2mRaWaiVjR2pTUCy0Eg2atVGJQvsbIQskGxUa2NJFko2UBslC8hGqA3lj+F9AlxB0847vUw1+UYA60KnQHgBetS5/IrqGNKOG+5qEs/6xc2x7cl4dytwt0pA+tOi0wy/E4lbh3TQ0iywsrHs8s5Z3ikr7KCSBZqNUhspfwy1y5+vSXR2qm8TiXR0ddn5HYDwbAAACVhJREFUYSRXAVgz7yyswEKEc4+y5VfAIJp3Wea4LR1lsb7VHcDDQLrjOF5SdmNZl9Gs0yK/U3Fl9epsIj9mIRnZZNi1saWCDmqX/Sta1vn0wD3mga//ai96PFDFxVR97yLvgHSgRacfohHc95/OMwX5dbFlIfDbI24nMgNbbnD1C12XfzrIRKCd4xheE7YTkR6uvr2orP0dtHpGNhErCw1nYwXKOuf+Ya5lZ6EV7D1VsxGpDeUdlAM6qJCF+jo3Is7IFki7hOY5X0ethWgFjqmC+Y2xrfnAiUfYqhi4j+Zd3E3ieWvBZQgvAMe5iuMp/Ro70JWWnd75+anVq7PJ2l274g4qv+w9lbJhrEjtnzuoRVnnpXwYvP/YtOxxLVLl+hF/bcWy29O0m/NLzysh8QvAhvltsa3ZwDGH3UZ4H7EG0OSADlJVBbOroVmPQYzvxFM5P6KEy45Zq7ymgTv+f9uRhPQTwmntaRX9Oy4ndgHYkN8BW2YCNY6w1QSk5Baa9t7ruJ118+sh1hRwuEioYVTeF4Qj7bm4+2exaCxxC8D6+X1AXqPs+LEC+j0q19G862zHbagKBQtuBB4DqjmOYxiV8xUE2tPMxbqSVZSYBWDDgkGovszhv3IJkZY2mIYuhlAFoRPQfS8hvk/dNQ6WnIcd3yBcQtOuH8ay0cQrABsW3I7qk1R8jX0Y5R80XfM3V3fi2ZDfAWUC8BvHMQyj8r7FiuTQuMf7sW44sQpAwfx7QQ43l/8zbAbSvOtqx/FDoTRq7BsZN5N4jBSg36OSQ7OuzleZciExCoCqsHHBQ8DwCl8XpiIZN9EoZ4fjNjbNOwvbmgS0chzDSE7RO+TYgdCJJl03RK2Fo4j/AhAMBjin1ljgxgpe3YVwO427TXDVRsG8qxB5HjjWVRzDqLydWNqZRt3X+5lEfE8GCoXSqFnyIjDk0Be1AGQAjbs5X8t+5cyaZGc9AzrIeZKGUWV7gN5+d36I5xHA1rxMfrJeQ+h70CsKMobMnSOo12+f4/ib5jVDZTIcdd6AYXhpL6I9adR9qd+JQLwWgM351YnoDKDTQa98g3ItTbo5v2utqvB2/jCUh6jyxBDDcEOKUHrRpGvc3Hg1/grAO3NqEw4cOpdfWUDEvobmPZ1PjHh30cmUlr4KdHWXZKzE35/HcGwfwuU06uZ8dekoiK9P2LuLTiZcugCo//NzQjEq99Gw65OIOD8fu2l+H9AXKZsSahixtA9Lr6RBD+dXpUZJ/BSAjXPPRGQhSJ1fnpQPIJJLo55vO44bCmVRu3g0yh3E089rpIoIIrk07BaXqzPFR4coyK+LZS9AOP3n54QJiHUrDbo6v3vNhjnnYwWmAA08yNIwqiqCMpjG3af4ncjh+F8A3s5rBJLPL3P5d4LeTMMer7uKuzlvCCpjMZN4DH/YwDU07D7R70SOxN/rAN6e3xzseaD7F9dYijCYBj2c36p60/RjkcxnUa5O1lkjqcH/fZMLCtwa750f/FzZ5e05OcA8yq6+C6P6AFv33EDHvs5XPd007xIksBBzOa/hH0W4nYY9nvM7kcrwZwSwOa83EKRsLv8XqAykUY+VjuOFQmkct3ck6EjMclWGfxRhGPV7jPU7kcqK/TjrnbyBKK9QVnymIfaN1O+13XG8jXPPJCCTgNYeZWgYzgj3Ub/HaL/TqIrYjgA2590KPIVQgupwGvR0t0Dn5rwrEZ6HSq4ka04JGNHz50Tr/BDLAvDOnHtBHwQ2YJNLw54fOY714cya7Ev/d5UX6Ezo80pG/NK/Ur/XP/3OwonodwlV4b280SjDUcaQtsfdJJ535jRBZApKnaNvbBhRpvoIDXpVvE5FAojuCKCs8z8O9AerFw2657mMNQzKJ/Ekyt7cHHYkMXmcBj0TtvNDNEcAwWCAujVeRPQ0AoEhXODiBgeb808iEH4FpbuHGRqGCzKGi3oM8zsLt6IzAtial0mxjgf9gAvXX+dqgc5353aG8Ksop3qYoWG48SIXdr/T7yS84H0B2JxfnZLSB7GsB6nXY5PjOFvzMimx7wcdgVmgs2rMYUf0CK9Qr+AmpGdS/Ja9PQTYNP1Y0tL6YxVNpF6/3Y7jvDO7LhaTQRp5mJ1huCMEKdybS79+Eb9T8Yp3BWBbKIu9u86h3qWFruK8N3sIyDNAdW8SMwwv6DS+q9GfnJyw35l4KX7OpX+y8BhKSsaiDPA7FcOBpBgQH4YwnaJTrqZp01K/U/FafBSA92e1RGUS8Du/U/lFfPxqDN/NJ8PqS50eJX4nEg3+fso1GKCw2nBEHwDSfc3FMA4hC6lW/VLOzin2O5No8a8AFM4+A2Ei0Na3HIzEFt3DjhWEM7q7WpEqAfgzHfiDOZejOg447qjbGsbhRGv3pbIK9vagQe+k7vwQ6xHAl8Fsdmc/iJLwV1AZSWstlt2Fun12+Z1ILMSuABTOqofFa8CFMWvTcCElT4JuolQ6ulqfIsHEZjbgllnDUBkNZEa9PcNwZjN2RgfqdfvR70RiKboFYGveiYQjL4P2jGo7huGKvItFB87r/b3fmcRa9ArAltkdUR0P/CZqbRiGe1uIBC6hnotbziUw778FCIXSOOWnkaj+BTOJx4hvW0E7pGrnB69HAB/OOhvRyehBN/Y0jLijn2Ont+eCnp/7nYmfvCsAW2YMAXkaqOFZTMOIji9RaU/dS7f5nYjf3B8CbM2rhZY+gzLQg3wMI9q+wrJzqHNZynd+cDsC2DK9OViTgXO8SccwoupbJHIJv7/8A78TiRfOCoCqsHXWMOBhzCQeIzF8h0gOdVyuV5Fkql4Atk77LZo2EbR9FPIxjGjYjgQ6Uaf3Rr8TiTdVKwAfT++LygvA8Z5lkMwLSRjxYCe2dKJunwK/E4lHlSsA20JZRHaONpN4jATzE7Z25rzL1vmdSLw6egHYOuMClCkI9WOQj2F4ZQ8qPfh9n+V+JxLPjlwAPp4xBHQsUC026ewXxSkK5pAjFewF7Umdy5b6nUi8q7inbZl9Amnhl1B6xzgfw3CrCLQX516+xO9EEsGhFwJ9PDMHSiegcpoP+RiGG/sQ+yrOucJ0/kr6ZQQQCqVxxo6RgJnEEw3m0CPaSlHrSur0meV3IomkrABsm34WNpOAVv6mYxiORFAZyLl9X/c7kUQT4NM3r0KZC9TxOxkDUnQpLjciIEM4t+9rfieSiP4/R52VWfSf1LIAAAAASUVORK5CYII="; + + UIImage *logo = [ZPCImageUtils decodeBase64ToImage:img64]; + + return logo; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.m.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.m.meta new file mode 100644 index 0000000..a4fcc37 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCImageUtils.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: e95c74584fd3b4e51a596d42ca4ed700 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.h b/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.h new file mode 100644 index 0000000..e06942e --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.h @@ -0,0 +1,5 @@ +#import + +@interface ZPCInjectedJS : NSObject ++ (NSString *)getInjectedScript; +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.h.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.h.meta new file mode 100644 index 0000000..dbad0b2 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 089bdd65a3ca046b1a8dd1025b111934 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.m b/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.m new file mode 100644 index 0000000..2ea5557 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.m @@ -0,0 +1,78 @@ +#import "ZPCInjectedJS.h" +#import +#import + +@implementation ZPCInjectedJS + ++ (NSString *)getInjectedScript { + //Gets the info to be injected + NSString *sdkVersion = @"2.0.0"; + NSDictionary *appInfo = NSBundle.mainBundle.infoDictionary; + NSString *appVersion = appInfo[@"CFBundleShortVersionString"]; + NSString *appBuild = appInfo[@"CFBundleVersion"]; + NSString *bundleId = NSBundle.mainBundle.bundleIdentifier; + NSString *deviceId = UIDevice.currentDevice.identifierForVendor.UUIDString; + NSString *iosVersion = UIDevice.currentDevice.systemVersion; + NSString *installId = [self installId]; + const int sdkApiVersion = 4; + const int loadTimeout = 10000; + + NSString *adId = @""; + + if (ASIdentifierManager.sharedManager.isAdvertisingTrackingEnabled) { + adId = ASIdentifierManager.sharedManager.advertisingIdentifier.UUIDString; + } + + return [NSString stringWithFormat: + @"window.iosWebViewWatchdog = window.setTimeout(function () {" + @" window.webkit.messageHandlers.dispatch.postMessage({\"type\":\"APP_FAILED\"});" + "}, %d);" + "window.zapic = {" + "environment: 'webview'," + "version: %d," + "iosVersion: '%@'," + "bundleId: '%@'," + "sdkVersion: '%@'," + "installId: '%@'," + "deviceId: '%@'," + "appVersion: '%@'," + "appBuild: '%@'," + "adId:'%@'," + "onLoaded: function(action$, publishAction) {" + "window.clearTimeout(window.iosWebViewWatchdog);" + "delete window.iosWebViewWatchdog;" + "window.zapic.dispatch = function(action) {" + "publishAction(action)" + "};" + "action$.subscribe(function(action) {" + "window.webkit.messageHandlers.dispatch.postMessage(action)" + "});" + "}" + "}", + loadTimeout, + sdkApiVersion, + iosVersion, + bundleId, + sdkVersion, + installId, + deviceId, + appBuild, + appVersion, + adId]; +} + ++ (NSString *)installId { + NSString *const installKey = @"zapic-install-id"; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + NSString *installId = [userDefaults stringForKey:installKey]; + + //If an install id was not found, create one + if (!installId) { + installId = [NSUUID UUID].UUIDString; + [userDefaults setObject:installId forKey:installKey]; + } + + return installId; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.m.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.m.meta new file mode 100644 index 0000000..197c9b6 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCInjectedJS.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 39da0d51aeea04f618114222db72a72e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.h b/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.h new file mode 100644 index 0000000..2b76f6b --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.h @@ -0,0 +1,11 @@ +#import + +@interface ZPCLog : NSObject + +extern bool isEnabled; + ++ (void)error:(NSString *)message, ... NS_FORMAT_FUNCTION(1, 2); ++ (void)warn:(NSString *)message, ... NS_FORMAT_FUNCTION(1, 2); ++ (void)info:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); + +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.h.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.h.meta new file mode 100644 index 0000000..8b2db3c --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 347cefde12658422b881b49ad6e6f3fe +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.m b/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.m new file mode 100644 index 0000000..4f98fd7 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.m @@ -0,0 +1,43 @@ +#import "ZPCLog.h" + +@implementation ZPCLog + ++ (void)error:(NSString *)message, ... NS_FORMAT_FUNCTION(1, 2) { + va_list args; + va_start(args, message); + + NSString *s = [[NSString alloc] initWithFormat:message arguments:args]; + + [self writeLog:s withSymbol:@"ERROR"]; + + va_end(args); +} + ++ (void)warn:(NSString *)message, ... NS_FORMAT_FUNCTION(1, 2) { + va_list args; + va_start(args, message); + + NSString *s = [[NSString alloc] initWithFormat:message arguments:args]; + + [self writeLog:s withSymbol:@"WARN"]; + + va_end(args); +} + ++ (void)info:(NSString *)message, ... NS_FORMAT_FUNCTION(1, 2) { + va_list args; + va_start(args, message); + + NSString *s = [[NSString alloc] initWithFormat:message arguments:args]; + + [self writeLog:s withSymbol:@"INFO"]; + + va_end(args); +} + ++ (void)writeLog:(NSString *)message withSymbol:(NSString *)symbol { + + NSLog(@"[Zapic][%@]-%@", symbol, message); +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.m.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.m.meta new file mode 100644 index 0000000..6f33e13 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCLog.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: b052a23fd07f642f1a431b8b52a9d14e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.h b/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.h new file mode 100644 index 0000000..f42d685 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.h @@ -0,0 +1,9 @@ +#import + +@interface ZPCQueue : NSObject +@property (strong) NSMutableArray *data; +@property (readonly) NSUInteger count; +- (void)enqueueMany:(NSArray *)source; +- (void)enqueue:(id)anObject; +- (id)dequeue; +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.h.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.h.meta new file mode 100644 index 0000000..5c7dd3c --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 55f225d781136406998af3fc87b7f35f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.m b/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.m new file mode 100644 index 0000000..092a9af --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.m @@ -0,0 +1,32 @@ +#import "ZPCQueue.h" + +@implementation ZPCQueue + +- (NSUInteger)count { + return _data.count; +} + +- (instancetype)init { + if (self = [super init]) { + _data = [[NSMutableArray alloc] init]; + } + return self; +} + +- (void)enqueueMany:(NSArray *)source { + [self.data addObjectsFromArray:source]; +} + +- (void)enqueue:(id)anObject { + [self.data addObject:anObject]; +} + +- (id)dequeue { + id headObject = [self.data objectAtIndex:0]; + if (headObject != nil) { + [self.data removeObjectAtIndex:0]; + } + return headObject; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.m.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.m.meta new file mode 100644 index 0000000..bc75f22 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCQueue.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: d3cb108d06037453588da59c4f0b2ede +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.h b/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.h new file mode 100644 index 0000000..22540a0 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.h @@ -0,0 +1,7 @@ +#import + +BOOL checkIfInstanceOverridesSelector(Class instance, SEL selector); +Class getClassWithProtocolInHierarchy(Class searchClass, Protocol *protocolToFind); +NSArray *ClassGetSubclasses(Class parentClass); +void injectToProperClass(SEL newSel, SEL makeLikeSel, NSArray *delegateSubclasses, Class myClass, Class delegateClass); +BOOL injectSelector(Class newClass, SEL newSel, Class addToClass, SEL makeLikeSel); diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.h.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.h.meta new file mode 100644 index 0000000..35c93e7 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 6cefaff7600b847f4830c6d0ff4b4373 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.m b/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.m new file mode 100644 index 0000000..36793c3 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.m @@ -0,0 +1,81 @@ +#import "ZPCSelectorHelpers.h" +#import + +BOOL checkIfInstanceOverridesSelector(Class instance, SEL selector) { + Class instSuperClass = [instance superclass]; + return [instance instanceMethodForSelector:selector] != [instSuperClass instanceMethodForSelector:selector]; +} + +Class getClassWithProtocolInHierarchy(Class searchClass, Protocol *protocolToFind) { + if (!class_conformsToProtocol(searchClass, protocolToFind)) { + if ([searchClass superclass] == nil) + return nil; + Class foundClass = getClassWithProtocolInHierarchy([searchClass superclass], protocolToFind); + if (foundClass) + return foundClass; + return searchClass; + } + return searchClass; +} + +BOOL injectSelector(Class newClass, SEL newSel, Class addToClass, SEL makeLikeSel) { + Method newMeth = class_getInstanceMethod(newClass, newSel); + IMP imp = method_getImplementation(newMeth); + + const char *methodTypeEncoding = method_getTypeEncoding(newMeth); + // Keep - class_getInstanceMethod for existing detection. + // class_addMethod will successfuly add if the addToClass was loaded twice into the runtime. + BOOL existing = class_getInstanceMethod(addToClass, makeLikeSel) != NULL; + + if (existing) { + class_addMethod(addToClass, newSel, imp, methodTypeEncoding); + newMeth = class_getInstanceMethod(addToClass, newSel); + Method orgMeth = class_getInstanceMethod(addToClass, makeLikeSel); + method_exchangeImplementations(orgMeth, newMeth); + } else + class_addMethod(addToClass, makeLikeSel, imp, methodTypeEncoding); + + return existing; +} + +// Try to find out which class to inject to +void injectToProperClass(SEL newSel, SEL makeLikeSel, NSArray *delegateSubclasses, Class myClass, Class delegateClass) { + // Find out if we should inject in delegateClass or one of its subclasses. + // CANNOT use the respondsToSelector method as it returns TRUE to both implementing and inheriting a method + // We need to make sure the class actually implements the method (overrides) and not inherits it to properly perform the call + // Start with subclasses then the delegateClass + + for (Class subclass in delegateSubclasses) { + if (checkIfInstanceOverridesSelector(subclass, makeLikeSel)) { + injectSelector(myClass, newSel, subclass, makeLikeSel); + return; + } + } + + // No subclass overrides the method, try to inject in delegate class + injectSelector(myClass, newSel, delegateClass, makeLikeSel); +} + +NSArray *ClassGetSubclasses(Class parentClass) { + int numClasses = objc_getClassList(NULL, 0); + Class *classes = (Class *)malloc(sizeof(Class) * numClasses); + + objc_getClassList(classes, numClasses); + + NSMutableArray *result = [NSMutableArray array]; + + for (NSInteger i = 0; i < numClasses; i++) { + Class superClass = classes[i]; + + while (superClass && superClass != parentClass) { + superClass = class_getSuperclass(superClass); + } + + if (superClass) + [result addObject:classes[i]]; + } + + free(classes); + + return result; +} diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.m.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.m.meta new file mode 100644 index 0000000..f0d31df --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCSelectorHelpers.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 521cddc8827534694b1955ceec3ffefc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.h b/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.h new file mode 100644 index 0000000..c080852 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.h @@ -0,0 +1,7 @@ +#import + +@interface ZPCStorage : NSObject +- (void)store:(NSArray *)objects; +- (NSArray *)retrieve; +- (void)clear; +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.h.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.h.meta new file mode 100644 index 0000000..cede8ac --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 039c3f2438d3d4e7bbfb20012796b9cc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.m b/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.m new file mode 100644 index 0000000..d1c4252 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.m @@ -0,0 +1,52 @@ +#import "ZPCStorage.h" +#import "ZPCLog.h" + +@implementation ZPCStorage + +NSString *const filename = @"zapic-events.json"; + +- (void)store:(NSArray *)objects { + NSError *error = nil; + NSData *json = [NSJSONSerialization dataWithJSONObject:objects options:kNilOptions error:&error]; + + NSURL *url = [[self getUrl] URLByAppendingPathComponent:filename]; + + //Delete the existing file + if ([NSFileManager.defaultManager fileExistsAtPath:url.path]) { + [NSFileManager.defaultManager removeItemAtURL:url error:&error]; + } + + [NSFileManager.defaultManager createFileAtPath:url.path contents:json attributes:nil]; +} + +- (NSArray *)retrieve { + NSURL *url = [[self getUrl] URLByAppendingPathComponent:filename]; + + if (![NSFileManager.defaultManager fileExistsAtPath:url.path]) { + return nil; + } + NSError *error = nil; + NSData *data = [NSFileManager.defaultManager contentsAtPath:url.path]; + NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; + + if (![NSFileManager.defaultManager removeItemAtPath:url.path error:&error]) { + [ZPCLog warn:@"Unable to remove file at %@", url.path]; + } + return json; +} + +- (void)clear { + NSURL *url = [[self getUrl] URLByAppendingPathComponent:filename]; + NSError *error = nil; + if (![NSFileManager.defaultManager removeItemAtPath:url.path error:&error]) { + [ZPCLog warn:@"Unable to clear file at %@", url.path]; + } +} + +- (NSURL *)getUrl { + NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; + + return [NSURL URLWithString:documentsPath]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.m.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.m.meta new file mode 100644 index 0000000..507d7d3 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCStorage.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 408ce9c19e21b4e8d912a48bfa72f38a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.h b/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.h new file mode 100644 index 0000000..c5c28b3 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.h @@ -0,0 +1,12 @@ +#import +#import + +@interface ZPCUtils : NSObject ++ (UIViewController *)getTopViewController; ++ (UIView *)getTopView; ++ (NSString *)getIsoNow; ++ (NSString *)toIsoDate:(NSDate *)date; ++ (NSDate *)parseDateIso:(NSString *)dateString; ++ (void)cleanDictionary:(NSDictionary *)dict; ++ (int)notchSize; +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.h.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.h.meta new file mode 100644 index 0000000..b7b409a --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 37bd36bc9f2ae4c3aa90d3a51f4dae2f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.m b/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.m new file mode 100644 index 0000000..729fe20 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.m @@ -0,0 +1,81 @@ +#import "ZPCUtils.h" +#import "ZPCLog.h" + +@implementation ZPCUtils + ++ (UIViewController *)getTopViewController { + return UIApplication.sharedApplication.delegate.window.rootViewController; +} + ++ (UIView *)getTopView { + UIViewController *root = [self getTopViewController]; + + if (root.presentedViewController) { + return root.presentedViewController.view; + } + + return root.view; +} + ++ (NSDateFormatter *)getIsoFormatter { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + [dateFormatter setLocale:enUSPOSIXLocale]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]; + return dateFormatter; +} + ++ (NSString *)getIsoNow { + NSDate *now = [NSDate date]; + return [ZPCUtils toIsoDate:now]; +} + ++ (NSString *)toIsoDate:(NSDate *)date { + NSDateFormatter *dateFormatter = [ZPCUtils getIsoFormatter]; + return [dateFormatter stringFromDate:date]; +} + ++ (NSDate *)parseDateIso:(NSString *)dateString { + NSDateFormatter *dateFormatter = [ZPCUtils getIsoFormatter]; + return [dateFormatter dateFromString:dateString]; +} + ++ (void)cleanDictionary:(NSDictionary *)dict { + NSMutableArray *keys = [NSMutableArray array]; + for (id key in dict) { + id value = dict[key]; + + if ([value isKindOfClass:[NSDictionary class]]) { + [ZPCUtils cleanDictionary:value]; + } else if ([value isEqual:[NSNull null]]) { + [keys addObject:key]; + } else if ([value isKindOfClass:[NSMutableArray class]]) { + [ZPCUtils cleanArray:value]; + } + } + + for (id key in keys) { + [dict setValue:nil forKey:key]; + } +} + ++ (void)cleanArray:(NSMutableArray *)array { + for (id value in array) { + if ([value isKindOfClass:[NSDictionary class]]) { + [ZPCUtils cleanDictionary:value]; + } else if ([value isKindOfClass:[NSArray class]]) { + [ZPCUtils cleanArray:value]; + } + } +} + ++ (int)notchSize { + if (@available(iOS 11.0, *)) { + UIWindow *window = UIApplication.sharedApplication.keyWindow; + return window.safeAreaInsets.top; + } else { + return 0; + } +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.m.meta b/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.m.meta new file mode 100644 index 0000000..046f995 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Utilities/ZPCUtils.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: b08661092e85149b79f10cf9d83e0ee4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views.meta b/Assets/Plugins/iOS/Zapic/Views.meta new file mode 100644 index 0000000..b7eb720 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f788152a17afc458481341a1193be745 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.h b/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.h new file mode 100644 index 0000000..407b1cd --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.h @@ -0,0 +1,5 @@ +#import + +@interface ZPCBackgroundView : UIView +- (void)placeViewToBackground; +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.h.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.h.meta new file mode 100644 index 0000000..d2d12b2 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: af15d1f36313e4d35b5f491434286902 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.m b/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.m new file mode 100644 index 0000000..edfad79 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.m @@ -0,0 +1,49 @@ +#import "ZPCBackgroundView.h" + +@interface ZPCBackgroundView () +@property (nonatomic, assign) BOOL needsPlacement; +@property (nonatomic, copy) NSArray<__kindof UIView *> *subviews; +@end + +@implementation ZPCBackgroundView + +- (instancetype)initWithFrame:(CGRect)frame { + self.needsPlacement = false; + self.subviews = [[NSArray alloc] init]; + self.accessibilityElementsHidden = true; + return [super initWithFrame:frame]; +} + +- (void)willMoveToSuperview:(UIView *)newSuperview { + [super willMoveToSuperview:newSuperview]; + if (!newSuperview) { + self.needsPlacement = true; + } +} + +- (void)didMoveToSuperview { + [super didMoveToSuperview]; + if (self.needsPlacement) { + [self placeViewToBackground]; + } +} + +- (void)placeViewToBackground { + if (!self.superview) { + [self setHidden:YES]; + [[UIApplication sharedApplication].windows.firstObject addSubview:self]; + + if (self.superview) { + [self.superview sendSubviewToBack:self]; + } + + self.needsPlacement = false; + } +} + +- (void)addSubview:(UIView *)view { + [super addSubview:view]; + self.subviews = [[NSArray alloc] init]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.m.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.m.meta new file mode 100644 index 0000000..6ad90e0 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBackgroundView.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 19b2312c9760d42d8bebd5bd92a96513 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.h b/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.h new file mode 100644 index 0000000..e58ac62 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.h @@ -0,0 +1,11 @@ +#import +#import + +@interface ZPCBanner : UIView + +@property (nonatomic, copy) void (^callback)(void); + +- (instancetype)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image; +- (void)show:(NSTimeInterval)duration; + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.h.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.h.meta new file mode 100644 index 0000000..22ede0a --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 898d6f6cef8ec4e67baaf6adfa25b33a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.m b/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.m new file mode 100644 index 0000000..6de9acd --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.m @@ -0,0 +1,204 @@ +#import "ZPCBanner.h" +#import "ZPCGradientBar.h" +#import "ZPCLog.h" +#import "ZPCUtils.h" + +@interface ZPCBanner () +@property (nonatomic, assign) float topPadding; +@property (nonatomic, strong) NSLayoutConstraint *showingConstraint; +@property (nonatomic, strong) NSLayoutConstraint *hiddenConstraint; +@end + +@implementation ZPCBanner + +static CGFloat const bannerHeight = 66; +static CGFloat const animationDuration = 0.4; + +- (instancetype)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle image:(UIImage *)image { + if (self = [super initWithFrame:CGRectZero]) { + _topPadding = [ZPCUtils notchSize]; + + if (![UIApplication sharedApplication].isStatusBarHidden) { + _topPadding = [UIApplication sharedApplication].statusBarFrame.size.height; + } + + self.backgroundColor = UIColor.whiteColor; + self.translatesAutoresizingMaskIntoConstraints = NO; + + float bannerWidth = MIN(375, MIN(UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height)); + [self.widthAnchor constraintEqualToConstant:bannerWidth].active = YES; + [self.heightAnchor constraintEqualToConstant:bannerHeight].active = YES; + + //Add the gradient to the top + ZPCGradientBar *gradient = [[ZPCGradientBar alloc] init]; + [self addSubview:gradient]; + + //Adds the icon + UIImageView *iconView = [[UIImageView alloc] initWithImage:image]; + iconView.translatesAutoresizingMaskIntoConstraints = NO; + iconView.contentMode = UIViewContentModeScaleAspectFit; + iconView.layer.cornerRadius = 5; + iconView.layer.masksToBounds = YES; + + [self addSubview:iconView]; + + CGFloat const iconPadding = 8; + [iconView.topAnchor constraintEqualToAnchor:gradient.bottomAnchor constant:iconPadding].active = YES; + [iconView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:iconPadding].active = YES; + [iconView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-iconPadding].active = YES; + [iconView.widthAnchor constraintEqualToAnchor:iconView.heightAnchor].active = YES; + + //Add the content container + UIView *content = [[UIView alloc] init]; + content.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:content]; + + static CGFloat const contentPadding = 5; + [content.topAnchor constraintEqualToAnchor:gradient.bottomAnchor constant:contentPadding].active = YES; + [content.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-contentPadding].active = YES; + [content.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:-contentPadding].active = YES; + [content.leftAnchor constraintEqualToAnchor:iconView.rightAnchor constant:contentPadding].active = YES; + + static CGFloat const subtitlePadding = 10; + + //Add the title + UILabel *titleLabel = [[UILabel alloc] init]; + titleLabel.font = [UIFont systemFontOfSize:16]; + titleLabel.text = title; + titleLabel.numberOfLines = 1; + titleLabel.textAlignment = NSTextAlignmentCenter; + + [content addSubview:titleLabel]; + + titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [titleLabel.centerXAnchor constraintEqualToAnchor:content.centerXAnchor].active = YES; + [titleLabel.centerYAnchor constraintEqualToAnchor:content.centerYAnchor constant:subtitle ? -subtitlePadding : 0].active = YES; + [titleLabel.widthAnchor constraintEqualToAnchor:content.widthAnchor].active = YES; + + if (subtitle) { + UILabel *subtitleLabel = [[UILabel alloc] init]; + subtitleLabel.font = [UIFont systemFontOfSize:14]; + subtitleLabel.textColor = [UIColor.blackColor colorWithAlphaComponent:0.5]; + subtitleLabel.text = subtitle; + subtitleLabel.numberOfLines = 1; + subtitleLabel.textAlignment = NSTextAlignmentCenter; + + [content addSubview:subtitleLabel]; + + subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [subtitleLabel.centerXAnchor constraintEqualToAnchor:content.centerXAnchor].active = YES; + [subtitleLabel.centerYAnchor constraintEqualToAnchor:content.centerYAnchor constant:subtitlePadding].active = YES; + [subtitleLabel.widthAnchor constraintEqualToAnchor:content.widthAnchor].active = YES; + } + + //Adds the shadown to the banner + self.layer.shadowColor = UIColor.blackColor.CGColor; + self.layer.shadowOpacity = 0.5; + self.layer.shadowOffset = CGSizeZero; + self.layer.shadowRadius = 4; + + [self addGestures]; + } + return self; +} + +- (void)didMoveToSuperview { + [super didMoveToSuperview]; + + if (!self.superview) { + return; + } + + [self.centerXAnchor constraintEqualToAnchor:self.superview.centerXAnchor].active = YES; + + _showingConstraint = [self.topAnchor constraintEqualToAnchor:self.superview.topAnchor constant:_topPadding]; + + // Offset the bottom constraint to make room for the shadow to animate off screen. + _hiddenConstraint = [self.bottomAnchor constraintEqualToAnchor:self.superview.topAnchor constant:-7.0]; +} + +- (void)show:(NSTimeInterval)duration { + //Finds the current view controller being shown + UIView *topView = [ZPCUtils getTopView]; + + //Adds the banner to that view + [topView addSubview:self]; + + [self setVisibility:NO]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [UIView animateWithDuration:animationDuration + delay:0.0 + usingSpringWithDamping:0.7 + initialSpringVelocity:1.5 + options:UIViewAnimationOptionAllowUserInteraction + animations:^{ + [self setVisibility:YES]; + } + completion:^(BOOL finished) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self dismiss]; + }); + }]; + }); +} + +- (void)addGestures { + //Tap gesture + [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTap:)]]; + + //Swipe gesture + UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(didSwipe:)]; + swipe.direction = UISwipeGestureRecognizerDirectionUp; + [self addGestureRecognizer:swipe]; +} + +- (void)didTap:(UITapGestureRecognizer *)rec { + [self dismiss]; + + if (self.callback) { + self.callback(); + } +} + +- (void)didSwipe:(UISwipeGestureRecognizer *)rec { + [self dismiss]; +} + +- (void)dismiss { + [UIView animateWithDuration:animationDuration + delay:0.0 + usingSpringWithDamping:0.7 + initialSpringVelocity:1.5 + options:UIViewAnimationOptionAllowUserInteraction + animations:^{ + [self setVisibility:NO]; + } + completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + +- (void)setVisibility:(BOOL)show { + if (show) { + [self.superview removeConstraint:_hiddenConstraint]; + [self.superview addConstraint:_showingConstraint]; + } else { + [self.superview removeConstraint:_showingConstraint]; + [self.superview addConstraint:_hiddenConstraint]; + } + + [self setNeedsLayout]; + [self setNeedsUpdateConstraints]; + + // Managing different -layoutIfNeeded behaviours among iOS versions (for more, read the UIKit iOS 10 release notes) + if (@available(iOS 10.0, *)) { + [self.superview layoutIfNeeded]; + } else { + [self layoutIfNeeded]; + } + [self updateConstraintsIfNeeded]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.m.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.m.meta new file mode 100644 index 0000000..f9cf2a5 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBanner.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 2b589d57a7a26489b8bea11203a15e3d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.h b/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.h new file mode 100644 index 0000000..3013d4c --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.h @@ -0,0 +1,8 @@ +#import +#import "ZPCCore.h" + +@interface ZPCBaseView : UIView +@property (weak) ZPCCore *viewController; +- (instancetype)initWithSpinner; +- (instancetype)initWithText:(NSString *)text subText:(NSString *)subText showSpinner:(BOOL)showSpinner; +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.h.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.h.meta new file mode 100644 index 0000000..491acf2 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: d5acd78f65e6647aabd06054e882a052 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.m b/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.m new file mode 100644 index 0000000..4f348dc --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.m @@ -0,0 +1,108 @@ +#import "ZPCBaseView.h" +#import "ZPCGradientBar.h" +#import "ZPCImageUtils.h" +#import "ZPCLog.h" +#import "ZPCUtils.h" + +@implementation ZPCBaseView + +- (instancetype)initWithSpinner { + return [self initWithText:nil subText:nil showSpinner:YES]; +} + +- (instancetype)initWithText:(NSString *)text subText:(NSString *)subText showSpinner:(BOOL)showSpinner { + if (self = [super initWithFrame:CGRectZero]) { + //Background color + self.backgroundColor = [UIColor.blackColor colorWithAlphaComponent:0.8]; + + //Add the gradient to the top + ZPCGradientBar *gradient = [[ZPCGradientBar alloc] init]; + [self addSubview:gradient]; + + //Add the zapic logo to the center of the screen + UIImageView *icon = [[UIImageView alloc] initWithImage:[ZPCImageUtils getZapicLogo]]; + icon.contentMode = UIViewContentModeScaleAspectFit; + icon.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:icon]; + + CGFloat const iconSize = 64; + [icon.centerXAnchor constraintEqualToAnchor:self.centerXAnchor].active = YES; + [icon.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:-150].active = YES; + [icon.heightAnchor constraintEqualToConstant:iconSize].active = YES; + [icon.widthAnchor constraintEqualToConstant:iconSize].active = YES; + + NSLayoutYAxisAnchor *lastAnchor = icon.bottomAnchor; + + if (showSpinner) { + UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + spinner.translatesAutoresizingMaskIntoConstraints = NO; + [spinner startAnimating]; + + [self addSubview:spinner]; + + [spinner.topAnchor constraintEqualToAnchor:lastAnchor constant:20].active = YES; + [spinner.centerXAnchor constraintEqualToAnchor:self.centerXAnchor].active = YES; + + lastAnchor = spinner.bottomAnchor; + } + + //Adds the text + if (text) { + UILabel *title = [[UILabel alloc] init]; + title.font = [UIFont systemFontOfSize:22]; + title.text = text; + title.textAlignment = NSTextAlignmentCenter; + title.textColor = UIColor.whiteColor; + title.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:title]; + + [title.centerXAnchor constraintEqualToAnchor:self.centerXAnchor].active = YES; + [title.topAnchor constraintEqualToAnchor:lastAnchor constant:15].active = YES; + + lastAnchor = title.bottomAnchor; + } + + //Adds the subtext + if (subText) { + UILabel *details = [[UILabel alloc] init]; + details.font = [UIFont systemFontOfSize:18]; + details.text = subText; + details.textAlignment = NSTextAlignmentCenter; + details.lineBreakMode = NSLineBreakByWordWrapping; + details.numberOfLines = 0; + details.textColor = [UIColor.whiteColor colorWithAlphaComponent:0.5]; + details.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:details]; + + [details.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:50].active = YES; + [details.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:-50].active = YES; + [details.topAnchor constraintEqualToAnchor:lastAnchor constant:15].active = YES; + } + + UIButton *closeButton = [[UIButton alloc] init]; + [closeButton setTitle:@"Done" forState:UIControlStateNormal]; + [closeButton addTarget:self action:@selector(closeButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + closeButton.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:closeButton]; + + [closeButton.topAnchor constraintEqualToAnchor:gradient.bottomAnchor constant:10].active = YES; + [closeButton.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:10].active = YES; + } + return self; +} + +- (void)closeButtonAction:(UIButton *)sender { + if (!_viewController) { + [ZPCLog error:@"Unable to close the view. No view controller set"]; + return; + } + + [ZPCLog info:@"Close button tapped"]; + [_viewController closePage]; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.m.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.m.meta new file mode 100644 index 0000000..61e582c --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCBaseView.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 89d67e08d6dfe4a95b1096f80f52e749 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.h b/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.h new file mode 100644 index 0000000..ccdd4a6 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.h @@ -0,0 +1,6 @@ +#import +#import "ZPCBaseView.h" + +@interface ZPCErrorView : ZPCBaseView + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.h.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.h.meta new file mode 100644 index 0000000..a8b146a --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 61d094e59292a44cd97088928001ea06 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.m b/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.m new file mode 100644 index 0000000..fffa7bb --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.m @@ -0,0 +1,11 @@ +#import "ZPCErrorView.h" + +@implementation ZPCErrorView + +- (instancetype)init { + if (self = [super initWithText:@"Could Not Connect" subText:@"Please check your network connection and try again" showSpinner:NO]) { + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.m.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.m.meta new file mode 100644 index 0000000..5c355cb --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCErrorView.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 2bc4d1e55703241ce85613171eee6dd1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.h b/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.h new file mode 100644 index 0000000..89b0ba9 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.h @@ -0,0 +1,5 @@ +#import + +@interface ZPCGradientBar : UIView + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.h.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.h.meta new file mode 100644 index 0000000..c19ec76 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 3fe9ed0106f6948d7877648f950421d2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.m b/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.m new file mode 100644 index 0000000..694bf8e --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.m @@ -0,0 +1,47 @@ +#import "ZPCGradientBar.h" + +@interface ZPCGradientBar () +@property (nonatomic, strong) CAGradientLayer *gradient; +@end + +@implementation ZPCGradientBar + +- (instancetype)init { + if (self = [super initWithFrame:CGRectZero]) { + self.backgroundColor = UIColor.redColor; + _gradient = [CAGradientLayer layer]; + + _gradient.frame = self.bounds; + + UIColor *zBlue = [UIColor colorWithRed:0.00 green:0.87 blue:0.68 alpha:1.0]; + UIColor *zGreen = [UIColor colorWithRed:0.00 green:0.52 blue:0.89 alpha:1.0]; + _gradient.startPoint = CGPointMake(1, 0); + _gradient.endPoint = CGPointZero; + _gradient.colors = @[(id)zBlue.CGColor, (id)zGreen.CGColor]; + + [self.layer insertSublayer:_gradient atIndex:0]; + } + return self; +} + +- (void)layoutSubviews { + _gradient.frame = self.frame; +} + +- (void)didMoveToSuperview { + [super didMoveToSuperview]; + + UIView *superview = self.superview; + + if (!superview) { + return; + } + + self.translatesAutoresizingMaskIntoConstraints = NO; + [self.topAnchor constraintEqualToAnchor:superview.topAnchor].active = YES; + [self.heightAnchor constraintEqualToConstant:6].active = YES; + [self.leadingAnchor constraintEqualToAnchor:superview.leadingAnchor].active = YES; + [self.trailingAnchor constraintEqualToAnchor:superview.trailingAnchor].active = YES; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.m.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.m.meta new file mode 100644 index 0000000..b3c3afa --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCGradientBar.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: f44076ab91c8c4d0e8c31a0600d02467 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.h b/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.h new file mode 100644 index 0000000..c1d3941 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.h @@ -0,0 +1,6 @@ +#import +#import "ZPCBaseView.h" + +@interface ZPCLoadingView : ZPCBaseView + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.h.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.h.meta new file mode 100644 index 0000000..cc97892 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 31d97249eddd24df3b8eda4caf11727f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.m b/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.m new file mode 100644 index 0000000..978b8ce --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.m @@ -0,0 +1,11 @@ +#import "ZPCLoadingView.h" + +@implementation ZPCLoadingView + +- (instancetype)init { + if (self = [super initWithSpinner]) { + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.m.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.m.meta new file mode 100644 index 0000000..6fb4fcc --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCLoadingView.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 1cf2765ab94d64ce0b54950769b03365 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.h b/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.h new file mode 100644 index 0000000..30d2a0f --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.h @@ -0,0 +1,16 @@ +#import +#import +#import "ZPCSafariManager.h" +#import "ZPCScriptMessageHandler.h" + +@interface ZPCWebApp : UIView +@property ZPCSafariManager *safariManager; +@property (readonly) BOOL errorLoading; +/** + The handler when a player logs in to Zapic. + */ +@property (nonatomic, copy, nullable) void (^loadErrorHandler)(void); +- (instancetype)initWithHandler:(nonnull ZPCScriptMessageHandler *)messageHandler; +- (void)loadUrl:(NSString *)url; +- (void)evaluateJavaScript:(NSString *)jsString; +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.h.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.h.meta new file mode 100644 index 0000000..b5aab43 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.h.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: b188ac43819f64655837d44f3b171175 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.m b/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.m new file mode 100644 index 0000000..2cab601 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.m @@ -0,0 +1,195 @@ +#import "ZPCWebApp.h" +#import "ZPCInjectedJS.h" +#import "ZPCLog.h" +#import "ZPCUtils.h" + +@interface ZPCWebApp () + +@property (nonatomic, strong) NSString *appUrl; +@property (nonatomic, assign) bool loadSuccessful; +@property (nonatomic, assign) int retryAttempt; +@property (readonly) WKWebView *webView; + +@end + +@implementation ZPCWebApp + +- (instancetype)initWithHandler:(nonnull ZPCScriptMessageHandler *)messageHandler { + if (self = [super initWithFrame:CGRectZero]) { + WKWebViewConfiguration *config = [ZPCWebApp getWebViewConfiguration]; + [config.userContentController addScriptMessageHandler:messageHandler name:ZPCScriptMethodName]; + + _webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config]; + + _webView.translatesAutoresizingMaskIntoConstraints = NO; + _webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); + _webView.scrollView.scrollEnabled = NO; + _webView.scrollView.bounces = NO; + _webView.scrollView.delegate = self; + _webView.navigationDelegate = self; + + [self addSubview:_webView]; + [_webView.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES; + [_webView.leftAnchor constraintEqualToAnchor:self.leftAnchor].active = YES; + [_webView.rightAnchor constraintEqualToAnchor:self.rightAnchor].active = YES; + [_webView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES; + } + return self; +} + +- (void)evaluateJavaScript:(NSString *)jsString { + dispatch_async(dispatch_get_main_queue(), ^{ + [ZPCLog info:@"Dispatching %@", jsString]; + + if (!self.webView) { + [ZPCLog error:@"Webview has not been set, unable to send"]; + return; + } + + [self.webView evaluateJavaScript:jsString + completionHandler:^(id _Nullable result, NSError *_Nullable error) { + if (error) { + [ZPCLog error:@"JS Error: %@", error]; + } else if (result) { + [ZPCLog info:@"JS Result: %@", result]; + } + }]; + }); +} + +- (void)loadUrl:(NSString *)url { + _appUrl = url; + [self load]; +} + +- (void)load { + NSURLRequest *appRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:_appUrl]]; + + [_webView loadRequest:appRequest]; +} + ++ (WKWebViewConfiguration *)getWebViewConfiguration { + WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; + + //Gets the JS code to be injected + NSString *injected = [ZPCInjectedJS getInjectedScript]; + + WKUserScript *script = [[WKUserScript alloc] initWithSource:injected injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; + + [config.userContentController addUserScript:script]; + + return config; +} + +- (void)retryAfterDelay { + if (_loadSuccessful) { + return; + } + + _retryAttempt += 1; + + static CGFloat const base = 5; + static CGFloat const maxDelay = 300; //5 minutes + + //Calculate the delay before the next retry + float delay = MAX(1, drand48() * MIN(maxDelay, base * pow(2.0, _retryAttempt))); + + [ZPCLog info:@"Will try to reload in %f sec", delay]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self load]; + }); +} + +#pragma mark - WKNavigationDelegate + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { + [ZPCLog info:@"Finished loading web app"]; + _retryAttempt = 0; + _loadSuccessful = YES; + _errorLoading = NO; +} + +/** + Handles any errors loading the web view + + @param webView The web view invoking the delegate method. + @param navigation The navigation object that started to load a page. + @param error The error that occurred. + */ +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { + if ([error.domain isEqual:@"WebKitErrorDomain"] && error.code == 102) { + [ZPCLog info:@"Skipping known error message loading url"]; + return; + } + + [ZPCLog warn:@"Error loading Zapic webview"]; + + [self retryAfterDelay]; + + _errorLoading = YES; + + if (_loadErrorHandler) { + _loadErrorHandler(); + } +} + +- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + NSURL *url = [navigationAction valueForKeyPath:@"request.URL"]; + + int const cancel = 0; + int const allow = 1; + + //Skip if there is not a valid url + if (!url) { + decisionHandler(cancel); + return; + } + + //Skip if the app has not loaded yet + if (!_appUrl) { + decisionHandler(cancel); + return; + } + + //Allow the webview to open other links that are within our web app. + if ([url.absoluteString hasPrefix:_appUrl]) { + decisionHandler(allow); + return; + } + NSString *scheme = url.scheme; + + if (!scheme) { + decisionHandler(cancel); + return; + } + + //Allow the OS to open the itms links directly into the app store + if ([scheme hasPrefix:@"itms"]) { + [UIApplication.sharedApplication openURL:url]; + decisionHandler(cancel); + return; + } + + //Opens the a safari view with the content + [_safariManager openUrl:url]; + + //Tell the webview not to open the link + decisionHandler(cancel); +} + +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view { + scrollView.pinchGestureRecognizer.enabled = NO; + scrollView.panGestureRecognizer.enabled = NO; + [scrollView setZoomScale:1.0 animated:NO]; +} + +- (void)scrollViewDidZoom:(UIScrollView *)scrollView { + if (scrollView.zoomScale == 1) { + return; + } + [scrollView setZoomScale:1.0 animated:NO]; +} +@end diff --git a/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.m.meta b/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.m.meta new file mode 100644 index 0000000..4a355c3 --- /dev/null +++ b/Assets/Plugins/iOS/Zapic/Views/ZPCWebApp.m.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 863beee9b48be401f9566540e206c93c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/AssetCatalog.cs b/Assets/Zapic/Editor/Xcode.Custom/AssetCatalog.cs deleted file mode 100644 index a789698..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/AssetCatalog.cs +++ /dev/null @@ -1,834 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode -#else -namespace UnityEditor.iOS.Xcode.Custom -#endif -{ - internal class DeviceTypeRequirement - { - public static readonly string Key = "idiom"; - public static readonly string Any = "universal"; - public static readonly string iPhone = "iphone"; - public static readonly string iPad = "ipad"; - public static readonly string Mac = "mac"; - public static readonly string iWatch = "watch"; - } - - internal class MemoryRequirement - { - public static readonly string Key = "memory"; - public static readonly string Any = ""; - public static readonly string Mem1GB = "1GB"; - public static readonly string Mem2GB = "2GB"; - } - - internal class GraphicsRequirement - { - public static readonly string Key = "graphics-feature-set"; - public static readonly string Any = ""; - public static readonly string Metal1v2 = "metal1v2"; - public static readonly string Metal2v2 = "metal2v2"; - } - - // only used for image sets - internal class SizeClassRequirement - { - public static readonly string HeightKey = "height-class"; - public static readonly string WidthKey = "width-class"; - public static readonly string Any = ""; - public static readonly string Compact = "compact"; - public static readonly string Regular = "regular"; - } - - // only used for image sets - internal class ScaleRequirement - { - public static readonly string Key = "scale"; - public static readonly string Any = ""; // vector image - public static readonly string X1 = "1x"; - public static readonly string X2 = "2x"; - public static readonly string X3 = "3x"; - } - - internal class DeviceRequirement - { - internal Dictionary values = new Dictionary(); - - public DeviceRequirement AddDevice(string device) - { - AddCustom(DeviceTypeRequirement.Key, device); - return this; - } - - public DeviceRequirement AddMemory(string memory) - { - AddCustom(MemoryRequirement.Key, memory); - return this; - } - - public DeviceRequirement AddGraphics(string graphics) - { - AddCustom(GraphicsRequirement.Key, graphics); - return this; - } - - public DeviceRequirement AddWidthClass(string sizeClass) - { - AddCustom(SizeClassRequirement.WidthKey, sizeClass); - return this; - } - - public DeviceRequirement AddHeightClass(string sizeClass) - { - AddCustom(SizeClassRequirement.HeightKey, sizeClass); - return this; - } - - public DeviceRequirement AddScale(string scale) - { - AddCustom(ScaleRequirement.Key, scale); - return this; - } - - public DeviceRequirement AddCustom(string key, string value) - { - if (values.ContainsKey(key)) - values.Remove(key); - values.Add(key, value); - return this; - } - - public DeviceRequirement() - { - values.Add("idiom", DeviceTypeRequirement.Any); - } - } - - internal class AssetCatalog - { - AssetFolder m_Root; - - public string path { get { return m_Root.path; } } - public AssetFolder root { get { return m_Root; } } - - public AssetCatalog(string path, string authorId) - { - if (Path.GetExtension(path) != ".xcassets") - throw new Exception("Asset catalogs must have xcassets extension"); - m_Root = new AssetFolder(path, null, authorId); - } - - AssetFolder OpenFolderForResource(string relativePath) - { - var pathItems = PBXPath.Split(relativePath).ToList(); - - // remove path filename - pathItems.RemoveAt(pathItems.Count - 1); - - AssetFolder folder = root; - foreach (var pathItem in pathItems) - folder = folder.OpenFolder(pathItem); - return folder; - } - - // Checks if a dataset at the given path exists and returns it if it does. - // Otherwise, creates a new dataset. Parent folders are created if needed. - // Note: the path is filesystem path, not logical asset name formed - // only from names of the folders that have "provides namespace" attribute. - // If you want to put certain resources in folders with namespace, first - // manually create the folders and then set the providesNamespace attribute. - // OpenNamespacedFolder may help to do this. - public AssetDataSet OpenDataSet(string relativePath) - { - var folder = OpenFolderForResource(relativePath); - return folder.OpenDataSet(Path.GetFileName(relativePath)); - } - - public AssetImageSet OpenImageSet(string relativePath) - { - var folder = OpenFolderForResource(relativePath); - return folder.OpenImageSet(Path.GetFileName(relativePath)); - } - - public AssetImageStack OpenImageStack(string relativePath) - { - var folder = OpenFolderForResource(relativePath); - return folder.OpenImageStack(Path.GetFileName(relativePath)); - } - - public AssetBrandAssetGroup OpenBrandAssetGroup(string relativePath) - { - var folder = OpenFolderForResource(relativePath); - return folder.OpenBrandAssetGroup(Path.GetFileName(relativePath)); - } - - // Checks if a folder with given path exists and returns it if it does. - // Otherwise, creates a new folder. Parent folders are created if needed. - public AssetFolder OpenFolder(string relativePath) - { - if (relativePath == null) - return root; - var pathItems = PBXPath.Split(relativePath); - if (pathItems.Length == 0) - return root; - AssetFolder folder = root; - foreach (var pathItem in pathItems) - folder = folder.OpenFolder(pathItem); - return folder; - } - - // Creates a directory structure with "provides namespace" attribute. - // First, retrieves or creates the directory at relativeBasePath, creating parent - // directories if needed. Effectively calls OpenFolder(relativeBasePath). - // Then, relative to this directory, creates namespacePath directories with "provides - // namespace" attribute set. Fails if the attribute can't be set. - public AssetFolder OpenNamespacedFolder(string relativeBasePath, string namespacePath) - { - var folder = OpenFolder(relativeBasePath); - var pathItems = PBXPath.Split(namespacePath); - foreach (var pathItem in pathItems) - { - folder = folder.OpenFolder(pathItem); - folder.providesNamespace = true; - } - return folder; - } - - public void Write() - { - Write(null); - } - - public void Write(List warnings) - { - m_Root.Write(warnings); - } - } - - internal abstract class AssetCatalogItem - { - public readonly string name; - public readonly string authorId; - public string path { get { return m_Path; } } - - protected Dictionary m_Properties = new Dictionary(); - - protected string m_Path; - - public AssetCatalogItem(string name, string authorId) - { - if (name != null && name.Contains("/")) - throw new Exception("Asset catalog item must not have slashes in name"); - this.name = name; - this.authorId = authorId; - } - - protected JsonElementDict WriteInfoToJson(JsonDocument doc) - { - var info = doc.root.CreateDict("info"); - info.SetInteger("version", 1); - info.SetString("author", authorId); - return info; - } - - public abstract void Write(List warnings); - } - - internal class AssetFolder : AssetCatalogItem - { - List m_Items = new List(); - bool m_ProvidesNamespace = false; - - public bool providesNamespace - { - get { return m_ProvidesNamespace; } - set { - if (m_Items.Count > 0 && value != m_ProvidesNamespace) - throw new Exception("Asset folder namespace providing status can't be "+ - "changed after items have been added"); - m_ProvidesNamespace = value; - } - } - - internal AssetFolder(string parentPath, string name, string authorId) : base(name, authorId) - { - if (name != null) - m_Path = Path.Combine(parentPath, name); - else - m_Path = parentPath; - } - - // Checks if a folder with given name exists and returns it if it does. - // Otherwise, creates a new folder. - public AssetFolder OpenFolder(string name) - { - var item = GetChild(name); - if (item != null) - { - if (item is AssetFolder) - return item as AssetFolder; - throw new Exception("The given path is already occupied with an asset"); - } - - var folder = new AssetFolder(m_Path, name, authorId); - m_Items.Add(folder); - return folder; - } - - T GetExistingItemWithType(string name) where T : class - { - var item = GetChild(name); - if (item != null) - { - if (item is T) - return item as T; - throw new Exception("The given path is already occupied with an asset"); - } - return null; - } - - // Checks if a dataset with given name exists and returns it if it does. - // Otherwise, creates a new data set. - public AssetDataSet OpenDataSet(string name) - { - var item = GetExistingItemWithType(name); - if (item != null) - return item; - - var dataset = new AssetDataSet(m_Path, name, authorId); - m_Items.Add(dataset); - return dataset; - } - - // Checks if an imageset with given name exists and returns it if it does. - // Otherwise, creates a new image set. - public AssetImageSet OpenImageSet(string name) - { - var item = GetExistingItemWithType(name); - if (item != null) - return item; - - var imageset = new AssetImageSet(m_Path, name, authorId); - m_Items.Add(imageset); - return imageset; - } - - // Checks if a image stack with given name exists and returns it if it does. - // Otherwise, creates a new image stack. - public AssetImageStack OpenImageStack(string name) - { - var item = GetExistingItemWithType(name); - if (item != null) - return item; - - var imageStack = new AssetImageStack(m_Path, name, authorId); - m_Items.Add(imageStack); - return imageStack; - } - - // Checks if a brand asset with given name exists and returns it if it does. - // Otherwise, creates a new brand asset. - public AssetBrandAssetGroup OpenBrandAssetGroup(string name) - { - var item = GetExistingItemWithType(name); - if (item != null) - return item; - - var brandAsset = new AssetBrandAssetGroup(m_Path, name, authorId); - m_Items.Add(brandAsset); - return brandAsset; - } - - // Returns the requested item or null if not found - public AssetCatalogItem GetChild(string name) - { - foreach (var item in m_Items) - { - if (item.name == name) - return item; - } - return null; - } - - void WriteJson() - { - if (!providesNamespace) - return; // json is optional when namespace is not provided - - var doc = new JsonDocument(); - - WriteInfoToJson(doc); - - var props = doc.root.CreateDict("properties"); - props.SetBoolean("provides-namespace", providesNamespace); - doc.WriteToFile(Path.Combine(m_Path, "Contents.json")); - } - - public override void Write(List warnings) - { - if (Directory.Exists(m_Path)) - Directory.Delete(m_Path, true); // ensure we start from clean state - Directory.CreateDirectory(m_Path); - WriteJson(); - - foreach (var item in m_Items) - item.Write(warnings); - } - } - - abstract class AssetCatalogItemWithVariants : AssetCatalogItem - { - protected List m_Variants = new List(); - protected List m_ODRTags = new List(); - - protected AssetCatalogItemWithVariants(string name, string authorId) : - base(name, authorId) - { - } - - protected class VariantData - { - public DeviceRequirement requirement; - public string path; - - public VariantData(DeviceRequirement requirement, string path) - { - this.requirement = requirement; - this.path = path; - } - } - - public bool HasVariant(DeviceRequirement requirement) - { - foreach (var item in m_Variants) - { - if (item.requirement.values == requirement.values) - return true; - } - return false; - } - - public void AddOnDemandResourceTag(string tag) - { - if (!m_ODRTags.Contains(tag)) - m_ODRTags.Add(tag); - } - - protected void AddVariant(VariantData newItem) - { - foreach (var item in m_Variants) - { - if (item.requirement.values == newItem.requirement.values) - throw new Exception("The given requirement has been already added"); - if (Path.GetFileName(item.path) == Path.GetFileName(path)) - throw new Exception("Two items within the same set must not have the same file name"); - } - if (Path.GetFileName(newItem.path) == "Contents.json") - throw new Exception("The file name must not be equal to Contents.json"); - m_Variants.Add(newItem); - } - - protected void WriteODRTagsToJson(JsonElementDict info) - { - if (m_ODRTags.Count > 0) - { - var tags = info.CreateArray("on-demand-resource-tags"); - foreach (var tag in m_ODRTags) - tags.AddString(tag); - } - } - - protected void WriteRequirementsToJson(JsonElementDict item, DeviceRequirement req) - { - foreach (var kv in req.values) - { - if (kv.Value != null && kv.Value != "") - item.SetString(kv.Key, kv.Value); - } - } - - // Returns the filename of the resulting file - protected string CopyFileToSet(string path, HashSet existingFilenames, List warnings) - { - var filename = Path.GetFileName(path); - if (!File.Exists(path)) - { - if (warnings != null) - warnings.Add("File not found: " + path); - } - else - { - // ensure that we don't create duplicate filenames - int index = 1; - string filenameBase = Path.GetFileNameWithoutExtension(filename); - string extension = Path.GetExtension(filename); - - while (existingFilenames.Contains(filename)) - { - filename = String.Format("{0}-{1}{2}", filenameBase, index, extension); - index++; - } - existingFilenames.Add(filename); - File.Copy(path, Path.Combine(m_Path, filename)); - } - return filename; - } - } - - internal class AssetDataSet : AssetCatalogItemWithVariants - { - class DataSetVariant : VariantData - { - public string id; - - public DataSetVariant(DeviceRequirement requirement, string path, string id) : base(requirement, path) - { - this.id = id; - } - } - - internal AssetDataSet(string parentPath, string name, string authorId) : base(name, authorId) - { - m_Path = Path.Combine(parentPath, name + ".dataset"); - } - - // an exception is thrown is two equivalent requirements are added. - // The same asset dataset must not have paths with equivalent filenames. - // The identifier allows to identify which data variant is actually loaded (use - // the typeIdentifer property of the NSDataAsset that was created from the data set) - public void AddVariant(DeviceRequirement requirement, string path, string typeIdentifier) - { - foreach (DataSetVariant item in m_Variants) - { - if (item.id != null && typeIdentifier != null && item.id == typeIdentifier) - throw new Exception("Two items within the same dataset must not have the same id"); - } - AddVariant(new DataSetVariant(requirement, path, typeIdentifier)); - } - - public override void Write(List warnings) - { - Directory.CreateDirectory(m_Path); - - var doc = new JsonDocument(); - - var info = WriteInfoToJson(doc); - WriteODRTagsToJson(info); - - var data = doc.root.CreateArray("data"); - - var existingFilenames = new HashSet(); - - foreach (DataSetVariant item in m_Variants) - { - var filename = CopyFileToSet(item.path, existingFilenames, warnings); - - var docItem = data.AddDict(); - docItem.SetString("filename", filename); - WriteRequirementsToJson(docItem, item.requirement); - if (item.id != null) - docItem.SetString("universal-type-identifier", item.id); - } - doc.WriteToFile(Path.Combine(m_Path, "Contents.json")); - } - } - - internal class ImageAlignment - { - public int left = 0, right = 0, top = 0, bottom = 0; - } - - internal class ImageResizing - { - public enum SlicingType - { - Horizontal, - Vertical, - HorizontalAndVertical - } - - public enum ResizeMode - { - Stretch, - Tile - } - - public SlicingType type = SlicingType.HorizontalAndVertical; - public int left = 0; // only valid for horizontal slicing - public int right = 0; // only valid for horizontal slicing - public int top = 0; // only valid for vertical slicing - public int bottom = 0; // only valid for vertical slicing - public ResizeMode centerResizeMode = ResizeMode.Stretch; - public int centerWidth = 0; // only valid for vertical slicing - public int centerHeight = 0; // only valid for horizontal slicing - } - - // TODO: rendering intent property - internal class AssetImageSet : AssetCatalogItemWithVariants - { - internal AssetImageSet(string assetCatalogPath, string name, string authorId) : base(name, authorId) - { - m_Path = Path.Combine(assetCatalogPath, name + ".imageset"); - } - - class ImageSetVariant : VariantData - { - public ImageAlignment alignment = null; - public ImageResizing resizing = null; - - public ImageSetVariant(DeviceRequirement requirement, string path) : base(requirement, path) - { - } - } - - public void AddVariant(DeviceRequirement requirement, string path) - { - AddVariant(new ImageSetVariant(requirement, path)); - } - - public void AddVariant(DeviceRequirement requirement, string path, ImageAlignment alignment, ImageResizing resizing) - { - var imageset = new ImageSetVariant(requirement, path); - imageset.alignment = alignment; - imageset.resizing = resizing; - AddVariant(imageset); - } - - void WriteAlignmentToJson(JsonElementDict item, ImageAlignment alignment) - { - var docAlignment = item.CreateDict("alignment-insets"); - docAlignment.SetInteger("top", alignment.top); - docAlignment.SetInteger("bottom", alignment.bottom); - docAlignment.SetInteger("left", alignment.left); - docAlignment.SetInteger("right", alignment.right); - } - - static string GetSlicingMode(ImageResizing.SlicingType mode) - { - switch (mode) - { - case ImageResizing.SlicingType.Horizontal: return "3-part-horizontal"; - case ImageResizing.SlicingType.Vertical: return "3-part-vertical"; - case ImageResizing.SlicingType.HorizontalAndVertical: return "9-part"; - } - return ""; - } - - static string GetCenterResizeMode(ImageResizing.ResizeMode mode) - { - switch (mode) - { - case ImageResizing.ResizeMode.Stretch: return "stretch"; - case ImageResizing.ResizeMode.Tile: return "tile"; - } - return ""; - } - - void WriteResizingToJson(JsonElementDict item, ImageResizing resizing) - { - var docResizing = item.CreateDict("resizing"); - docResizing.SetString("mode", GetSlicingMode(resizing.type)); - - var docCenter = docResizing.CreateDict("center"); - docCenter.SetString("mode", GetCenterResizeMode(resizing.centerResizeMode)); - docCenter.SetInteger("width", resizing.centerWidth); - docCenter.SetInteger("height", resizing.centerHeight); - - var docInsets = docResizing.CreateDict("cap-insets"); - docInsets.SetInteger("top", resizing.top); - docInsets.SetInteger("bottom", resizing.bottom); - docInsets.SetInteger("left", resizing.left); - docInsets.SetInteger("right", resizing.right); - } - - public override void Write(List warnings) - { - Directory.CreateDirectory(m_Path); - var doc = new JsonDocument(); - var info = WriteInfoToJson(doc); - WriteODRTagsToJson(info); - - var images = doc.root.CreateArray("images"); - - var existingFilenames = new HashSet(); - - foreach (ImageSetVariant item in m_Variants) - { - var filename = CopyFileToSet(item.path, existingFilenames, warnings); - - var docItem = images.AddDict(); - docItem.SetString("filename", filename); - WriteRequirementsToJson(docItem, item.requirement); - if (item.alignment != null) - WriteAlignmentToJson(docItem, item.alignment); - if (item.resizing != null) - WriteResizingToJson(docItem, item.resizing); - } - doc.WriteToFile(Path.Combine(m_Path, "Contents.json")); - } - } - - /* A stack layer may either contain an image set or reference another imageset - */ - class AssetImageStackLayer : AssetCatalogItem - { - internal AssetImageStackLayer(string assetCatalogPath, string name, string authorId) : base(name, authorId) - { - m_Path = Path.Combine(assetCatalogPath, name + ".imagestacklayer"); - m_Imageset = new AssetImageSet(m_Path, "Content", authorId); - } - - AssetImageSet m_Imageset = null; - string m_ReferencedName = null; - - public void SetReference(string name) - { - m_Imageset = null; - m_ReferencedName = name; - } - - public string ReferencedName() - { - return m_ReferencedName; - } - - public AssetImageSet GetImageSet() - { - return m_Imageset; - } - - public override void Write(List warnings) - { - Directory.CreateDirectory(m_Path); - var doc = new JsonDocument(); - WriteInfoToJson(doc); - - if (m_ReferencedName != null) - { - var props = doc.root.CreateDict("properties"); - var reference = props.CreateDict("content-reference"); - reference.SetString("type", "image-set"); - reference.SetString("name", m_ReferencedName); - reference.SetString("matching-style", "fully-qualified-name"); - } - if (m_Imageset != null) - m_Imageset.Write(warnings); - - doc.WriteToFile(Path.Combine(m_Path, "Contents.json")); - } - } - - class AssetImageStack : AssetCatalogItem - { - List m_Layers = new List(); - - internal AssetImageStack(string assetCatalogPath, string name, string authorId) : base(name, authorId) - { - m_Path = Path.Combine(assetCatalogPath, name + ".imagestack"); - } - - public AssetImageStackLayer AddLayer(string name) - { - foreach (var layer in m_Layers) - { - if (layer.name == name) - throw new Exception("A layer with given name already exists"); - } - var newLayer = new AssetImageStackLayer(m_Path, name, authorId); - m_Layers.Add(newLayer); - return newLayer; - } - - public override void Write(List warnings) - { - Directory.CreateDirectory(m_Path); - var doc = new JsonDocument(); - WriteInfoToJson(doc); - - var docLayers = doc.root.CreateArray("layers"); - foreach (var layer in m_Layers) - { - layer.Write(warnings); - - var docLayer = docLayers.AddDict(); - docLayer.SetString("filename", Path.GetFileName(layer.path)); - } - doc.WriteToFile(Path.Combine(m_Path, "Contents.json")); - } - } - - class AssetBrandAssetGroup : AssetCatalogItem - { - class AssetBrandAssetItem - { - internal string idiom = null; - internal string role = null; - internal int width, height; - internal AssetCatalogItem item = null; - - } - - List m_Items = new List(); - - internal AssetBrandAssetGroup(string assetCatalogPath, string name, string authorId) : base(name, authorId) - { - m_Path = Path.Combine(assetCatalogPath, name + ".brandassets"); - } - - void AddItem(AssetCatalogItem item, string idiom, string role, int width, int height) - { - foreach (var it in m_Items) - { - if (it.item.name == item.name) - throw new Exception("An item with given name already exists"); - } - var newItem = new AssetBrandAssetItem(); - newItem.item = item; - newItem.idiom = idiom; - newItem.role = role; - newItem.width = width; - newItem.height = height; - m_Items.Add(newItem); - } - - public AssetImageSet OpenImageSet(string name, string idiom, string role, int width, int height) - { - var newItem = new AssetImageSet(m_Path, name, authorId); - AddItem(newItem, idiom, role, width, height); - return newItem; - } - - public AssetImageStack OpenImageStack(string name, string idiom, string role, int width, int height) - { - var newItem = new AssetImageStack(m_Path, name, authorId); - AddItem(newItem, idiom, role, width, height); - return newItem; - } - - public override void Write(List warnings) - { - Directory.CreateDirectory(m_Path); - var doc = new JsonDocument(); - WriteInfoToJson(doc); - - var docAssets = doc.root.CreateArray("assets"); - foreach (var item in m_Items) - { - var docAsset = docAssets.AddDict(); - docAsset.SetString("size", String.Format("{0}x{1}", item.width, item.height)); - docAsset.SetString("idiom", item.idiom); - docAsset.SetString("role", item.role); - docAsset.SetString("filename", Path.GetFileName(item.item.path)); - - item.item.Write(warnings); - } - doc.WriteToFile(Path.Combine(m_Path, "Contents.json")); - } - } - -} // namespace UnityEditor.iOS.Xcode diff --git a/Assets/Zapic/Editor/Xcode.Custom/AssetCatalog.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/AssetCatalog.cs.meta deleted file mode 100644 index 96fbd14..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/AssetCatalog.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: ead45ed6b3a46469fa79e36d9b1cf342 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/JsonParser.cs b/Assets/Zapic/Editor/Xcode.Custom/JsonParser.cs deleted file mode 100644 index ddf7a61..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/JsonParser.cs +++ /dev/null @@ -1,261 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Linq; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode -#else -namespace UnityEditor.iOS.Xcode.Custom -#endif -{ - internal class JsonElement - { - protected JsonElement() {} - - // convenience methods - public string AsString() { return ((JsonElementString)this).value; } - public int AsInteger() { return ((JsonElementInteger)this).value; } - public bool AsBoolean() { return ((JsonElementBoolean)this).value; } - public JsonElementArray AsArray() { return (JsonElementArray)this; } - public JsonElementDict AsDict() { return (JsonElementDict)this; } - - public JsonElement this[string key] - { - get { return AsDict()[key]; } - set { AsDict()[key] = value; } - } - } - - internal class JsonElementString : JsonElement - { - public JsonElementString(string v) { value = v; } - - public string value; - } - - internal class JsonElementInteger : JsonElement - { - public JsonElementInteger(int v) { value = v; } - - public int value; - } - - internal class JsonElementBoolean : JsonElement - { - public JsonElementBoolean(bool v) { value = v; } - - public bool value; - } - - internal class JsonElementDict : JsonElement - { - public JsonElementDict() : base() {} - - private SortedDictionary m_PrivateValue = new SortedDictionary(); - public IDictionary values { get { return m_PrivateValue; }} - - new public JsonElement this[string key] - { - get { - if (values.ContainsKey(key)) - return values[key]; - return null; - } - set { this.values[key] = value; } - } - - public bool Contains(string key) - { - return values.ContainsKey(key); - } - - public void Remove(string key) - { - values.Remove(key); - } - - // convenience methods - public void SetInteger(string key, int val) - { - values[key] = new JsonElementInteger(val); - } - - public void SetString(string key, string val) - { - values[key] = new JsonElementString(val); - } - - public void SetBoolean(string key, bool val) - { - values[key] = new JsonElementBoolean(val); - } - - public JsonElementArray CreateArray(string key) - { - var v = new JsonElementArray(); - values[key] = v; - return v; - } - - public JsonElementDict CreateDict(string key) - { - var v = new JsonElementDict(); - values[key] = v; - return v; - } - } - - internal class JsonElementArray : JsonElement - { - public JsonElementArray() : base() {} - public List values = new List(); - - // convenience methods - public void AddString(string val) - { - values.Add(new JsonElementString(val)); - } - - public void AddInteger(int val) - { - values.Add(new JsonElementInteger(val)); - } - - public void AddBoolean(bool val) - { - values.Add(new JsonElementBoolean(val)); - } - - public JsonElementArray AddArray() - { - var v = new JsonElementArray(); - values.Add(v); - return v; - } - - public JsonElementDict AddDict() - { - var v = new JsonElementDict(); - values.Add(v); - return v; - } - } - - internal class JsonDocument - { - public JsonElementDict root; - public string indentString = " "; - - public JsonDocument() - { - root = new JsonElementDict(); - } - - void AppendIndent(StringBuilder sb, int indent) - { - for (int i = 0; i < indent; ++i) - sb.Append(indentString); - } - - void WriteString(StringBuilder sb, string str) - { - // TODO: escape - sb.Append('"'); - sb.Append(str); - sb.Append('"'); - } - - void WriteBoolean(StringBuilder sb, bool value) - { - sb.Append(value ? "true" : "false"); - } - - void WriteInteger(StringBuilder sb, int value) - { - sb.Append(value.ToString()); - } - - void WriteDictKeyValue(StringBuilder sb, string key, JsonElement value, int indent) - { - sb.Append("\n"); - AppendIndent(sb, indent); - WriteString(sb, key); - sb.Append(" : "); - if (value is JsonElementString) - WriteString(sb, value.AsString()); - else if (value is JsonElementInteger) - WriteInteger(sb, value.AsInteger()); - else if (value is JsonElementBoolean) - WriteBoolean(sb, value.AsBoolean()); - else if (value is JsonElementDict) - WriteDict(sb, value.AsDict(), indent); - else if (value is JsonElementArray) - WriteArray(sb, value.AsArray(), indent); - } - - void WriteDict(StringBuilder sb, JsonElementDict el, int indent) - { - sb.Append("{"); - bool hasElement = false; - foreach (var key in el.values.Keys) - { - if (hasElement) - sb.Append(","); // trailing commas not supported - WriteDictKeyValue(sb, key, el[key], indent+1); - hasElement = true; - } - sb.Append("\n"); - AppendIndent(sb, indent); - sb.Append("}"); - } - - void WriteArray(StringBuilder sb, JsonElementArray el, int indent) - { - sb.Append("["); - bool hasElement = false; - foreach (var value in el.values) - { - if (hasElement) - sb.Append(","); // trailing commas not supported - sb.Append("\n"); - AppendIndent(sb, indent+1); - - if (value is JsonElementString) - WriteString(sb, value.AsString()); - else if (value is JsonElementInteger) - WriteInteger(sb, value.AsInteger()); - else if (value is JsonElementBoolean) - WriteBoolean(sb, value.AsBoolean()); - else if (value is JsonElementDict) - WriteDict(sb, value.AsDict(), indent+1); - else if (value is JsonElementArray) - WriteArray(sb, value.AsArray(), indent+1); - hasElement = true; - } - sb.Append("\n"); - AppendIndent(sb, indent); - sb.Append("]"); - } - - public void WriteToFile(string path) - { - File.WriteAllText(path, WriteToString()); - } - - public void WriteToStream(TextWriter tw) - { - tw.Write(WriteToString()); - } - - public string WriteToString() - { - var sb = new StringBuilder(); - WriteDict(sb, root, 0); - return sb.ToString(); - } - } - - -} // namespace UnityEditor.iOS.Xcode \ No newline at end of file diff --git a/Assets/Zapic/Editor/Xcode.Custom/JsonParser.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/JsonParser.cs.meta deleted file mode 100644 index e51459d..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/JsonParser.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 6b673be46cbf34086a15b2a3e2d1693d -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Elements.cs b/Assets/Zapic/Editor/Xcode.Custom/PBX/Elements.cs deleted file mode 100644 index 309c830..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Elements.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System.Collections.Generic; -using System.Collections; -using System; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode.PBX -#else -namespace UnityEditor.iOS.Xcode.Custom.PBX -#endif -{ - - class PBXElement - { - protected PBXElement() {} - - // convenience methods - public string AsString() { return ((PBXElementString)this).value; } - public PBXElementArray AsArray() { return (PBXElementArray)this; } - public PBXElementDict AsDict() { return (PBXElementDict)this; } - - public PBXElement this[string key] - { - get { return AsDict()[key]; } - set { AsDict()[key] = value; } - } - } - - class PBXElementString : PBXElement - { - public PBXElementString(string v) { value = v; } - - public string value; - } - - class PBXElementDict : PBXElement - { - public PBXElementDict() : base() {} - - private Dictionary m_PrivateValue = new Dictionary(); - public IDictionary values { get { return m_PrivateValue; }} - - new public PBXElement this[string key] - { - get { - if (values.ContainsKey(key)) - return values[key]; - return null; - } - set { this.values[key] = value; } - } - - public bool Contains(string key) - { - return values.ContainsKey(key); - } - - public void Remove(string key) - { - values.Remove(key); - } - - public void SetString(string key, string val) - { - values[key] = new PBXElementString(val); - } - - public PBXElementArray CreateArray(string key) - { - var v = new PBXElementArray(); - values[key] = v; - return v; - } - - public PBXElementDict CreateDict(string key) - { - var v = new PBXElementDict(); - values[key] = v; - return v; - } - } - - class PBXElementArray : PBXElement - { - public PBXElementArray() : base() {} - public List values = new List(); - - // convenience methods - public void AddString(string val) - { - values.Add(new PBXElementString(val)); - } - - public PBXElementArray AddArray() - { - var v = new PBXElementArray(); - values.Add(v); - return v; - } - - public PBXElementDict AddDict() - { - var v = new PBXElementDict(); - values.Add(v); - return v; - } - } - -} // namespace UnityEditor.iOS.Xcode - diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Lexer.cs b/Assets/Zapic/Editor/Xcode.Custom/PBX/Lexer.cs deleted file mode 100644 index a2a93be..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Lexer.cs +++ /dev/null @@ -1,246 +0,0 @@ -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.IO; -using System.Linq; -using System; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode.PBX -#else -namespace UnityEditor.iOS.Xcode.Custom.PBX -#endif -{ - enum TokenType - { - EOF, - Invalid, - String, - QuotedString, - Comment, - - Semicolon, // ; - Comma, // , - Eq, // = - LParen, // ( - RParen, // ) - LBrace, // { - RBrace, // } - } - - class Token - { - public TokenType type; - - // the line of the input stream the token starts in (0-based) - public int line; - - // start and past-the-end positions of the token in the input stream - public int begin, end; - } - - class TokenList : List - { - } - - class Lexer - { - string text; - int pos; - int length; - int line; - - public static TokenList Tokenize(string text) - { - var lexer = new Lexer(); - lexer.SetText(text); - return lexer.ScanAll(); - } - - public void SetText(string text) - { - this.text = text + " "; // to prevent out-of-bounds access during look ahead - pos = 0; - length = text.Length; - line = 0; - } - - public TokenList ScanAll() - { - var tokens = new TokenList(); - - while (true) - { - var tok = new Token(); - ScanOne(tok); - tokens.Add(tok); - if (tok.type == TokenType.EOF) - break; - } - return tokens; - } - - void UpdateNewlineStats(char ch) - { - if (ch == '\n') - line++; - } - - // tokens list is modified in the case when we add BrokenLine token and need to remove already - // added tokens for the current line - void ScanOne(Token tok) - { - while (true) - { - while (pos < length && Char.IsWhiteSpace(text[pos])) - { - UpdateNewlineStats(text[pos]); - pos++; - } - - if (pos >= length) - { - tok.type = TokenType.EOF; - break; - } - - char ch = text[pos]; - char ch2 = text[pos+1]; - - if (ch == '\"') - ScanQuotedString(tok); - else if (ch == '/' && ch2 == '*') - ScanMultilineComment(tok); - else if (ch == '/' && ch2 == '/') - ScanComment(tok); - else if (IsOperator(ch)) - ScanOperator(tok); - else - ScanString(tok); // be more robust and accept whatever is left - return; - } - } - - void ScanString(Token tok) - { - tok.type = TokenType.String; - tok.begin = pos; - while (pos < length) - { - char ch = text[pos]; - char ch2 = text[pos+1]; - - if (Char.IsWhiteSpace(ch)) - break; - else if (ch == '\"') - break; - else if (ch == '/' && ch2 == '*') - break; - else if (ch == '/' && ch2 == '/') - break; - else if (IsOperator(ch)) - break; - pos++; - } - tok.end = pos; - tok.line = line; - } - - void ScanQuotedString(Token tok) - { - tok.type = TokenType.QuotedString; - tok.begin = pos; - pos++; - - while (pos < length) - { - // ignore escaped quotes - if (text[pos] == '\\' && text[pos+1] == '\"') - { - pos += 2; - continue; - } - - // note that we close unclosed quotes - if (text[pos] == '\"') - break; - - UpdateNewlineStats(text[pos]); - pos++; - } - pos++; - tok.end = pos; - tok.line = line; - } - - void ScanMultilineComment(Token tok) - { - tok.type = TokenType.Comment; - tok.begin = pos; - pos += 2; - - while (pos < length) - { - if (text[pos] == '*' && text[pos+1] == '/') - break; - - // we support multiline comments - UpdateNewlineStats(text[pos]); - pos++; - } - pos += 2; - tok.end = pos; - tok.line = line; - } - - void ScanComment(Token tok) - { - tok.type = TokenType.Comment; - tok.begin = pos; - pos += 2; - - while (pos < length) - { - if (text[pos] == '\n') - break; - pos++; - } - UpdateNewlineStats(text[pos]); - pos++; - tok.end = pos; - tok.line = line; - } - - bool IsOperator(char ch) - { - if (ch == ';' || ch == ',' || ch == '=' || ch == '(' || ch == ')' || ch == '{' || ch == '}') - return true; - return false; - } - - void ScanOperator(Token tok) - { - switch (text[pos]) - { - case ';': ScanOperatorSpecific(tok, TokenType.Semicolon); return; - case ',': ScanOperatorSpecific(tok, TokenType.Comma); return; - case '=': ScanOperatorSpecific(tok, TokenType.Eq); return; - case '(': ScanOperatorSpecific(tok, TokenType.LParen); return; - case ')': ScanOperatorSpecific(tok, TokenType.RParen); return; - case '{': ScanOperatorSpecific(tok, TokenType.LBrace); return; - case '}': ScanOperatorSpecific(tok, TokenType.RBrace); return; - default: return; - } - } - - void ScanOperatorSpecific(Token tok, TokenType type) - { - tok.type = type; - tok.begin = pos; - pos++; - tok.end = pos; - tok.line = line; - } - } - - -} // namespace UnityEditor.iOS.Xcode \ No newline at end of file diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Lexer.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBX/Lexer.cs.meta deleted file mode 100644 index c7f0868..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Lexer.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 8644bb49d46884ac9bcb5fa52e5e6984 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Objects.cs b/Assets/Zapic/Editor/Xcode.Custom/PBX/Objects.cs deleted file mode 100644 index 01d5ebc..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Objects.cs +++ /dev/null @@ -1,1022 +0,0 @@ -using System.Collections.Generic; -using System.Collections; -using System.Text.RegularExpressions; -using System.IO; -using System.Linq; -using System; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode.PBX -#else -namespace UnityEditor.iOS.Xcode.Custom.PBX -#endif -{ - internal class PBXObjectData - { - public string guid; - protected PBXElementDict m_Properties = new PBXElementDict(); - - internal void SetPropertiesWhenSerializing(PBXElementDict props) - { - m_Properties = props; - } - - internal PBXElementDict GetPropertiesWhenSerializing() - { - return m_Properties; - } - - /* Returns the internal properties dictionary which the user may manipulate directly. - If any of the properties are modified, UpdateVars() must be called before any other - operation affecting the given Xcode document is executed. - */ - internal PBXElementDict GetPropertiesRaw() - { - UpdateProps(); - return m_Properties; - } - - // returns null if it does not exist - protected string GetPropertyString(string name) - { - var prop = m_Properties[name]; - if (prop == null) - return null; - - return prop.AsString(); - } - - protected void SetPropertyString(string name, string value) - { - if (value == null) - m_Properties.Remove(name); - else - m_Properties.SetString(name, value); - } - - protected List GetPropertyList(string name) - { - var prop = m_Properties[name]; - if (prop == null) - return null; - - var list = new List(); - foreach (var el in prop.AsArray().values) - list.Add(el.AsString()); - return list; - } - - protected void SetPropertyList(string name, List value) - { - if (value == null) - m_Properties.Remove(name); - else - { - var array = m_Properties.CreateArray(name); - foreach (string val in value) - array.AddString(val); - } - } - - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(); - internal virtual PropertyCommentChecker checker { get { return checkerData; } } - internal virtual bool shouldCompact { get { return false; } } - - public virtual void UpdateProps() {} // Updates the props from cached variables - public virtual void UpdateVars() {} // Updates the cached variables from underlying props - } - - internal class PBXBuildFileData : PBXObjectData - { - public string fileRef; - public string compileFlags; - public bool weak; - public bool codeSignOnCopy; - public bool removeHeadersOnCopy; - public List assetTags; - - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "fileRef/*" - }); - internal override PropertyCommentChecker checker { get { return checkerData; } } - internal override bool shouldCompact { get { return true; } } - - public static PBXBuildFileData CreateFromFile(string fileRefGUID, bool weak, - string compileFlags) - { - PBXBuildFileData buildFile = new PBXBuildFileData(); - buildFile.guid = PBXGUID.Generate(); - buildFile.SetPropertyString("isa", "PBXBuildFile"); - buildFile.fileRef = fileRefGUID; - buildFile.compileFlags = compileFlags; - buildFile.weak = weak; - buildFile.codeSignOnCopy = false; - buildFile.removeHeadersOnCopy = false; - buildFile.assetTags = new List(); - return buildFile; - } - - PBXElementDict UpdatePropsAttribute(PBXElementDict settings, bool value, string attributeName) - { - PBXElementArray attrs = null; - if (value) - { - if (settings == null) - settings = m_Properties.CreateDict("settings"); - } - if (settings != null && settings.Contains("ATTRIBUTES")) - attrs = settings["ATTRIBUTES"].AsArray(); - - if (value) - { - if (attrs == null) - attrs = settings.CreateArray("ATTRIBUTES"); - - bool exists = attrs.values.Any(attr => - { - return attr is PBXElementString && attr.AsString() == attributeName; - }); - - if (!exists) - attrs.AddString(attributeName); - } - else - { - if (attrs != null) - { - attrs.values.RemoveAll(el => (el is PBXElementString && el.AsString() == attributeName)); - if (attrs.values.Count == 0) - settings.Remove("ATTRIBUTES"); - } - } - return settings; - } - - public override void UpdateProps() - { - SetPropertyString("fileRef", fileRef); - - PBXElementDict settings = null; - if (m_Properties.Contains("settings")) - settings = m_Properties["settings"].AsDict(); - - if (compileFlags != null && compileFlags != "") - { - if (settings == null) - settings = m_Properties.CreateDict("settings"); - settings.SetString("COMPILER_FLAGS", compileFlags); - } - else - { - if (settings != null) - settings.Remove("COMPILER_FLAGS"); - } - - settings = UpdatePropsAttribute(settings, weak, "Weak"); - settings = UpdatePropsAttribute(settings, codeSignOnCopy, "CodeSignOnCopy"); - settings = UpdatePropsAttribute(settings, removeHeadersOnCopy, "RemoveHeadersOnCopy"); - - if (assetTags.Count > 0) - { - if (settings == null) - settings = m_Properties.CreateDict("settings"); - var tagsArray = settings.CreateArray("ASSET_TAGS"); - foreach (string tag in assetTags) - tagsArray.AddString(tag); - } - else - { - if (settings != null) - settings.Remove("ASSET_TAGS"); - } - - if (settings != null && settings.values.Count == 0) - m_Properties.Remove("settings"); - } - - public override void UpdateVars() - { - fileRef = GetPropertyString("fileRef"); - compileFlags = null; - weak = false; - assetTags = new List(); - if (m_Properties.Contains("settings")) - { - var dict = m_Properties["settings"].AsDict(); - if (dict.Contains("COMPILER_FLAGS")) - compileFlags = dict["COMPILER_FLAGS"].AsString(); - - if (dict.Contains("ATTRIBUTES")) - { - var attrs = dict["ATTRIBUTES"].AsArray(); - foreach (var value in attrs.values) - { - if (value is PBXElementString && value.AsString() == "Weak") - weak = true; - if (value is PBXElementString && value.AsString() == "CodeSignOnCopy") - codeSignOnCopy = true; - if (value is PBXElementString && value.AsString() == "RemoveHeadersOnCopy") - removeHeadersOnCopy = true; - } - } - if (dict.Contains("ASSET_TAGS")) - { - var tags = dict["ASSET_TAGS"].AsArray(); - foreach (var value in tags.values) - assetTags.Add(value.AsString()); - } - } - } - } - - internal class PBXFileReferenceData : PBXObjectData - { - string m_Path = null; - string m_ExplicitFileType = null; - string m_LastKnownFileType = null; - - public string path - { - get { return m_Path; } - set { m_ExplicitFileType = null; m_LastKnownFileType = null; m_Path = value; } - } - - public string name; - public PBXSourceTree tree; - public bool isFolderReference - { - get { return m_LastKnownFileType != null && m_LastKnownFileType == "folder"; } - } - - internal override bool shouldCompact { get { return true; } } - - public static PBXFileReferenceData CreateFromFile(string path, string projectFileName, - PBXSourceTree tree) - { - string guid = PBXGUID.Generate(); - - PBXFileReferenceData fileRef = new PBXFileReferenceData(); - fileRef.SetPropertyString("isa", "PBXFileReference"); - fileRef.guid = guid; - fileRef.path = path; - fileRef.name = projectFileName; - fileRef.tree = tree; - return fileRef; - } - - public static PBXFileReferenceData CreateFromFolderReference(string path, string projectFileName, - PBXSourceTree tree) - { - var fileRef = CreateFromFile(path, projectFileName, tree); - fileRef.m_LastKnownFileType = "folder"; - return fileRef; - } - - public override void UpdateProps() - { - string ext = null; - if (m_ExplicitFileType != null) - SetPropertyString("explicitFileType", m_ExplicitFileType); - else if (m_LastKnownFileType != null) - SetPropertyString("lastKnownFileType", m_LastKnownFileType); - else - { - if (name != null) - ext = Path.GetExtension(name); - else if (m_Path != null) - ext = Path.GetExtension(m_Path); - if (ext != null) - { - if (FileTypeUtils.IsFileTypeExplicit(ext)) - SetPropertyString("explicitFileType", FileTypeUtils.GetTypeName(ext)); - else - SetPropertyString("lastKnownFileType", FileTypeUtils.GetTypeName(ext)); - } - } - if (m_Path == name) - SetPropertyString("name", null); - else - SetPropertyString("name", name); - if (m_Path == null) - SetPropertyString("path", ""); - else - SetPropertyString("path", m_Path); - SetPropertyString("sourceTree", FileTypeUtils.SourceTreeDesc(tree)); - } - - public override void UpdateVars() - { - name = GetPropertyString("name"); - m_Path = GetPropertyString("path"); - if (name == null) - name = m_Path; - if (m_Path == null) - m_Path = ""; - tree = FileTypeUtils.ParseSourceTree(GetPropertyString("sourceTree")); - m_ExplicitFileType = GetPropertyString("explicitFileType"); - m_LastKnownFileType = GetPropertyString("lastKnownFileType"); - } - } - - class GUIDList : IEnumerable - { - private List m_List = new List(); - - public GUIDList() {} - public GUIDList(List data) - { - m_List = data; - } - - public static implicit operator List(GUIDList list) { return list.m_List; } - public static implicit operator GUIDList(List data) { return new GUIDList(data); } - - public void AddGUID(string guid) { m_List.Add(guid); } - public void RemoveGUID(string guid) { m_List.RemoveAll(x => x == guid); } - public bool Contains(string guid) { return m_List.Contains(guid); } - public int Count { get { return m_List.Count; } } - public void Clear() { m_List.Clear(); } - IEnumerator IEnumerable.GetEnumerator() { return m_List.GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() { return m_List.GetEnumerator(); } - } - - internal class XCConfigurationListData : PBXObjectData - { - public GUIDList buildConfigs; - - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "buildConfigurations/*" - }); - internal override PropertyCommentChecker checker { get { return checkerData; } } - - public static XCConfigurationListData Create() - { - var res = new XCConfigurationListData(); - res.guid = PBXGUID.Generate(); - - res.SetPropertyString("isa", "XCConfigurationList"); - res.buildConfigs = new GUIDList(); - res.SetPropertyString("defaultConfigurationIsVisible", "0"); - - return res; - } - - public override void UpdateProps() - { - SetPropertyList("buildConfigurations", buildConfigs); - } - public override void UpdateVars() - { - buildConfigs = GetPropertyList("buildConfigurations"); - } - } - - internal class PBXGroupData : PBXObjectData - { - public GUIDList children; - public PBXSourceTree tree; - public string name, path; - - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "children/*" - }); - internal override PropertyCommentChecker checker { get { return checkerData; } } - - // name must not contain '/' - public static PBXGroupData Create(string name, string path, PBXSourceTree tree) - { - if (name.Contains("/")) - throw new Exception("Group name must not contain '/'"); - - PBXGroupData gr = new PBXGroupData(); - gr.guid = PBXGUID.Generate(); - gr.SetPropertyString("isa", "PBXGroup"); - gr.name = name; - gr.path = path; - gr.tree = PBXSourceTree.Group; - gr.children = new GUIDList(); - - return gr; - } - - public static PBXGroupData CreateRelative(string name) - { - return Create(name, name, PBXSourceTree.Group); - } - - public override void UpdateProps() - { - // The name property is set only if it is different from the path property - SetPropertyList("children", children); - if (name == path) - SetPropertyString("name", null); - else - SetPropertyString("name", name); - if (path == "") - SetPropertyString("path", null); - else - SetPropertyString("path", path); - SetPropertyString("sourceTree", FileTypeUtils.SourceTreeDesc(tree)); - } - public override void UpdateVars() - { - children = GetPropertyList("children"); - path = GetPropertyString("path"); - name = GetPropertyString("name"); - if (name == null) - name = path; - if (path == null) - path = ""; - tree = FileTypeUtils.ParseSourceTree(GetPropertyString("sourceTree")); - } - } - - internal class PBXVariantGroupData : PBXGroupData - { - } - - internal class PBXNativeTargetData : PBXObjectData - { - public GUIDList phases; - - public string buildConfigList; // guid - public string name; - public GUIDList dependencies; - public string productReference; // guid - - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "buildPhases/*", - "buildRules/*", - "dependencies/*", - "productReference/*", - "buildConfigurationList/*" - }); - - internal override PropertyCommentChecker checker { get { return checkerData; } } - - public static PBXNativeTargetData Create(string name, string productRef, - string productType, string buildConfigList) - { - var res = new PBXNativeTargetData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "PBXNativeTarget"); - res.buildConfigList = buildConfigList; - res.phases = new GUIDList(); - res.SetPropertyList("buildRules", new List()); - res.dependencies = new GUIDList(); - res.name = name; - res.productReference = productRef; - res.SetPropertyString("productName", name); - res.SetPropertyString("productReference", productRef); - res.SetPropertyString("productType", productType); - return res; - } - - public override void UpdateProps() - { - SetPropertyString("buildConfigurationList", buildConfigList); - SetPropertyString("name", name); - SetPropertyString("productReference", productReference); - SetPropertyList("buildPhases", phases); - SetPropertyList("dependencies", dependencies); - } - public override void UpdateVars() - { - buildConfigList = GetPropertyString("buildConfigurationList"); - name = GetPropertyString("name"); - productReference = GetPropertyString("productReference"); - phases = GetPropertyList("buildPhases"); - dependencies = GetPropertyList("dependencies"); - } - } - - - internal class FileGUIDListBase : PBXObjectData - { - public GUIDList files; - - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "files/*", - }); - - internal override PropertyCommentChecker checker { get { return checkerData; } } - - public override void UpdateProps() - { - SetPropertyList("files", files); - } - public override void UpdateVars() - { - files = GetPropertyList("files"); - } - } - - internal class PBXSourcesBuildPhaseData : FileGUIDListBase - { - public static PBXSourcesBuildPhaseData Create() - { - var res = new PBXSourcesBuildPhaseData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "PBXSourcesBuildPhase"); - res.SetPropertyString("buildActionMask", "2147483647"); - res.files = new List(); - res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0"); - return res; - } - } - - internal class PBXFrameworksBuildPhaseData : FileGUIDListBase - { - public static PBXFrameworksBuildPhaseData Create() - { - var res = new PBXFrameworksBuildPhaseData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "PBXFrameworksBuildPhase"); - res.SetPropertyString("buildActionMask", "2147483647"); - res.files = new List(); - res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0"); - return res; - } - } - - internal class PBXResourcesBuildPhaseData : FileGUIDListBase - { - public static PBXResourcesBuildPhaseData Create() - { - var res = new PBXResourcesBuildPhaseData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "PBXResourcesBuildPhase"); - res.SetPropertyString("buildActionMask", "2147483647"); - res.files = new List(); - res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0"); - return res; - } - } - - internal class PBXCopyFilesBuildPhaseData : FileGUIDListBase - { - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "files/*", - }); - - internal override PropertyCommentChecker checker { get { return checkerData; } } - - public string name; - public string dstPath; - public string dstSubfolderSpec; - - // name may be null - public static PBXCopyFilesBuildPhaseData Create(string name, string dstPath, string subfolderSpec) - { - var res = new PBXCopyFilesBuildPhaseData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "PBXCopyFilesBuildPhase"); - res.SetPropertyString("buildActionMask", "2147483647"); - res.dstPath = dstPath; - res.dstSubfolderSpec = subfolderSpec; - res.files = new List(); - res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0"); - res.name = name; - return res; - } - - public override void UpdateProps() - { - SetPropertyList("files", files); - SetPropertyString("name", name); - SetPropertyString("dstPath", dstPath); - SetPropertyString("dstSubfolderSpec", dstSubfolderSpec); - } - - public override void UpdateVars() - { - files = GetPropertyList("files"); - name = GetPropertyString("name"); - dstPath = GetPropertyString("dstPath"); - dstSubfolderSpec = GetPropertyString("dstSubfolderSpec"); - } - } - - internal class PBXShellScriptBuildPhaseData : FileGUIDListBase - { - public string name; - public string shellPath; - public string shellScript; - - public static PBXShellScriptBuildPhaseData Create(string name, string shellPath, string shellScript) - { - var res = new PBXShellScriptBuildPhaseData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "PBXShellScriptBuildPhase"); - res.SetPropertyString("buildActionMask", "2147483647"); - res.files = new List(); - res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0"); - res.name = name; - res.shellPath = shellPath; - res.shellScript = shellScript; - return res; - } - - public override void UpdateProps() - { - base.UpdateProps(); - SetPropertyString("name", name); - SetPropertyString("shellPath", shellPath); - SetPropertyString("shellScript", shellScript); - } - public override void UpdateVars() - { - base.UpdateVars(); - name = GetPropertyString("name"); - shellPath = GetPropertyString("shellPath"); - shellScript = GetPropertyString("shellScript"); - } - } - - internal class BuildConfigEntryData - { - public string name; - public List val = new List(); - - public static string ExtractValue(string src) - { - return PBXStream.UnquoteString(src.Trim().TrimEnd(',')); - } - - public void AddValue(string value) - { - if (!val.Contains(value)) - val.Add(value); - } - - public void RemoveValue(string value) - { - val.RemoveAll(v => v == value); - } - - public void RemoveValueList(IEnumerable values) - { - List valueList = new List(values); - if (valueList.Count == 0) - return; - for (int i = 0; i < val.Count - valueList.Count; i++) - { - bool match = true; - for (int j = 0; j < valueList.Count; j++) - { - if (val[i + j] != valueList[j]) - { - match = false; - break; - } - } - if (match) - { - val.RemoveRange(i, valueList.Count); - return; - } - } - } - - public static BuildConfigEntryData FromNameValue(string name, string value) - { - BuildConfigEntryData ret = new BuildConfigEntryData(); - ret.name = name; - ret.AddValue(value); - return ret; - } - } - - internal class XCBuildConfigurationData : PBXObjectData - { - protected SortedDictionary entries = new SortedDictionary(); - public string name { get { return GetPropertyString("name"); } } - public string baseConfigurationReference; // may be null - - // Note that QuoteStringIfNeeded does its own escaping. Double-escaping with quotes is - // required to please Xcode that does not handle paths with spaces if they are not - // enclosed in quotes. - static string EscapeWithQuotesIfNeeded(string name, string value) - { - if (name != "LIBRARY_SEARCH_PATHS" && name != "FRAMEWORK_SEARCH_PATHS") - return value; - if (!value.Contains(" ")) - return value; - if (value.First() == '\"' && value.Last() == '\"') - return value; - return "\"" + value + "\""; - } - - public void SetProperty(string name, string value) - { - entries[name] = BuildConfigEntryData.FromNameValue(name, EscapeWithQuotesIfNeeded(name, value)); - } - - public void AddProperty(string name, string value) - { - if (entries.ContainsKey(name)) - entries[name].AddValue(EscapeWithQuotesIfNeeded(name, value)); - else - SetProperty(name, value); - } - - public void RemoveProperty(string name) - { - if (entries.ContainsKey(name)) - entries.Remove(name); - } - - public void RemovePropertyValue(string name, string value) - { - if (entries.ContainsKey(name)) - entries[name].RemoveValue(EscapeWithQuotesIfNeeded(name, value)); - } - - public void RemovePropertyValueList(string name, IEnumerable valueList) - { - if (entries.ContainsKey(name)) - entries[name].RemoveValueList(valueList); - } - - // name should be either release or debug - public static XCBuildConfigurationData Create(string name) - { - var res = new XCBuildConfigurationData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "XCBuildConfiguration"); - res.SetPropertyString("name", name); - return res; - } - - public override void UpdateProps() - { - SetPropertyString("baseConfigurationReference", baseConfigurationReference); - - var dict = m_Properties.CreateDict("buildSettings"); - foreach (var kv in entries) - { - if (kv.Value.val.Count == 0) - continue; - else if (kv.Value.val.Count == 1) - dict.SetString(kv.Key, kv.Value.val[0]); - else // kv.Value.val.Count > 1 - { - var array = dict.CreateArray(kv.Key); - foreach (var value in kv.Value.val) - array.AddString(value); - } - } - } - public override void UpdateVars() - { - baseConfigurationReference = GetPropertyString("baseConfigurationReference"); - - entries = new SortedDictionary(); - if (m_Properties.Contains("buildSettings")) - { - var dict = m_Properties["buildSettings"].AsDict(); - foreach (var key in dict.values.Keys) - { - var value = dict[key]; - if (value is PBXElementString) - { - if (entries.ContainsKey(key)) - entries[key].val.Add(value.AsString()); - else - entries.Add(key, BuildConfigEntryData.FromNameValue(key, value.AsString())); - } - else if (value is PBXElementArray) - { - foreach (var pvalue in value.AsArray().values) - { - if (pvalue is PBXElementString) - { - if (entries.ContainsKey(key)) - entries[key].val.Add(pvalue.AsString()); - else - entries.Add(key, BuildConfigEntryData.FromNameValue(key, pvalue.AsString())); - } - } - } - } - } - } - } - - internal class PBXContainerItemProxyData : PBXObjectData - { - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "containerPortal/*" - }); - - internal override PropertyCommentChecker checker { get { return checkerData; } } - - public static PBXContainerItemProxyData Create(string containerRef, string proxyType, - string remoteGlobalGUID, string remoteInfo) - { - var res = new PBXContainerItemProxyData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "PBXContainerItemProxy"); - res.SetPropertyString("containerPortal", containerRef); // guid - res.SetPropertyString("proxyType", proxyType); - res.SetPropertyString("remoteGlobalIDString", remoteGlobalGUID); // guid - res.SetPropertyString("remoteInfo", remoteInfo); - return res; - } - } - - internal class PBXReferenceProxyData : PBXObjectData - { - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "remoteRef/*" - }); - - internal override PropertyCommentChecker checker { get { return checkerData; } } - - public string path { get { return GetPropertyString("path"); } } - - public static PBXReferenceProxyData Create(string path, string fileType, - string remoteRef, string sourceTree) - { - var res = new PBXReferenceProxyData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "PBXReferenceProxy"); - res.SetPropertyString("path", path); - res.SetPropertyString("fileType", fileType); - res.SetPropertyString("remoteRef", remoteRef); - res.SetPropertyString("sourceTree", sourceTree); - return res; - } - } - - internal class PBXTargetDependencyData : PBXObjectData - { - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "target/*", - "targetProxy/*" - }); - - internal override PropertyCommentChecker checker { get { return checkerData; } } - - public static PBXTargetDependencyData Create(string target, string targetProxy) - { - var res = new PBXTargetDependencyData(); - res.guid = PBXGUID.Generate(); - res.SetPropertyString("isa", "PBXTargetDependency"); - res.SetPropertyString("target", target); - res.SetPropertyString("targetProxy", targetProxy); - return res; - } - } - - internal class ProjectReference - { - public string group; // guid - public string projectRef; // guid - - public static ProjectReference Create(string group, string projectRef) - { - var res = new ProjectReference(); - res.group = group; - res.projectRef = projectRef; - return res; - } - } - - internal class PBXProjectObjectData : PBXObjectData - { - private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{ - "buildConfigurationList/*", - "mainGroup/*", - "projectReferences/*/ProductGroup/*", - "projectReferences/*/ProjectRef/*", - "targets/*" - }); - - internal override PropertyCommentChecker checker { get { return checkerData; } } - - public List projectReferences = new List(); - public string mainGroup { get { return GetPropertyString("mainGroup"); } } - public List targets = new List(); - public List knownAssetTags = new List(); - public string buildConfigList; - // the name of the entitlements file required for some capabilities. - public string entitlementsFile; - public List capabilities = new List(); - public Dictionary teamIDs = new Dictionary(); - - - public void AddReference(string productGroup, string projectRef) - { - projectReferences.Add(ProjectReference.Create(productGroup, projectRef)); - } - - public override void UpdateProps() - { - m_Properties.values.Remove("projectReferences"); - if (projectReferences.Count > 0) - { - var array = m_Properties.CreateArray("projectReferences"); - foreach (var value in projectReferences) - { - var dict = array.AddDict(); - dict.SetString("ProductGroup", value.group); - dict.SetString("ProjectRef", value.projectRef); - } - }; - SetPropertyList("targets", targets); - SetPropertyString("buildConfigurationList", buildConfigList); - if (knownAssetTags.Count > 0) - { - PBXElementDict attrs; - if (m_Properties.Contains("attributes")) - attrs = m_Properties["attributes"].AsDict(); - else - attrs = m_Properties.CreateDict("attributes"); - var tags = attrs.CreateArray("knownAssetTags"); - foreach (var tag in knownAssetTags) - tags.AddString(tag); - } - - // Enable the capabilities. - foreach (var cap in capabilities) - { - var attrs = m_Properties.Contains("attributes") ? m_Properties["attributes"].AsDict() : m_Properties.CreateDict("attributes"); - var targAttr = attrs.Contains("TargetAttributes") ? attrs["TargetAttributes"].AsDict() : attrs.CreateDict("TargetAttributes"); - var target = targAttr.Contains(cap.targetGuid) ? targAttr[cap.targetGuid].AsDict() : targAttr.CreateDict(cap.targetGuid); - var sysCap = target.Contains("SystemCapabilities") ? target["SystemCapabilities"].AsDict() : target.CreateDict("SystemCapabilities"); - - var capabilityId = cap.capability.id; - var currentCapability = sysCap.Contains(capabilityId) ? sysCap[capabilityId].AsDict() : sysCap.CreateDict(capabilityId); - currentCapability.SetString("enabled", "1"); - } - - // Set the team id - foreach (KeyValuePair teamID in teamIDs) - { - var attrs = m_Properties.Contains("attributes") ? m_Properties["attributes"].AsDict() : m_Properties.CreateDict("attributes"); - var targAttr = attrs.Contains("TargetAttributes") ? attrs["TargetAttributes"].AsDict() : attrs.CreateDict("TargetAttributes"); - var target = targAttr.Contains(teamID.Key) ? targAttr[teamID.Key].AsDict() : targAttr.CreateDict(teamID.Key); - target.SetString("DevelopmentTeam", teamID.Value); - } - } - - public override void UpdateVars() - { - projectReferences = new List(); - if (m_Properties.Contains("projectReferences")) - { - var el = m_Properties["projectReferences"].AsArray(); - foreach (var value in el.values) - { - PBXElementDict dict = value.AsDict(); - if (dict.Contains("ProductGroup") && dict.Contains("ProjectRef")) - { - string group = dict["ProductGroup"].AsString(); - string projectRef = dict["ProjectRef"].AsString(); - projectReferences.Add(ProjectReference.Create(group, projectRef)); - } - } - } - targets = GetPropertyList("targets"); - buildConfigList = GetPropertyString("buildConfigurationList"); - - // update knownAssetTags - knownAssetTags = new List(); - if (m_Properties.Contains("attributes")) - { - var el = m_Properties["attributes"].AsDict(); - if (el.Contains("knownAssetTags")) - { - var tags = el["knownAssetTags"].AsArray(); - foreach (var tag in tags.values) - knownAssetTags.Add(tag.AsString()); - } - - capabilities = new List(); - teamIDs = new Dictionary(); - - if (el.Contains("TargetAttributes")) - { - var targetAttr = el["TargetAttributes"].AsDict(); - foreach (var attr in targetAttr.values) - { - if (attr.Key == "DevelopmentTeam") - { - teamIDs.Add(attr.Key, attr.Value.AsString()); - } - - if (attr.Key == "SystemCapabilities") - { - var caps = el["SystemCapabilities"].AsDict(); - foreach (var cap in caps.values) - capabilities.Add(new PBXCapabilityType.TargetCapabilityPair(attr.Key, PBXCapabilityType.StringToPBXCapabilityType(cap.Value.AsString()))); - } - } - } - } - } - } - -} // namespace UnityEditor.iOS.Xcode - diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Objects.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBX/Objects.cs.meta deleted file mode 100644 index c77499c..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Objects.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 6cdfed4c065e3479ab92f14eccab0824 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Parser.cs b/Assets/Zapic/Editor/Xcode.Custom/PBX/Parser.cs deleted file mode 100644 index f8cf9c6..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Parser.cs +++ /dev/null @@ -1,173 +0,0 @@ -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.IO; -using System.Linq; -using System; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode.PBX -#else -namespace UnityEditor.iOS.Xcode.Custom.PBX -#endif -{ - class ValueAST {} - - // IdentifierAST := \ - class IdentifierAST : ValueAST - { - public int value = 0; // token id - } - - // TreeAST := '{' KeyValuePairList '}' - // KeyValuePairList := KeyValuePair ',' KeyValuePairList - // KeyValuePair ',' - // (empty) - class TreeAST : ValueAST - { - public List values = new List(); - } - - // ListAST := '(' ValueList ')' - // ValueList := ValueAST ',' ValueList - // ValueAST ',' - // (empty) - class ArrayAST : ValueAST - { - public List values = new List(); - } - - // KeyValueAST := IdentifierAST '=' ValueAST ';' - // ValueAST := IdentifierAST | TreeAST | ListAST - class KeyValueAST - { - public IdentifierAST key = null; - public ValueAST value = null; // either IdentifierAST, TreeAST or ListAST - } - - class Parser - { - TokenList tokens; - int currPos; - - public Parser(TokenList tokens) - { - this.tokens = tokens; - currPos = SkipComments(0); - } - - int SkipComments(int pos) - { - while (pos < tokens.Count && tokens[pos].type == TokenType.Comment) - { - pos++; - } - return pos; - } - - // returns new position - int IncInternal(int pos) - { - if (pos >= tokens.Count) - return pos; - pos++; - - return SkipComments(pos); - } - - // Increments current pointer if not past the end, returns previous pos - int Inc() - { - int prev = currPos; - currPos = IncInternal(currPos); - return prev; - } - - // Returns the token type of the current token - TokenType Tok() - { - if (currPos >= tokens.Count) - return TokenType.EOF; - return tokens[currPos].type; - } - - void SkipIf(TokenType type) - { - if (Tok() == type) - Inc(); - } - - string GetErrorMsg() - { - return "Invalid PBX project (parsing line " + tokens[currPos].line + ")"; - } - - public IdentifierAST ParseIdentifier() - { - if (Tok() != TokenType.String && Tok() != TokenType.QuotedString) - throw new Exception(GetErrorMsg()); - var ast = new IdentifierAST(); - ast.value = Inc(); - return ast; - } - - public TreeAST ParseTree() - { - if (Tok() != TokenType.LBrace) - throw new Exception(GetErrorMsg()); - Inc(); - - var ast = new TreeAST(); - while (Tok() != TokenType.RBrace && Tok() != TokenType.EOF) - { - ast.values.Add(ParseKeyValue()); - } - SkipIf(TokenType.RBrace); - return ast; - } - - public ArrayAST ParseList() - { - if (Tok() != TokenType.LParen) - throw new Exception(GetErrorMsg()); - Inc(); - - var ast = new ArrayAST(); - while (Tok() != TokenType.RParen && Tok() != TokenType.EOF) - { - ast.values.Add(ParseValue()); - SkipIf(TokenType.Comma); - } - SkipIf(TokenType.RParen); - return ast; - } - - // throws on error - public KeyValueAST ParseKeyValue() - { - var ast = new KeyValueAST(); - ast.key = ParseIdentifier(); - - if (Tok() != TokenType.Eq) - throw new Exception(GetErrorMsg()); - Inc(); // skip '=' - - ast.value = ParseValue(); - SkipIf(TokenType.Semicolon); - - return ast; - } - - // throws on error - public ValueAST ParseValue() - { - if (Tok() == TokenType.String || Tok() == TokenType.QuotedString) - return ParseIdentifier(); - else if (Tok() == TokenType.LBrace) - return ParseTree(); - else if (Tok() == TokenType.LParen) - return ParseList(); - throw new Exception(GetErrorMsg()); - } - } - -} // namespace UnityEditor.iOS.Xcode \ No newline at end of file diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Parser.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBX/Parser.cs.meta deleted file mode 100644 index a2f9be7..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Parser.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 28cb6e8c04bd94635bc991347670d320 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Sections.cs b/Assets/Zapic/Editor/Xcode.Custom/PBX/Sections.cs deleted file mode 100644 index e5cc48d..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Sections.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; -using System.IO; - -// Base classes for section handling - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode.PBX -#else -namespace UnityEditor.iOS.Xcode.Custom.PBX -#endif -{ - - // common base - internal abstract class SectionBase - { - public abstract void AddObject(string key, PBXElementDict value); - public abstract void WriteSection(StringBuilder sb, GUIDToCommentMap comments); - } - - // known section: contains objects that we care about - internal class KnownSectionBase : SectionBase where T : PBXObjectData, new() - { - private Dictionary m_Entries = new Dictionary(); - - private string m_Name; - - public KnownSectionBase(string sectionName) - { - m_Name = sectionName; - } - - public IEnumerable> GetEntries() - { - return m_Entries; - } - - public IEnumerable GetGuids() - { - return m_Entries.Keys; - } - - public IEnumerable GetObjects() - { - return m_Entries.Values; - } - - public override void AddObject(string key, PBXElementDict value) - { - T obj = new T(); - obj.guid = key; - obj.SetPropertiesWhenSerializing(value); - obj.UpdateVars(); - m_Entries[obj.guid] = obj; - } - - public override void WriteSection(StringBuilder sb, GUIDToCommentMap comments) - { - if (m_Entries.Count == 0) - return; // do not write empty sections - - sb.AppendFormat("\n\n/* Begin {0} section */", m_Name); - var keys = new List(m_Entries.Keys); - keys.Sort(StringComparer.Ordinal); - foreach (string key in keys) - { - T obj = m_Entries[key]; - obj.UpdateProps(); - sb.Append("\n\t\t"); - comments.WriteStringBuilder(sb, obj.guid); - sb.Append(" = "); - Serializer.WriteDict(sb, obj.GetPropertiesWhenSerializing(), 2, - obj.shouldCompact, obj.checker, comments); - sb.Append(";"); - } - sb.AppendFormat("\n/* End {0} section */", m_Name); - } - - // returns null if not found - public T this[string guid] - { - get { - if (m_Entries.ContainsKey(guid)) - return m_Entries[guid]; - return null; - } - } - - public bool HasEntry(string guid) - { - return m_Entries.ContainsKey(guid); - } - - public void AddEntry(T obj) - { - m_Entries[obj.guid] = obj; - } - - public void RemoveEntry(string guid) - { - if (m_Entries.ContainsKey(guid)) - m_Entries.Remove(guid); - } - } - - // we assume there is only one PBXProject entry - internal class PBXProjectSection : KnownSectionBase - { - public PBXProjectSection() : base("PBXProject") - { - } - - public PBXProjectObjectData project - { - get { - foreach (var kv in GetEntries()) - return kv.Value; - return null; - } - } - } - -} // UnityEditor.iOS.Xcode diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Sections.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBX/Sections.cs.meta deleted file mode 100644 index 66d0ac7..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Sections.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 857a39f3c2239453e94d9b8366ea981f -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Serializer.cs b/Assets/Zapic/Editor/Xcode.Custom/PBX/Serializer.cs deleted file mode 100644 index 813ab98..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Serializer.cs +++ /dev/null @@ -1,263 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; -using System.IO; -using System.Linq; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode.PBX -#else -namespace UnityEditor.iOS.Xcode.Custom.PBX -#endif -{ - class PropertyCommentChecker - { - private int m_Level; - private bool m_All; - private List> m_Props; - - /* The argument is an array of matcher strings each of which determine - whether a property with a certain path needs to be decorated with a - comment. - - A path is a number of path elements concatenated by '/'. The last path - element is either: - the key if we're referring to a dict key - the value if we're referring to a value in an array - the value if we're referring to a value in a dict - All other path elements are either: - the key if the container is dict - '*' if the container is array - - Path matcher has the same structure as a path, except that any of the - elements may be '*'. Matcher matches a path if both have the same number - of elements and for each pair matcher element is the same as path element - or is '*'. - - a/b/c matches a/b/c but not a/b nor a/b/c/d - a/* /c matches a/d/c but not a/b nor a/b/c/d - * /* /* matches any path from three elements - */ - protected PropertyCommentChecker(int level, List> props) - { - m_Level = level; - m_All = false; - m_Props = props; - } - - public PropertyCommentChecker() - { - m_Level = 0; - m_All = false; - m_Props = new List>(); - } - - public PropertyCommentChecker(IEnumerable props) - { - m_Level = 0; - m_All = false; - m_Props = new List>(); - foreach (var prop in props) - { - m_Props.Add(new List(prop.Split('/'))); - } - } - - bool CheckContained(string prop) - { - if (m_All) - return true; - foreach (var list in m_Props) - { - if (list.Count == m_Level+1) - { - if (list[m_Level] == prop) - return true; - if (list[m_Level] == "*") - { - m_All = true; // short-circuit all at this level - return true; - } - } - } - return false; - } - - public bool CheckStringValueInArray(string value) { return CheckContained(value); } - public bool CheckKeyInDict(string key) { return CheckContained(key); } - - public bool CheckStringValueInDict(string key, string value) - { - foreach (var list in m_Props) - { - if (list.Count == m_Level + 2) - { - if ((list[m_Level] == "*" || list[m_Level] == key) && - list[m_Level+1] == "*" || list[m_Level+1] == value) - return true; - } - } - return false; - } - - public PropertyCommentChecker NextLevel(string prop) - { - var newList = new List>(); - foreach (var list in m_Props) - { - if (list.Count <= m_Level+1) - continue; - if (list[m_Level] == "*" || list[m_Level] == prop) - newList.Add(list); - } - return new PropertyCommentChecker(m_Level + 1, newList); - } - } - - class Serializer - { - public static PBXElementDict ParseTreeAST(TreeAST ast, TokenList tokens, string text) - { - var el = new PBXElementDict(); - foreach (var kv in ast.values) - { - PBXElementString key = ParseIdentifierAST(kv.key, tokens, text); - PBXElement value = ParseValueAST(kv.value, tokens, text); - el[key.value] = value; - } - return el; - } - - public static PBXElementArray ParseArrayAST(ArrayAST ast, TokenList tokens, string text) - { - var el = new PBXElementArray(); - foreach (var v in ast.values) - { - el.values.Add(ParseValueAST(v, tokens, text)); - } - return el; - } - - public static PBXElement ParseValueAST(ValueAST ast, TokenList tokens, string text) - { - if (ast is TreeAST) - return ParseTreeAST((TreeAST)ast, tokens, text); - if (ast is ArrayAST) - return ParseArrayAST((ArrayAST)ast, tokens, text); - if (ast is IdentifierAST) - return ParseIdentifierAST((IdentifierAST)ast, tokens, text); - return null; - } - - public static PBXElementString ParseIdentifierAST(IdentifierAST ast, TokenList tokens, string text) - { - Token tok = tokens[ast.value]; - string value; - switch (tok.type) - { - case TokenType.String: - value = text.Substring(tok.begin, tok.end - tok.begin); - return new PBXElementString(value); - case TokenType.QuotedString: - value = text.Substring(tok.begin, tok.end - tok.begin); - value = PBXStream.UnquoteString(value); - return new PBXElementString(value); - default: - throw new Exception("Internal parser error"); - } - } - - static string k_Indent = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; - - static string GetIndent(int indent) - { - return k_Indent.Substring(0, indent); - } - - static void WriteStringImpl(StringBuilder sb, string s, bool comment, GUIDToCommentMap comments) - { - if (comment) - comments.WriteStringBuilder(sb, s); - else - sb.Append(PBXStream.QuoteStringIfNeeded(s)); - } - - public static void WriteDictKeyValue(StringBuilder sb, string key, PBXElement value, int indent, bool compact, - PropertyCommentChecker checker, GUIDToCommentMap comments) - { - if (!compact) - { - sb.Append("\n"); - sb.Append(GetIndent(indent)); - } - WriteStringImpl(sb, key, checker.CheckKeyInDict(key), comments); - sb.Append(" = "); - - if (value is PBXElementString) - WriteStringImpl(sb, value.AsString(), checker.CheckStringValueInDict(key, value.AsString()), comments); - else if (value is PBXElementDict) - WriteDict(sb, value.AsDict(), indent, compact, checker.NextLevel(key), comments); - else if (value is PBXElementArray) - WriteArray(sb, value.AsArray(), indent, compact, checker.NextLevel(key), comments); - sb.Append(";"); - if (compact) - sb.Append(" "); - } - - public static void WriteDict(StringBuilder sb, PBXElementDict el, int indent, bool compact, - PropertyCommentChecker checker, GUIDToCommentMap comments) - { - sb.Append("{"); - - if (el.Contains("isa")) - WriteDictKeyValue(sb, "isa", el["isa"], indent+1, compact, checker, comments); - var keys = new List(el.values.Keys); - keys.Sort(StringComparer.Ordinal); - foreach (var key in keys) - { - if (key != "isa") - WriteDictKeyValue(sb, key, el[key], indent+1, compact, checker, comments); - } - if (!compact) - { - sb.Append("\n"); - sb.Append(GetIndent(indent)); - } - sb.Append("}"); - } - - public static void WriteArray(StringBuilder sb, PBXElementArray el, int indent, bool compact, - PropertyCommentChecker checker, GUIDToCommentMap comments) - { - sb.Append("("); - foreach (var value in el.values) - { - if (!compact) - { - sb.Append("\n"); - sb.Append(GetIndent(indent+1)); - } - - if (value is PBXElementString) - WriteStringImpl(sb, value.AsString(), checker.CheckStringValueInArray(value.AsString()), comments); - else if (value is PBXElementDict) - WriteDict(sb, value.AsDict(), indent+1, compact, checker.NextLevel("*"), comments); - else if (value is PBXElementArray) - WriteArray(sb, value.AsArray(), indent+1, compact, checker.NextLevel("*"), comments); - sb.Append(","); - if (compact) - sb.Append(" "); - } - - if (!compact) - { - sb.Append("\n"); - sb.Append(GetIndent(indent)); - } - sb.Append(")"); - } - } - -} // namespace UnityEditor.iOS.Xcode - diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Serializer.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBX/Serializer.cs.meta deleted file mode 100644 index 3a690e2..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Serializer.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 5a9befc0de3574177bda5354fbfa8986 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Utils.cs b/Assets/Zapic/Editor/Xcode.Custom/PBX/Utils.cs deleted file mode 100644 index 231980e..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Utils.cs +++ /dev/null @@ -1,308 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; -using System.IO; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode.PBX -#else -namespace UnityEditor.iOS.Xcode.Custom.PBX -#endif -{ - internal class GUIDToCommentMap - { - private Dictionary m_Dict = new Dictionary(); - - public string this[string guid] - { - get { - if (m_Dict.ContainsKey(guid)) - return m_Dict[guid]; - return null; - } - } - - public void Add(string guid, string comment) - { - if (m_Dict.ContainsKey(guid)) - return; - m_Dict.Add(guid, comment); - } - - public void Remove(string guid) - { - m_Dict.Remove(guid); - } - - public string Write(string guid) - { - string comment = this[guid]; - if (comment == null) - return guid; - return String.Format("{0} /* {1} */", guid, comment); - } - - public void WriteStringBuilder(StringBuilder sb, string guid) - { - string comment = this[guid]; - if (comment == null) - sb.Append(guid); - else - { - // {0} /* {1} */ - sb.Append(guid).Append(" /* ").Append(comment).Append(" */"); - } - } - } - - internal class PBXGUID - { - internal delegate string GuidGenerator(); - - // We allow changing Guid generator to make testing of PBXProject possible - private static GuidGenerator guidGenerator = DefaultGuidGenerator; - - internal static string DefaultGuidGenerator() - { - return Guid.NewGuid().ToString("N").Substring(8).ToUpper(); - } - - internal static void SetGuidGenerator(GuidGenerator generator) - { - guidGenerator = generator; - } - - // Generates a GUID. - public static string Generate() - { - return guidGenerator(); - } - } - - internal class PBXRegex - { - public static string GuidRegexString = "[A-Fa-f0-9]{24}"; - } - - internal class PBXStream - { - static bool DontNeedQuotes(string src) - { - // using a regex instead of explicit matching slows down common cases by 40% - if (src.Length == 0) - return false; - - bool hasSlash = false; - for (int i = 0; i < src.Length; ++i) - { - char c = src[i]; - if (Char.IsLetterOrDigit(c) || c == '.' || c == '*' || c == '_') - continue; - if (c == '/') - { - hasSlash = true; - continue; - } - return false; - } - if (hasSlash) - { - if (src.Contains("//") || src.Contains("/*") || src.Contains("*/")) - return false; - } - return true; - } - - // Quotes the given string if it contains special characters. Note: if the string already - // contains quotes, then they are escaped and the entire string quoted again - public static string QuoteStringIfNeeded(string src) - { - if (DontNeedQuotes(src)) - return src; - return "\"" + src.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") + "\""; - } - - // If the given string is quoted, removes the quotes and unescapes any quotes within the string - public static string UnquoteString(string src) - { - if (!src.StartsWith("\"") || !src.EndsWith("\"")) - return src; - return src.Substring(1, src.Length - 2).Replace("\\\\", "\u569f").Replace("\\\"", "\"") - .Replace("\\n", "\n").Replace("\u569f", "\\"); // U+569f is a rarely used Chinese character - } - } - - internal enum PBXFileType - { - NotBuildable, - Framework, - Source, - Resource, - CopyFile, - ShellScript - } - - internal class FileTypeUtils - { - internal class FileTypeDesc - { - public FileTypeDesc(string typeName, PBXFileType type) - { - this.name = typeName; - this.type = type; - this.isExplicit = false; - } - - public FileTypeDesc(string typeName, PBXFileType type, bool isExplicit) - { - this.name = typeName; - this.type = type; - this.isExplicit = isExplicit; - } - - public string name; - public PBXFileType type; - public bool isExplicit; - } - - private static readonly Dictionary types = - new Dictionary - { - { "a", new FileTypeDesc("archive.ar", PBXFileType.Framework) }, - { "aif", new FileTypeDesc("sound.aif", PBXFileType.Resource) }, - { "app", new FileTypeDesc("wrapper.application", PBXFileType.NotBuildable, true) }, - { "appex", new FileTypeDesc("wrapper.app-extension", PBXFileType.CopyFile) }, - { "bin", new FileTypeDesc("archive.macbinary", PBXFileType.Resource) }, - { "s", new FileTypeDesc("sourcecode.asm", PBXFileType.Source) }, - { "c", new FileTypeDesc("sourcecode.c.c", PBXFileType.Source) }, - { "cc", new FileTypeDesc("sourcecode.cpp.cpp", PBXFileType.Source) }, - { "cpp", new FileTypeDesc("sourcecode.cpp.cpp", PBXFileType.Source) }, - { "swift", new FileTypeDesc("sourcecode.swift", PBXFileType.Source) }, - { "dll", new FileTypeDesc("file", PBXFileType.NotBuildable) }, - { "framework", new FileTypeDesc("wrapper.framework", PBXFileType.Framework) }, - { "h", new FileTypeDesc("sourcecode.c.h", PBXFileType.NotBuildable) }, - { "pch", new FileTypeDesc("sourcecode.c.h", PBXFileType.NotBuildable) }, - { "icns", new FileTypeDesc("image.icns", PBXFileType.Resource) }, - { "xcassets", new FileTypeDesc("folder.assetcatalog", PBXFileType.Resource) }, - { "inc", new FileTypeDesc("sourcecode.inc", PBXFileType.NotBuildable) }, - { "m", new FileTypeDesc("sourcecode.c.objc", PBXFileType.Source) }, - { "mm", new FileTypeDesc("sourcecode.cpp.objcpp", PBXFileType.Source ) }, - { "mp3", new FileTypeDesc("sound.mp3", PBXFileType.Resource) }, - { "nib", new FileTypeDesc("wrapper.nib", PBXFileType.Resource) }, - { "plist", new FileTypeDesc("text.plist.xml", PBXFileType.Resource) }, - { "png", new FileTypeDesc("image.png", PBXFileType.Resource) }, - { "rtf", new FileTypeDesc("text.rtf", PBXFileType.Resource) }, - { "tiff", new FileTypeDesc("image.tiff", PBXFileType.Resource) }, - { "txt", new FileTypeDesc("text", PBXFileType.Resource) }, - { "json", new FileTypeDesc("text.json", PBXFileType.Resource) }, - { "xcodeproj", new FileTypeDesc("wrapper.pb-project", PBXFileType.NotBuildable) }, - { "xib", new FileTypeDesc("file.xib", PBXFileType.Resource) }, - { "strings", new FileTypeDesc("text.plist.strings", PBXFileType.Resource) }, - { "storyboard",new FileTypeDesc("file.storyboard", PBXFileType.Resource) }, - { "bundle", new FileTypeDesc("wrapper.plug-in", PBXFileType.Resource) }, - { "dylib", new FileTypeDesc("compiled.mach-o.dylib", PBXFileType.Framework) }, - { "tbd", new FileTypeDesc("sourcecode.text-based-dylib-definition", PBXFileType.Framework) }, - { "wav", new FileTypeDesc("sound.wav", PBXFileType.Resource) } - }; - - public static string TrimExtension(string ext) - { - return ext.TrimStart('.'); - } - - public static bool IsKnownExtension(string ext) - { - ext = TrimExtension(ext); - return types.ContainsKey(ext); - } - - internal static bool IsFileTypeExplicit(string ext) - { - ext = TrimExtension(ext); - if (types.ContainsKey(ext)) - return types[ext].isExplicit; - return false; - } - - public static PBXFileType GetFileType(string ext, bool isFolderRef) - { - ext = TrimExtension(ext); - if (isFolderRef) - return PBXFileType.Resource; - if (!types.ContainsKey(ext)) - return PBXFileType.Resource; - return types[ext].type; - } - - public static string GetTypeName(string ext) - { - ext = TrimExtension(ext); - if (types.ContainsKey(ext)) - return types[ext].name; - // Xcode actually checks the file contents to determine the file type. - // Text files have "text" type and all other files have "file" type. - // Since we can't reasonably determine whether the file in question is - // a text file, we just take the safe route and return "file" type. - return "file"; - } - - public static bool IsBuildableFile(string ext) - { - ext = TrimExtension(ext); - if (!types.ContainsKey(ext)) - return true; - if (types[ext].type != PBXFileType.NotBuildable) - return true; - return false; - } - - public static bool IsBuildable(string ext, bool isFolderReference) - { - ext = TrimExtension(ext); - if (isFolderReference) - return true; - return IsBuildableFile(ext); - } - - private static readonly Dictionary sourceTree = new Dictionary - { - { PBXSourceTree.Absolute, "" }, - { PBXSourceTree.Group, "" }, - { PBXSourceTree.Build, "BUILT_PRODUCTS_DIR" }, - { PBXSourceTree.Developer, "DEVELOPER_DIR" }, - { PBXSourceTree.Sdk, "SDKROOT" }, - { PBXSourceTree.Source, "SOURCE_ROOT" }, - }; - - private static readonly Dictionary stringToSourceTreeMap = new Dictionary - { - { "", PBXSourceTree.Absolute }, - { "", PBXSourceTree.Group }, - { "BUILT_PRODUCTS_DIR", PBXSourceTree.Build }, - { "DEVELOPER_DIR", PBXSourceTree.Developer }, - { "SDKROOT", PBXSourceTree.Sdk }, - { "SOURCE_ROOT", PBXSourceTree.Source }, - }; - - internal static string SourceTreeDesc(PBXSourceTree tree) - { - return sourceTree[tree]; - } - - // returns PBXSourceTree.Source on error - internal static PBXSourceTree ParseSourceTree(string tree) - { - if (stringToSourceTreeMap.ContainsKey(tree)) - return stringToSourceTreeMap[tree]; - return PBXSourceTree.Source; - } - - internal static List AllAbsoluteSourceTrees() - { - return new List{PBXSourceTree.Absolute, PBXSourceTree.Build, - PBXSourceTree.Developer, PBXSourceTree.Sdk, PBXSourceTree.Source}; - } - } - -} // UnityEditor.iOS.Xcode diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Utils.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBX/Utils.cs.meta deleted file mode 100644 index 014c592..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Utils.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: c91fbdb87f24f4039a2dd8c9f9949c8b -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXCapabilityType.cs b/Assets/Zapic/Editor/Xcode.Custom/PBXCapabilityType.cs deleted file mode 100644 index 0b201fd..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXCapabilityType.cs +++ /dev/null @@ -1,129 +0,0 @@ -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode -#else -namespace UnityEditor.iOS.Xcode.Custom -#endif -{ - /// - /// List of all the capabilities available. - /// - public sealed class PBXCapabilityType - { - public static readonly PBXCapabilityType ApplePay = new PBXCapabilityType ("com.apple.ApplePay", true); - public static readonly PBXCapabilityType AppGroups = new PBXCapabilityType ("com.apple.ApplicationGroups.iOS", true); - public static readonly PBXCapabilityType AssociatedDomains = new PBXCapabilityType ("com.apple.SafariKeychain", true); - public static readonly PBXCapabilityType BackgroundModes = new PBXCapabilityType ("com.apple.BackgroundModes", false); - public static readonly PBXCapabilityType DataProtection = new PBXCapabilityType ("com.apple.DataProtection", true); - public static readonly PBXCapabilityType GameCenter = new PBXCapabilityType ("com.apple.GameCenter", false, "GameKit.framework"); - public static readonly PBXCapabilityType HealthKit = new PBXCapabilityType ("com.apple.HealthKit", true, "HealthKit.framework"); - public static readonly PBXCapabilityType HomeKit = new PBXCapabilityType ("com.apple.HomeKit", true, "HomeKit.framework"); - public static readonly PBXCapabilityType iCloud = new PBXCapabilityType("com.apple.iCloud", true, "CloudKit.framework", true); - public static readonly PBXCapabilityType InAppPurchase = new PBXCapabilityType ("com.apple.InAppPurchase", false); - public static readonly PBXCapabilityType InterAppAudio = new PBXCapabilityType ("com.apple.InterAppAudio", true, "AudioToolbox.framework"); - public static readonly PBXCapabilityType KeychainSharing = new PBXCapabilityType ("com.apple.KeychainSharing", true); - public static readonly PBXCapabilityType Maps = new PBXCapabilityType("com.apple.Maps.iOS", false, "MapKit.framework"); - public static readonly PBXCapabilityType PersonalVPN = new PBXCapabilityType("com.apple.VPNLite", true, "NetworkExtension.framework"); - public static readonly PBXCapabilityType PushNotifications = new PBXCapabilityType ("com.apple.Push", true); - public static readonly PBXCapabilityType Siri = new PBXCapabilityType ("com.apple.Siri", true); - public static readonly PBXCapabilityType Wallet = new PBXCapabilityType ("com.apple.Wallet", true, "PassKit.framework"); - public static readonly PBXCapabilityType WirelessAccessoryConfiguration = new PBXCapabilityType("com.apple.WAC", true, "ExternalAccessory.framework"); - - private readonly string m_ID; - private readonly bool m_RequiresEntitlements; - private readonly string m_Framework; - private readonly bool m_OptionalFramework; - - public bool optionalFramework - { - get { return m_OptionalFramework; } - } - - public string framework - { - get { return m_Framework; } - } - - public string id - { - get { return m_ID; } - } - - public bool requiresEntitlements - { - get { return m_RequiresEntitlements; } - } - - public struct TargetCapabilityPair - { - public string targetGuid; - public PBXCapabilityType capability; - - public TargetCapabilityPair(string guid, PBXCapabilityType type) - { - targetGuid = guid; - capability = type; - } - } - - /// - /// This private object represents what a capability changes in the PBXProject file - /// - /// The string used in the PBXProject file to identify the capability and mark it as enabled. - /// This capability requires an entitlements file therefore we need to add this entitlements file to the code signing entitlement. - /// Specify which framework need to be added to the project for this capability, if "" no framework are added. - /// Some capability (right now only iCloud) adds a framework, not all the time but just when some option are checked - /// this parameter indicates if one of them is checked. - private PBXCapabilityType(string _id, bool _requiresEntitlements, string _framework = "", bool _optionalFramework = false) - { - m_ID = _id; - m_RequiresEntitlements = _requiresEntitlements; - m_Framework = _framework; - m_OptionalFramework = _optionalFramework; - } - - public static PBXCapabilityType StringToPBXCapabilityType(string cap) - { - switch (cap) - { - case "com.apple.ApplePay": - return ApplePay; - case "com.apple.ApplicationGroups.iOS": - return AppGroups; - case "com.apple.SafariKeychain": - return AssociatedDomains; - case "com.apple.BackgroundModes": - return BackgroundModes; - case "com.apple.DataProtection": - return DataProtection; - case "com.apple.GameCenter": - return GameCenter; - case "com.apple.HealthKit": - return HealthKit; - case "com.apple.HomeKit": - return HomeKit; - case "com.apple.iCloud": - return iCloud; - case "com.apple.InAppPurchase": - return InAppPurchase; - case "com.apple.InterAppAudio": - return InterAppAudio; - case "com.apple.KeychainSharing": - return KeychainSharing; - case "com.apple.Maps.iOS": - return Maps; - case "com.apple.VPNLite": - return PersonalVPN; - case "com.apple.Push": - return PushNotifications; - case "com.apple.Siri": - return Siri; - case "com.apple.Wallet": - return Wallet; - case "WAC": - return WirelessAccessoryConfiguration; - default: - return null; - } - } - } -} diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXCapabilityType.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBXCapabilityType.cs.meta deleted file mode 100644 index abbe652..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXCapabilityType.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 01a225e71ba0d4404bf491344faf805a -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXPath.cs b/Assets/Zapic/Editor/Xcode.Custom/PBXPath.cs deleted file mode 100644 index 9c4aaf9..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXPath.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; -using System.IO; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode -#else -namespace UnityEditor.iOS.Xcode.Custom -#endif -{ - internal class PBXPath - { - /// Replaces '\' with '/'. We need to apply this function to all paths that come from the user - /// of the API because we store paths to pbxproj and on windows we may get path with '\' slashes - /// instead of '/' slashes - public static string FixSlashes(string path) - { - if (path == null) - return null; - return path.Replace('\\', '/'); - } - - public static void Combine(string path1, PBXSourceTree tree1, string path2, PBXSourceTree tree2, - out string resPath, out PBXSourceTree resTree) - { - if (tree2 == PBXSourceTree.Group) - { - resPath = Combine(path1, path2); - resTree = tree1; - return; - } - - resPath = path2; - resTree = tree2; - } - - // Combines two paths - public static string Combine(string path1, string path2) - { - if (path2.StartsWith("/")) - return path2; - if (path1.EndsWith("/")) - return path1 + path2; - if (path1 == "") - return path2; - if (path2 == "") - return path1; - return path1 + "/" + path2; - } - - public static string GetDirectory(string path) - { - path = path.TrimEnd('/'); - int pos = path.LastIndexOf('/'); - if (pos == -1) - return ""; - else - return path.Substring(0, pos); - } - - public static string GetCurrentDirectory() - { - if (Environment.OSVersion.Platform != PlatformID.MacOSX && - Environment.OSVersion.Platform != PlatformID.Unix) - { - throw new Exception("PBX project compatible current directory can only obtained on OSX"); - } - - string path = Directory.GetCurrentDirectory(); - path = FixSlashes(path); - if (!IsPathRooted(path)) - return "/" + path; - return path; - } - - public static string GetFilename(string path) - { - int pos = path.LastIndexOf('/'); - if (pos == -1) - return path; - else - return path.Substring(pos + 1); - } - - public static bool IsPathRooted(string path) - { - if (path == null || path.Length == 0) - return false; - return path[0] == '/'; - } - - public static string GetFullPath(string path) - { - if (IsPathRooted(path)) - return path; - else - return Combine(GetCurrentDirectory(), path); - } - - public static string[] Split(string path) - { - if (string.IsNullOrEmpty(path)) - return new string[]{}; - return path.Split(new[]{'/'}, StringSplitOptions.RemoveEmptyEntries); - } - } - -} // UnityEditor.iOS.Xcode diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXPath.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBXPath.cs.meta deleted file mode 100644 index 729cf3e..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXPath.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 99e0d9ef7c3634554b38ae84d17b8f45 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXProject.cs b/Assets/Zapic/Editor/Xcode.Custom/PBXProject.cs deleted file mode 100644 index d38cce0..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXProject.cs +++ /dev/null @@ -1,1425 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -#if UNITY_XCODE_API_BUILD -using UnityEditor.iOS.Xcode.PBX; -#else -using UnityEditor.iOS.Xcode.Custom.PBX; -#endif - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode -#else -namespace UnityEditor.iOS.Xcode.Custom -#endif -{ - using PBXBuildFileSection = KnownSectionBase; - using PBXFileReferenceSection = KnownSectionBase; - using PBXGroupSection = KnownSectionBase; - using PBXContainerItemProxySection = KnownSectionBase; - using PBXReferenceProxySection = KnownSectionBase; - using PBXSourcesBuildPhaseSection = KnownSectionBase; - using PBXFrameworksBuildPhaseSection= KnownSectionBase; - using PBXResourcesBuildPhaseSection = KnownSectionBase; - using PBXCopyFilesBuildPhaseSection = KnownSectionBase; - using PBXShellScriptBuildPhaseSection = KnownSectionBase; - using PBXVariantGroupSection = KnownSectionBase; - using PBXNativeTargetSection = KnownSectionBase; - using PBXTargetDependencySection = KnownSectionBase; - using XCBuildConfigurationSection = KnownSectionBase; - using XCConfigurationListSection = KnownSectionBase; - using UnknownSection = KnownSectionBase; - - // Determines the tree the given path is relative to - public enum PBXSourceTree - { - Absolute, // The path is absolute - Source, // The path is relative to the source folder - Group, // The path is relative to the folder it's in. This enum is used only internally, - // do not use it as function parameter - Build, // The path is relative to the build products folder - Developer, // The path is relative to the developer folder - Sdk // The path is relative to the sdk folder - } - - public class PBXProject - { - PBXProjectData m_Data = new PBXProjectData(); - - // convenience accessors for public members of data. This is temporary; will be fixed by an interface change - // of PBXProjectData - internal PBXContainerItemProxySection containerItems { get { return m_Data.containerItems; } } - internal PBXReferenceProxySection references { get { return m_Data.references; } } - internal PBXSourcesBuildPhaseSection sources { get { return m_Data.sources; } } - internal PBXFrameworksBuildPhaseSection frameworks { get { return m_Data.frameworks; } } - internal PBXResourcesBuildPhaseSection resources { get { return m_Data.resources; } } - internal PBXCopyFilesBuildPhaseSection copyFiles { get { return m_Data.copyFiles; } } - internal PBXShellScriptBuildPhaseSection shellScripts { get { return m_Data.shellScripts; } } - internal PBXNativeTargetSection nativeTargets { get { return m_Data.nativeTargets; } } - internal PBXTargetDependencySection targetDependencies { get { return m_Data.targetDependencies; } } - internal PBXVariantGroupSection variantGroups { get { return m_Data.variantGroups; } } - internal XCBuildConfigurationSection buildConfigs { get { return m_Data.buildConfigs; } } - internal XCConfigurationListSection buildConfigLists { get { return m_Data.buildConfigLists; } } - internal PBXProjectSection project { get { return m_Data.project; } } - - internal PBXBuildFileData BuildFilesGet(string guid) { return m_Data.BuildFilesGet(guid); } - internal void BuildFilesAdd(string targetGuid, PBXBuildFileData buildFile) { m_Data.BuildFilesAdd(targetGuid, buildFile); } - internal void BuildFilesRemove(string targetGuid, string fileGuid) { m_Data.BuildFilesRemove(targetGuid, fileGuid); } - internal PBXBuildFileData BuildFilesGetForSourceFile(string targetGuid, string fileGuid) { return m_Data.BuildFilesGetForSourceFile(targetGuid, fileGuid); } - internal IEnumerable BuildFilesGetAll() { return m_Data.BuildFilesGetAll(); } - internal void FileRefsAdd(string realPath, string projectPath, PBXGroupData parent, PBXFileReferenceData fileRef) { m_Data.FileRefsAdd(realPath, projectPath, parent, fileRef); } - internal PBXFileReferenceData FileRefsGet(string guid) { return m_Data.FileRefsGet(guid); } - internal PBXFileReferenceData FileRefsGetByRealPath(string path, PBXSourceTree sourceTree) { return m_Data.FileRefsGetByRealPath(path, sourceTree); } - internal PBXFileReferenceData FileRefsGetByProjectPath(string path) { return m_Data.FileRefsGetByProjectPath(path); } - internal void FileRefsRemove(string guid) { m_Data.FileRefsRemove(guid); } - internal PBXGroupData GroupsGet(string guid) { return m_Data.GroupsGet(guid); } - internal PBXGroupData GroupsGetByChild(string childGuid) { return m_Data.GroupsGetByChild(childGuid); } - internal PBXGroupData GroupsGetMainGroup() { return m_Data.GroupsGetMainGroup(); } - internal PBXGroupData GroupsGetByProjectPath(string sourceGroup) { return m_Data.GroupsGetByProjectPath(sourceGroup); } - internal void GroupsAdd(string projectPath, PBXGroupData parent, PBXGroupData gr) { m_Data.GroupsAdd(projectPath, parent, gr); } - internal void GroupsAddDuplicate(PBXGroupData gr) { m_Data.GroupsAddDuplicate(gr); } - internal void GroupsRemove(string guid) { m_Data.GroupsRemove(guid); } - internal FileGUIDListBase BuildSectionAny(PBXNativeTargetData target, string path, bool isFolderRef) { return m_Data.BuildSectionAny(target, path, isFolderRef); } - internal FileGUIDListBase BuildSectionAny(string sectionGuid) { return m_Data.BuildSectionAny(sectionGuid); } - - /// - /// Returns the path to PBX project in the given Unity build path. This function can only - /// be used in Unity-generated projects - /// - /// The project build path - /// The path to the PBX project file that can later be opened via ReadFromFile function - public static string GetPBXProjectPath(string buildPath) - { - return PBXPath.Combine(buildPath, "Unity-iPhone.xcodeproj/project.pbxproj"); - } - - /// - /// Returns the default main target name in Unity project. - /// The returned target name can then be used to retrieve the GUID of the target via TargetGuidByName - /// function. This function can only be used in Unity-generated projects. - /// - /// The default main target name. - public static string GetUnityTargetName() - { - return "Unity-iPhone"; - } - - /// - /// Returns the default test target name in Unity project. - /// The returned target name can then be used to retrieve the GUID of the target via TargetGuidByName - /// function. This function can only be used in Unity-generated projects. - /// - /// The default test target name. - public static string GetUnityTestTargetName() - { - return "Unity-iPhone Tests"; - } - - /// - /// Returns the GUID of the project. The project GUID identifies a project-wide native target which - /// is used to set project-wide properties. This GUID can be passed to any functions that accepts - /// target GUIDs as parameters. - /// - /// The GUID of the project. - public string ProjectGuid() - { - return project.project.guid; - } - - /// - /// Returns the GUID of the native target with the given name. - /// In projects produced by Unity the main target can be retrieved via GetUnityTargetName function, - /// whereas the test target name can be retrieved by GetUnityTestTargetName function. - /// - /// The name of the native target. - /// The GUID identifying the native target. - public string TargetGuidByName(string name) - { - foreach (var entry in nativeTargets.GetEntries()) - if (entry.Value.name == name) - return entry.Key; - return null; - } - - /// - /// Checks if files with the given extension are known to PBXProject. - /// - /// Returns true if is the extension is known, false otherwise. - /// The file extension (leading dot is not necessary, but accepted). - public static bool IsKnownExtension(string ext) - { - return FileTypeUtils.IsKnownExtension(ext); - } - - /// - /// Checks if files with the given extension are known to PBXProject. - /// Returns true if the extension is not known by PBXProject. - /// - /// Returns true if is the extension is known, false otherwise. - /// The file extension (leading dot is not necessary, but accepted). - public static bool IsBuildable(string ext) - { - return FileTypeUtils.IsBuildableFile(ext); - } - - // The same file can be referred to by more than one project path. - private string AddFileImpl(string path, string projectPath, PBXSourceTree tree, bool isFolderReference) - { - path = PBXPath.FixSlashes(path); - projectPath = PBXPath.FixSlashes(projectPath); - - if (!isFolderReference && Path.GetExtension(path) != Path.GetExtension(projectPath)) - throw new Exception("Project and real path extensions do not match"); - - string guid = FindFileGuidByProjectPath(projectPath); - if (guid == null) - guid = FindFileGuidByRealPath(path); - if (guid == null) - { - PBXFileReferenceData fileRef; - if (isFolderReference) - fileRef = PBXFileReferenceData.CreateFromFolderReference(path, PBXPath.GetFilename(projectPath), tree); - else - fileRef = PBXFileReferenceData.CreateFromFile(path, PBXPath.GetFilename(projectPath), tree); - PBXGroupData parent = CreateSourceGroup(PBXPath.GetDirectory(projectPath)); - parent.children.AddGUID(fileRef.guid); - FileRefsAdd(path, projectPath, parent, fileRef); - guid = fileRef.guid; - } - return guid; - } - - /// - /// Adds a new file reference to the list of known files. - /// The group structure is automatically created to correspond to the project path. - /// To add the file to the list of files to build, pass the returned value to [[AddFileToBuild]]. - /// - /// The GUID of the added file. It can later be used to add the file for building to targets, etc. - /// The physical path to the file on the filesystem. - /// The project path to the file. - /// The source tree the path is relative to. By default it's [[PBXSourceTree.Source]]. - /// The [[PBXSourceTree.Group]] tree is not supported. - public string AddFile(string path, string projectPath, PBXSourceTree sourceTree = PBXSourceTree.Source) - { - if (sourceTree == PBXSourceTree.Group) - throw new Exception("sourceTree must not be PBXSourceTree.Group"); - return AddFileImpl(path, projectPath, sourceTree, false); - } - - /// - /// Adds a new folder reference to the list of known files. - /// The group structure is automatically created to correspond to the project path. - /// To add the folder reference to the list of files to build, pass the returned value to [[AddFileToBuild]]. - /// - /// The GUID of the added folder reference. It can later be used to add the file for building to targets, etc. - /// The physical path to the folder on the filesystem. - /// The project path to the folder. - /// The source tree the path is relative to. By default it's [[PBXSourceTree.Source]]. - /// The [[PBXSourceTree.Group]] tree is not supported. - public string AddFolderReference(string path, string projectPath, PBXSourceTree sourceTree = PBXSourceTree.Source) - { - if (sourceTree == PBXSourceTree.Group) - throw new Exception("sourceTree must not be PBXSourceTree.Group"); - return AddFileImpl(path, projectPath, sourceTree, true); - } - - private void AddBuildFileImpl(string targetGuid, string fileGuid, bool weak, string compileFlags) - { - PBXNativeTargetData target = nativeTargets[targetGuid]; - PBXFileReferenceData fileRef = FileRefsGet(fileGuid); - - string ext = Path.GetExtension(fileRef.path); - - if (FileTypeUtils.IsBuildable(ext, fileRef.isFolderReference) && - BuildFilesGetForSourceFile(targetGuid, fileGuid) == null) - { - PBXBuildFileData buildFile = PBXBuildFileData.CreateFromFile(fileGuid, weak, compileFlags); - BuildFilesAdd(targetGuid, buildFile); - BuildSectionAny(target, ext, fileRef.isFolderReference).files.AddGUID(buildFile.guid); - } - } - - /// - /// Configures file for building for the given native target. - /// A projects containing multiple native targets, a single file or folder reference can be - /// configured to be built in all, some or none of the targets. The file or folder reference is - /// added to appropriate build section depending on the file extension. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The file guid returned by [[AddFile]] or [[AddFolderReference]]. - public void AddFileToBuild(string targetGuid, string fileGuid) - { - AddBuildFileImpl(targetGuid, fileGuid, false, null); - } - - /// - /// Configures file for building for the given native target with specific compiler flags. - /// The function is equivalent to [[AddFileToBuild()]] except that compile flags are specified. - /// A projects containing multiple native targets, a single file or folder reference can be - /// configured to be built in all, some or none of the targets. The file or folder reference is - /// added to appropriate build section depending on the file extension. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The file guid returned by [[AddFile]] or [[AddFolderReference]]. - /// Compile flags to use. - public void AddFileToBuildWithFlags(string targetGuid, string fileGuid, string compileFlags) - { - AddBuildFileImpl(targetGuid, fileGuid, false, compileFlags); - } - - /// - /// Configures file for building for the given native target on specific build section. - /// The function is equivalent to [[AddFileToBuild()]] except that specific build section is specified. - /// A projects containing multiple native targets, a single file or folder reference can be - /// configured to be built in all, some or none of the targets. The file or folder reference is - /// added to appropriate build section depending on the file extension. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The GUID of the section to add the file to. - /// The file guid returned by [[AddFile]] or [[AddFolderReference]]. - public void AddFileToBuildSection(string targetGuid, string sectionGuid, string fileGuid) - { - PBXBuildFileData buildFile = PBXBuildFileData.CreateFromFile(fileGuid, false, null); - BuildFilesAdd(targetGuid, buildFile); - BuildSectionAny(sectionGuid).files.AddGUID(buildFile.guid); - } - - /// - /// Returns compile flags set for the specific file. - /// Null is returned if the file has no configured compile flags or the file is not configured for - /// building on the given target. - /// - /// The compile flags for the specified file. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The GUID of the file. - public List GetCompileFlagsForFile(string targetGuid, string fileGuid) - { - var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid); - if (buildFile == null) - return null; - if (buildFile.compileFlags == null) - return new List(); - return new List(buildFile.compileFlags.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries)); - } - - /// - /// Sets the compilation flags for the given file in the given target. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The GUID of the file. - /// The list of compile flags or null if the flags should be unset. - public void SetCompileFlagsForFile(string targetGuid, string fileGuid, List compileFlags) - { - var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid); - if (buildFile == null) - return; - if (compileFlags == null) - buildFile.compileFlags = null; - else - buildFile.compileFlags = string.Join(" ", compileFlags.ToArray()); - } - - /// - /// Adds an asset tag for the given file. - /// The asset tags identify resources that will be downloaded via On Demand Resources functionality. - /// A request for specific tag will initiate download of all files, configured for that tag. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The GUID of the file. - /// The name of the asset tag. - public void AddAssetTagForFile(string targetGuid, string fileGuid, string tag) - { - var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid); - if (buildFile == null) - return; - if (!buildFile.assetTags.Contains(tag)) - buildFile.assetTags.Add(tag); - if (!project.project.knownAssetTags.Contains(tag)) - project.project.knownAssetTags.Add(tag); - } - - /// - /// Removes an asset tag for the given file. - /// The function does nothing if the file is not configured for building in the given target or if - /// the asset tag is not present in the list of asset tags configured for file. If the file was the - /// last file referring to the given tag across the Xcode project, then the tag is removed from the - /// list of known tags. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The GUID of the file. - /// The name of the asset tag. - public void RemoveAssetTagForFile(string targetGuid, string fileGuid, string tag) - { - var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid); - if (buildFile == null) - return; - buildFile.assetTags.Remove(tag); - // remove from known tags if this was the last one - foreach (var buildFile2 in BuildFilesGetAll()) - { - if (buildFile2.assetTags.Contains(tag)) - return; - } - project.project.knownAssetTags.Remove(tag); - } - - /// - /// Adds the asset tag to the list of tags to download during initial installation. - /// The function does nothing if there are no files that use the given asset tag across the project. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the asset tag. - public void AddAssetTagToDefaultInstall(string targetGuid, string tag) - { - if (!project.project.knownAssetTags.Contains(tag)) - return; - AddBuildProperty(targetGuid, "ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS", tag); - } - - /// - /// Removes the asset tag from the list of tags to download during initial installation. - /// The function does nothing if the tag is not already configured for downloading during - /// initial installation. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the asset tag. - public void RemoveAssetTagFromDefaultInstall(string targetGuid, string tag) - { - UpdateBuildProperty(targetGuid, "ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS", null, new[]{tag}); - } - - /// - /// Removes an asset tag. - /// Removes the given asset tag from the list of configured asset tags for all files on all targets, - /// the list of asset tags configured for initial installation and the list of known asset tags in - /// the Xcode project. - /// - /// The name of the asset tag. - public void RemoveAssetTag(string tag) - { - foreach (var buildFile in BuildFilesGetAll()) - buildFile.assetTags.Remove(tag); - foreach (var targetGuid in nativeTargets.GetGuids()) - RemoveAssetTagFromDefaultInstall(targetGuid, tag); - project.project.knownAssetTags.Remove(tag); - } - - /// - /// Checks if the project contains a file with the given physical path. - /// The search is performed across all absolute source trees. - /// - /// Returns true if the project contains the file, false otherwise. - /// The physical path of the file. - public bool ContainsFileByRealPath(string path) - { - return FindFileGuidByRealPath(path) != null; - } - - /// - /// Checks if the project contains a file with the given physical path. - /// - /// Returns true if the project contains the file, false otherwise. - /// The physical path of the file. - /// The source tree path is relative to. The [[PBXSourceTree.Group]] tree is not supported. - public bool ContainsFileByRealPath(string path, PBXSourceTree sourceTree) - { - if (sourceTree == PBXSourceTree.Group) - throw new Exception("sourceTree must not be PBXSourceTree.Group"); - return FindFileGuidByRealPath(path, sourceTree) != null; - } - - /// - /// Checks if the project contains a file with the given project path. - /// - /// Returns true if the project contains the file, false otherwise. - /// The project path of the file. - public bool ContainsFileByProjectPath(string path) - { - return FindFileGuidByProjectPath(path) != null; - } - - /// - /// Checks whether the given system framework is a dependency of a target. - /// The function assumes system frameworks are located in System/Library/Frameworks folder in the SDK source tree. - /// - /// Returns true if the given framework is a dependency of the given target, - /// false otherwise. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the framework. The extension of the filename must be ".framework". - public bool ContainsFramework(string targetGuid, string framework) - { - var fileGuid = FindFileGuidByRealPath("System/Library/Frameworks/" + framework, PBXSourceTree.Sdk); - if (fileGuid == null) - return false; - - var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid); - return (buildFile != null); - } - - /// - /// Adds a system framework dependency for the specified target. - /// The function assumes system frameworks are located in System/Library/Frameworks folder in the SDK source tree. - /// The framework is added to Frameworks logical folder in the project. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the framework. The extension of the filename must be ".framework". - /// true if the framework is optional (i.e. weakly linked) required, - /// false if the framework is required. - public void AddFrameworkToProject(string targetGuid, string framework, bool weak) - { - string fileGuid = AddFile("System/Library/Frameworks/" + framework, "Frameworks/" + framework, PBXSourceTree.Sdk); - AddBuildFileImpl(targetGuid, fileGuid, weak, null); - } - - /// - /// Removes a system framework dependency for the specified target. - /// The function assumes system frameworks are located in System/Library/Frameworks folder in the SDK source tree. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the framework. The extension of the filename must be ".framework". - public void RemoveFrameworkFromProject(string targetGuid, string framework) - { - var fileGuid = FindFileGuidByRealPath("System/Library/Frameworks/" + framework, PBXSourceTree.Sdk); - if (fileGuid == null) - return; - - BuildFilesRemove(targetGuid, fileGuid); - } - - // Allow user to add a Capability - public bool AddCapability(string targetGuid, PBXCapabilityType capability, string entitlementsFilePath = null, bool addOptionalFramework = false) - { - // If the capability requires entitlements then you have to provide the name of it or we don't add the capability. - if (capability.requiresEntitlements && entitlementsFilePath == "") - { - throw new Exception("Couldn't add the Xcode Capability " + capability.id + " to the PBXProject file because this capability requires an entitlement file."); - } - var p = project.project; - - // If an entitlement with a different name was added for another capability - // we don't add this capacity. - if (p.entitlementsFile != null && entitlementsFilePath != null && p.entitlementsFile != entitlementsFilePath) - { - if (p.capabilities.Count > 0) - throw new WarningException("Attention, it seems that you have multiple entitlements file. Only one will be added the Project : " + p.entitlementsFile); - - return false; - } - - // Add the capability only if it doesn't already exist. - if (p.capabilities.Contains(new PBXCapabilityType.TargetCapabilityPair(targetGuid, capability))) - { - throw new WarningException("This capability has already been added. Method ignored"); - } - - p.capabilities.Add(new PBXCapabilityType.TargetCapabilityPair(targetGuid, capability)); - - // Add the required framework. - if (capability.framework != "" && !capability.optionalFramework || - (capability.framework != "" && capability.optionalFramework && addOptionalFramework)) - { - AddFrameworkToProject(targetGuid, capability.framework, false); - } - - // Finally add the entitlement code signing if it wasn't added before. - if (entitlementsFilePath != null && p.entitlementsFile == null) - { - p.entitlementsFile = entitlementsFilePath; - AddFileImpl(entitlementsFilePath, entitlementsFilePath, PBXSourceTree.Source, false); - SetBuildProperty(targetGuid, "CODE_SIGN_ENTITLEMENTS", PBXPath.FixSlashes(entitlementsFilePath)); - } - return true; - } - - // The Xcode project needs a team set to be able to complete code signing or to add some capabilities. - public void SetTeamId(string targetGuid, string teamId) - { - SetBuildProperty(targetGuid, "DEVELOPMENT_TEAM", teamId); - project.project.teamIDs.Add(targetGuid, teamId); - } - - /// - /// Finds a file with the given physical path in the project, if any. - /// - /// The GUID of the file if the search succeeded, null otherwise. - /// The physical path of the file. - /// The source tree path is relative to. The [[PBXSourceTree.Group]] tree is not supported. - public string FindFileGuidByRealPath(string path, PBXSourceTree sourceTree) - { - if (sourceTree == PBXSourceTree.Group) - throw new Exception("sourceTree must not be PBXSourceTree.Group"); - path = PBXPath.FixSlashes(path); - var fileRef = FileRefsGetByRealPath(path, sourceTree); - if (fileRef != null) - return fileRef.guid; - return null; - } - - /// - /// Finds a file with the given physical path in the project, if any. - /// The search is performed across all absolute source trees. - /// - /// The GUID of the file if the search succeeded, null otherwise. - /// The physical path of the file. - public string FindFileGuidByRealPath(string path) - { - path = PBXPath.FixSlashes(path); - - foreach (var tree in FileTypeUtils.AllAbsoluteSourceTrees()) - { - string res = FindFileGuidByRealPath(path, tree); - if (res != null) - return res; - } - return null; - } - - /// - /// Finds a file with the given project path in the project, if any. - /// - /// The GUID of the file if the search succeeded, null otherwise. - /// The project path of the file. - public string FindFileGuidByProjectPath(string path) - { - path = PBXPath.FixSlashes(path); - var fileRef = FileRefsGetByProjectPath(path); - if (fileRef != null) - return fileRef.guid; - return null; - } - - /// - /// Removes given file from the list of files to build for the given target. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The GUID of the file or folder reference. - public void RemoveFileFromBuild(string targetGuid, string fileGuid) - { - var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid); - if (buildFile == null) - return; - BuildFilesRemove(targetGuid, fileGuid); - - string buildGuid = buildFile.guid; - if (buildGuid != null) - { - foreach (var section in sources.GetEntries()) - section.Value.files.RemoveGUID(buildGuid); - foreach (var section in resources.GetEntries()) - section.Value.files.RemoveGUID(buildGuid); - foreach (var section in copyFiles.GetEntries()) - section.Value.files.RemoveGUID(buildGuid); - foreach (var section in frameworks.GetEntries()) - section.Value.files.RemoveGUID(buildGuid); - } - } - - /// - /// Removes the given file from project. - /// The file is removed from the list of files to build for each native target and also removed - /// from the list of known files. - /// - /// The GUID of the file or folder reference. - public void RemoveFile(string fileGuid) - { - if (fileGuid == null) - return; - - // remove from parent - PBXGroupData parent = GroupsGetByChild(fileGuid); - if (parent != null) - parent.children.RemoveGUID(fileGuid); - RemoveGroupIfEmpty(parent); - - // remove actual file - foreach (var target in nativeTargets.GetEntries()) - RemoveFileFromBuild(target.Value.guid, fileGuid); - FileRefsRemove(fileGuid); - } - - void RemoveGroupIfEmpty(PBXGroupData gr) - { - if (gr.children.Count == 0 && gr != GroupsGetMainGroup()) - { - // remove from parent - PBXGroupData parent = GroupsGetByChild(gr.guid); - parent.children.RemoveGUID(gr.guid); - RemoveGroupIfEmpty(parent); - - // remove actual group - GroupsRemove(gr.guid); - } - } - - private void RemoveGroupChildrenRecursive(PBXGroupData parent) - { - List children = new List(parent.children); - parent.children.Clear(); - foreach (string guid in children) - { - PBXFileReferenceData file = FileRefsGet(guid); - if (file != null) - { - foreach (var target in nativeTargets.GetEntries()) - RemoveFileFromBuild(target.Value.guid, guid); - FileRefsRemove(guid); - continue; - } - - PBXGroupData gr = GroupsGet(guid); - if (gr != null) - { - RemoveGroupChildrenRecursive(gr); - GroupsRemove(gr.guid); - continue; - } - } - } - - internal void RemoveFilesByProjectPathRecursive(string projectPath) - { - projectPath = PBXPath.FixSlashes(projectPath); - PBXGroupData gr = GroupsGetByProjectPath(projectPath); - if (gr == null) - return; - RemoveGroupChildrenRecursive(gr); - RemoveGroupIfEmpty(gr); - } - - // Returns null on error - internal List GetGroupChildrenFiles(string projectPath) - { - projectPath = PBXPath.FixSlashes(projectPath); - PBXGroupData gr = GroupsGetByProjectPath(projectPath); - if (gr == null) - return null; - var res = new List(); - foreach (var guid in gr.children) - { - PBXFileReferenceData fileRef = FileRefsGet(guid); - if (fileRef != null) - res.Add(fileRef.name); - } - return res; - } - - // Returns an empty dictionary if no group or files are found - internal HashSet GetGroupChildrenFilesRefs(string projectPath) - { - projectPath = PBXPath.FixSlashes(projectPath); - PBXGroupData gr = GroupsGetByProjectPath(projectPath); - if (gr == null) - return new HashSet(); - HashSet res = new HashSet(); - foreach (var guid in gr.children) - { - PBXFileReferenceData fileRef = FileRefsGet(guid); - if (fileRef != null) - res.Add(fileRef.path); - } - return res == null ? new HashSet () : res; - } - - internal HashSet GetFileRefsByProjectPaths(IEnumerable paths) - { - HashSet ret = new HashSet(); - foreach (string path in paths) - { - string fixedPath = PBXPath.FixSlashes(path); - var fileRef = FileRefsGetByProjectPath(fixedPath); - if (fileRef != null) - ret.Add(fileRef.path); - } - return ret; - } - - private PBXGroupData GetPBXGroupChildByName(PBXGroupData group, string name) - { - foreach (string guid in group.children) - { - var gr = GroupsGet(guid); - if (gr != null && gr.name == name) - return gr; - } - return null; - } - - /// Creates source group identified by sourceGroup, if needed, and returns it. - /// If sourceGroup is empty or null, root group is returned - internal PBXGroupData CreateSourceGroup(string sourceGroup) - { - sourceGroup = PBXPath.FixSlashes(sourceGroup); - - if (sourceGroup == null || sourceGroup == "") - return GroupsGetMainGroup(); - - PBXGroupData gr = GroupsGetByProjectPath(sourceGroup); - if (gr != null) - return gr; - - // the group does not exist -- create new - gr = GroupsGetMainGroup(); - - var elements = PBXPath.Split(sourceGroup); - string projectPath = null; - foreach (string pathEl in elements) - { - if (projectPath == null) - projectPath = pathEl; - else - projectPath += "/" + pathEl; - - PBXGroupData child = GetPBXGroupChildByName(gr, pathEl); - if (child != null) - gr = child; - else - { - PBXGroupData newGroup = PBXGroupData.Create(pathEl, pathEl, PBXSourceTree.Group); - gr.children.AddGUID(newGroup.guid); - GroupsAdd(projectPath, gr, newGroup); - gr = newGroup; - } - } - return gr; - } - - /// - /// Creates a new native target. - /// Target-specific build configurations are automatically created for each known build configuration name. - /// Note, that this is a requirement that follows from the structure of Xcode projects, not an implementation - /// detail of this function. The function creates a product file reference in the "Products" project folder - /// which refers to the target artifact that is built via this target. - /// - /// The GUID of the new target. - /// The name of the new target. - /// The file extension of the target artifact (leading dot is not necessary, but accepted). - /// The type of the target. For example: - /// "com.apple.product-type.app-extension" - App extension, - /// "com.apple.product-type.application.watchapp2" - WatchKit 2 application - public string AddTarget(string name, string ext, string type) - { - var buildConfigList = XCConfigurationListData.Create(); - buildConfigLists.AddEntry(buildConfigList); - - // create build file reference - string fullName = name + "." + FileTypeUtils.TrimExtension(ext); - var productFileRef = AddFile(fullName, "Products/" + fullName, PBXSourceTree.Build); - var newTarget = PBXNativeTargetData.Create(name, productFileRef, type, buildConfigList.guid); - nativeTargets.AddEntry(newTarget); - project.project.targets.Add(newTarget.guid); - - foreach (var buildConfigName in BuildConfigNames()) - AddBuildConfigForTarget(newTarget.guid, buildConfigName); - - return newTarget.guid; - } - - private IEnumerable GetAllTargetGuids() - { - var targets = new List(); - - targets.Add(project.project.guid); - targets.AddRange(nativeTargets.GetGuids()); - - return targets; - } - - /// - /// Returns the file reference of the artifact created by building target. - /// - /// The file reference of the artifact created by building target. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - public string GetTargetProductFileRef(string targetGuid) - { - return nativeTargets[targetGuid].productReference; - } - - /// - /// Sets up a dependency between two targets. - /// - /// The GUID of the target that is depending on the dependency. - /// The GUID of the dependency target - internal void AddTargetDependency(string targetGuid, string targetDependencyGuid) - { - string dependencyName = nativeTargets[targetDependencyGuid].name; - var containerProxy = PBXContainerItemProxyData.Create(project.project.guid, "1", targetDependencyGuid, dependencyName); - containerItems.AddEntry(containerProxy); - - var targetDependency = PBXTargetDependencyData.Create(targetDependencyGuid, containerProxy.guid); - targetDependencies.AddEntry(targetDependency); - - nativeTargets[targetGuid].dependencies.AddGUID(targetDependency.guid); - } - - // Returns the GUID of the new configuration - // targetGuid can be either native target or the project target. - private string AddBuildConfigForTarget(string targetGuid, string name) - { - if (BuildConfigByName(targetGuid, name) != null) - { - throw new Exception(String.Format("A build configuration by name {0} already exists for target {1}", - targetGuid, name)); - } - var buildConfig = XCBuildConfigurationData.Create(name); - buildConfigs.AddEntry(buildConfig); - - buildConfigLists[GetConfigListForTarget(targetGuid)].buildConfigs.AddGUID(buildConfig.guid); - return buildConfig.guid; - } - - private void RemoveBuildConfigForTarget(string targetGuid, string name) - { - var buildConfigGuid = BuildConfigByName(targetGuid, name); - if (buildConfigGuid == null) - return; - buildConfigs.RemoveEntry(buildConfigGuid); - buildConfigLists[GetConfigListForTarget(targetGuid)].buildConfigs.RemoveGUID(buildConfigGuid); - } - - /// - /// Returns the GUID of build configuration with the given name for the specific target. - /// Null is returned if such configuration does not exist. - /// - /// The GUID of the build configuration or null if it does not exist. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the build configuration. - public string BuildConfigByName(string targetGuid, string name) - { - foreach (string guid in buildConfigLists[GetConfigListForTarget(targetGuid)].buildConfigs) - { - var buildConfig = buildConfigs[guid]; - if (buildConfig != null && buildConfig.name == name) - return buildConfig.guid; - } - return null; - } - - /// - /// Returns the names of the build configurations available in the project. - /// The number and names of the build configurations is a project-wide setting. Each target has the - /// same number of build configurations and the names of these build configurations is the same. - /// In other words, [[BuildConfigByName()]] will succeed for all targets in the project and all - /// build configuration names returned by this function. - /// - /// An array of build config names. - public IEnumerable BuildConfigNames() - { - var names = new List(); - // We use the project target to fetch the build configs - foreach (var guid in buildConfigLists[project.project.buildConfigList].buildConfigs) - names.Add(buildConfigs[guid].name); - - return names; - } - - /// - /// Creates a new set of build configurations for all targets in the project. - /// The number and names of the build configurations is a project-wide setting. Each target has the - /// same number of build configurations and the names of these build configurations is the same. - /// The created configurations are initially empty. Care must be taken to fill them with reasonable - /// defaults. - /// The function throws an exception if a build configuration with the given name already exists. - /// - /// The name of the build configuration. - public void AddBuildConfig(string name) - { - foreach (var targetGuid in GetAllTargetGuids()) - AddBuildConfigForTarget(targetGuid, name); - } - - /// - /// Removes all build configurations with the given name from all targets in the project. - /// The number and names of the build configurations is a project-wide setting. Each target has the - /// same number of build configurations and the names of these build configurations is the same. - /// The function does nothing if the build configuration with the specified name does not exist. - /// - /// The name of the build configuration. - public void RemoveBuildConfig(string name) - { - foreach (var targetGuid in GetAllTargetGuids()) - RemoveBuildConfigForTarget(targetGuid, name); - } - - /// - /// Returns the GUID of sources build phase for the given target. - /// - /// Returns the GUID of the existing phase or null if it does not exist. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - public string GetSourcesBuildPhaseByTarget(string targetGuid) - { - var target = nativeTargets[targetGuid]; - foreach (var phaseGuid in target.phases) { - var phaseAny = BuildSectionAny(phaseGuid); - if (phaseAny is PBXSourcesBuildPhaseData) - return phaseGuid; - } - return null; - } - - /// - /// Creates a new sources build phase for given target. - /// If the target already has sources build phase configured for it, the function returns the - /// existing phase. The new phase is placed at the end of the list of build phases configured - /// for the target. - /// - /// Returns the GUID of the new phase. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - public string AddSourcesBuildPhase(string targetGuid) - { - var phaseGuid = GetSourcesBuildPhaseByTarget(targetGuid); - if (phaseGuid != null) - return phaseGuid; - - var phase = PBXSourcesBuildPhaseData.Create(); - sources.AddEntry(phase); - nativeTargets[targetGuid].phases.AddGUID(phase.guid); - return phase.guid; - } - - /// - /// Returns the GUID of resources build phase for the given target. - /// - /// Returns the GUID of the existing phase or null if it does not exist. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - public string GetResourcesBuildPhaseByTarget(string targetGuid) - { - var target = nativeTargets[targetGuid]; - foreach (var phaseGuid in target.phases) { - var phaseAny = BuildSectionAny(phaseGuid); - if (phaseAny is PBXResourcesBuildPhaseData) - return phaseGuid; - } - return null; - } - - /// - /// Creates a new resources build phase for given target. - /// If the target already has resources build phase configured for it, the function returns the - /// existing phase. The new phase is placed at the end of the list of build phases configured - /// for the target. - /// - /// Returns the GUID of the new phase. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - public string AddResourcesBuildPhase(string targetGuid) - { - var phaseGuid = GetResourcesBuildPhaseByTarget(targetGuid); - if (phaseGuid != null) - return phaseGuid; - - var phase = PBXResourcesBuildPhaseData.Create(); - resources.AddEntry(phase); - nativeTargets[targetGuid].phases.AddGUID(phase.guid); - return phase.guid; - } - - /// - /// Returns the GUID of frameworks build phase for the given target. - /// - /// Returns the GUID of the existing phase or null if it does not exist. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - public string GetFrameworksBuildPhaseByTarget(string targetGuid) - { - var target = nativeTargets[targetGuid]; - foreach (var phaseGuid in target.phases) { - var phaseAny = BuildSectionAny(phaseGuid); - if (phaseAny is PBXFrameworksBuildPhaseData) - return phaseGuid; - } - return null; - } - - /// - /// Creates a new frameworks build phase for given target. - /// If the target already has frameworks build phase configured for it, the function returns the - /// existing phase. The new phase is placed at the end of the list of build phases configured - /// for the target. - /// - /// Returns the GUID of the new phase. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - public string AddFrameworksBuildPhase(string targetGuid) - { - var phaseGuid = GetFrameworksBuildPhaseByTarget(targetGuid); - if (phaseGuid != null) - return phaseGuid; - - var phase = PBXFrameworksBuildPhaseData.Create(); - frameworks.AddEntry(phase); - nativeTargets[targetGuid].phases.AddGUID(phase.guid); - return phase.guid; - } - - /// - /// Returns the GUID of matching copy files build phase for the given target. - /// The parameters of existing copy files build phase are matched to the arguments of this - /// function and the GUID of the phase is returned only if a matching build phase is found. - /// - /// Returns the GUID of the matching phase or null if it does not exist. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the phase. - /// The destination path. - /// The "subfolder spec". The following usages are known: - /// "10" for embedding frameworks; - /// "13" for embedding app extension content; - /// "16" for embedding watch content - public string GetCopyFilesBuildPhaseByTarget(string targetGuid, string name, string dstPath, string subfolderSpec) - { - var target = nativeTargets[targetGuid]; - foreach (var phaseGuid in target.phases) { - var phaseAny = BuildSectionAny(phaseGuid); - if (phaseAny is PBXCopyFilesBuildPhaseData) - { - var copyPhase = (PBXCopyFilesBuildPhaseData) phaseAny; - if (copyPhase.name == name && copyPhase.dstPath == dstPath && - copyPhase.dstSubfolderSpec == subfolderSpec) - { - return phaseGuid; - } - } - } - return null; - } - - /// - /// Creates a new copy files build phase for given target. - /// If the target already has copy files build phase with the same name, dstPath and subfolderSpec - /// configured for it, the function returns the existing phase. - /// The new phase is placed at the end of the list of build phases configured for the target. - /// - /// Returns the GUID of the new phase. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the phase. - /// The destination path. - /// The "subfolder spec". The following usages are known: - /// "10" for embedding frameworks; - /// "13" for embedding app extension content; - /// "16" for embedding watch content - public string AddCopyFilesBuildPhase(string targetGuid, string name, string dstPath, string subfolderSpec) - { - var phaseGuid = GetCopyFilesBuildPhaseByTarget(targetGuid, name, dstPath, subfolderSpec); - if (phaseGuid != null) - return phaseGuid; - - var phase = PBXCopyFilesBuildPhaseData.Create(name, dstPath, subfolderSpec); - copyFiles.AddEntry(phase); - nativeTargets[targetGuid].phases.AddGUID(phase.guid); - return phase.guid; - } - - internal string GetConfigListForTarget(string targetGuid) - { - if (targetGuid == project.project.guid) - return project.project.buildConfigList; - else - return nativeTargets[targetGuid].buildConfigList; - } - - // Sets the baseConfigurationReference key for a XCBuildConfiguration. - // If the argument is null, the base configuration is removed. - internal void SetBaseReferenceForConfig(string configGuid, string baseReference) - { - buildConfigs[configGuid].baseConfigurationReference = baseReference; - } - - internal PBXBuildFileData FindFrameworkByFileGuid(PBXCopyFilesBuildPhaseData phase, string fileGuid) - { - foreach (string buildFileDataGuid in phase.files) - { - var buildFile = BuildFilesGet(buildFileDataGuid); - if (buildFile.fileRef == fileGuid) - return buildFile; - } - return null; - } - - /// - /// Adds a value to build property list in all build configurations for the specified target. - /// Duplicate build properties are ignored. Values for names "LIBRARY_SEARCH_PATHS" and - /// "FRAMEWORK_SEARCH_PATHS" are quoted if they contain spaces. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the build property. - /// The value of the build property. - public void AddBuildProperty(string targetGuid, string name, string value) - { - foreach (string guid in buildConfigLists[GetConfigListForTarget(targetGuid)].buildConfigs) - AddBuildPropertyForConfig(guid, name, value); - } - - /// - /// Adds a value to build property list in all build configurations for the specified targets. - /// Duplicate build properties are ignored. Values for names "LIBRARY_SEARCH_PATHS" and - /// "FRAMEWORK_SEARCH_PATHS" are quoted if they contain spaces. - /// - /// The GUIDs of the target as returned by [[TargetGuidByName()]]. - /// The name of the build property. - /// The value of the build property. - public void AddBuildProperty(IEnumerable targetGuids, string name, string value) - { - foreach (string t in targetGuids) - AddBuildProperty(t, name, value); - } - - /// - /// Adds a value to build property list of the given build configuration - /// Duplicate build properties are ignored. Values for names "LIBRARY_SEARCH_PATHS" and - /// "FRAMEWORK_SEARCH_PATHS" are quoted if they contain spaces. - /// - /// The GUID of the build configuration as returned by [[BuildConfigByName()]]. - /// The name of the build property. - /// The value of the build property. - public void AddBuildPropertyForConfig(string configGuid, string name, string value) - { - buildConfigs[configGuid].AddProperty(name, value); - } - - /// - /// Adds a value to build property list of the given build configurations - /// Duplicate build properties are ignored. Values for names "LIBRARY_SEARCH_PATHS" and - /// "FRAMEWORK_SEARCH_PATHS" are quoted if they contain spaces. - /// - /// The GUIDs of the build configurations as returned by [[BuildConfigByName()]]. - /// The name of the build property. - /// The value of the build property. - public void AddBuildPropertyForConfig(IEnumerable configGuids, string name, string value) - { - foreach (string guid in configGuids) - AddBuildPropertyForConfig(guid, name, value); - } - - /// - /// Adds a value to build property list in all build configurations for the specified target. - /// Duplicate build properties are ignored. Values for names "LIBRARY_SEARCH_PATHS" and - /// "FRAMEWORK_SEARCH_PATHS" are quoted if they contain spaces. - /// - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The name of the build property. - /// The value of the build property. - public void SetBuildProperty(string targetGuid, string name, string value) - { - foreach (string guid in buildConfigLists[GetConfigListForTarget(targetGuid)].buildConfigs) - SetBuildPropertyForConfig(guid, name, value); - } - - /// - /// Adds a value to build property list in all build configurations for the specified targets. - /// Duplicate build properties are ignored. Values for names "LIBRARY_SEARCH_PATHS" and - /// "FRAMEWORK_SEARCH_PATHS" are quoted if they contain spaces. - /// - /// The GUIDs of the target as returned by [[TargetGuidByName()]]. - /// The name of the build property. - /// The value of the build property. - public void SetBuildProperty(IEnumerable targetGuids, string name, string value) - { - foreach (string t in targetGuids) - SetBuildProperty(t, name, value); - } - public void SetBuildPropertyForConfig(string configGuid, string name, string value) - { - buildConfigs[configGuid].SetProperty(name, value); - } - public void SetBuildPropertyForConfig(IEnumerable configGuids, string name, string value) - { - foreach (string guid in configGuids) - SetBuildPropertyForConfig(guid, name, value); - } - - internal void RemoveBuildProperty(string targetGuid, string name) - { - foreach (string guid in buildConfigLists[GetConfigListForTarget(targetGuid)].buildConfigs) - RemoveBuildPropertyForConfig(guid, name); - } - internal void RemoveBuildProperty(IEnumerable targetGuids, string name) - { - foreach (string t in targetGuids) - RemoveBuildProperty(t, name); - } - internal void RemoveBuildPropertyForConfig(string configGuid, string name) - { - buildConfigs[configGuid].RemoveProperty(name); - } - internal void RemoveBuildPropertyForConfig(IEnumerable configGuids, string name) - { - foreach (string guid in configGuids) - RemoveBuildPropertyForConfig(guid, name); - } - - internal void RemoveBuildPropertyValueList(string targetGuid, string name, IEnumerable valueList) - { - foreach (string guid in buildConfigLists[GetConfigListForTarget(targetGuid)].buildConfigs) - RemoveBuildPropertyValueListForConfig(guid, name, valueList); - } - internal void RemoveBuildPropertyValueList(IEnumerable targetGuids, string name, IEnumerable valueList) - { - foreach (string t in targetGuids) - RemoveBuildPropertyValueList(t, name, valueList); - } - internal void RemoveBuildPropertyValueListForConfig(string configGuid, string name, IEnumerable valueList) - { - buildConfigs[configGuid].RemovePropertyValueList(name, valueList); - } - internal void RemoveBuildPropertyValueListForConfig(IEnumerable configGuids, string name, IEnumerable valueList) - { - foreach (string guid in configGuids) - RemoveBuildPropertyValueListForConfig(guid, name, valueList); - } - - /// Interprets the value of the given property as a set of space-delimited strings, then - /// removes strings equal to items to removeValues and adds strings in addValues. - public void UpdateBuildProperty(string targetGuid, string name, - IEnumerable addValues, IEnumerable removeValues) - { - foreach (string guid in buildConfigLists[GetConfigListForTarget(targetGuid)].buildConfigs) - UpdateBuildPropertyForConfig(guid, name, addValues, removeValues); - } - public void UpdateBuildProperty(IEnumerable targetGuids, string name, - IEnumerable addValues, IEnumerable removeValues) - { - foreach (string t in targetGuids) - UpdateBuildProperty(t, name, addValues, removeValues); - } - public void UpdateBuildPropertyForConfig(string configGuid, string name, - IEnumerable addValues, IEnumerable removeValues) - { - var config = buildConfigs[configGuid]; - if (config != null) - { - if (removeValues != null) - foreach (var v in removeValues) - config.RemovePropertyValue(name, v); - if (addValues != null) - foreach (var v in addValues) - config.AddProperty(name, v); - } - } - public void UpdateBuildPropertyForConfig(IEnumerable configGuids, string name, - IEnumerable addValues, IEnumerable removeValues) - { - foreach (string guid in configGuids) - UpdateBuildProperty(guid, name, addValues, removeValues); - } - - internal string ShellScriptByName(string targetGuid, string name) - { - foreach (var phase in nativeTargets[targetGuid].phases) - { - var script = shellScripts[phase]; - if (script != null && script.name == name) - return script.guid; - } - return null; - } - - internal void AppendShellScriptBuildPhase(string targetGuid, string name, string shellPath, string shellScript) - { - PBXShellScriptBuildPhaseData shellScriptPhase = PBXShellScriptBuildPhaseData.Create(name, shellPath, shellScript); - - shellScripts.AddEntry(shellScriptPhase); - nativeTargets[targetGuid].phases.AddGUID(shellScriptPhase.guid); - } - - internal void AppendShellScriptBuildPhase(IEnumerable targetGuids, string name, string shellPath, string shellScript) - { - PBXShellScriptBuildPhaseData shellScriptPhase = PBXShellScriptBuildPhaseData.Create(name, shellPath, shellScript); - - shellScripts.AddEntry(shellScriptPhase); - foreach (string guid in targetGuids) - { - nativeTargets[guid].phases.AddGUID(shellScriptPhase.guid); - } - } - - public void ReadFromFile(string path) - { - ReadFromString(File.ReadAllText(path)); - } - - public void ReadFromString(string src) - { - TextReader sr = new StringReader(src); - ReadFromStream(sr); - } - - public void ReadFromStream(TextReader sr) - { - m_Data.ReadFromStream(sr); - } - - public void WriteToFile(string path) - { - File.WriteAllText(path, WriteToString()); - } - - public void WriteToStream(TextWriter sw) - { - sw.Write(WriteToString()); - } - - public string WriteToString() - { - return m_Data.WriteToString(); - } - - internal PBXProjectObjectData GetProjectInternal() - { - return project.project; - } - - /* - * Allows the setting of target attributes in the project section such as Provisioning Style and Team ID for each target - * - * The Target Attributes are structured like so: - * attributes = { - * TargetAttributes = { - * 1D6058900D05DD3D006BFB54 = { - * DevelopmentTeam = Z6SFPV59E3; - * ProvisioningStyle = Manual; - * }; - * 5623C57217FDCB0800090B9E = { - * DevelopmentTeam = Z6SFPV59E3; - * ProvisioningStyle = Manual; - * TestTargetID = 1D6058900D05DD3D006BFB54; - * }; - * }; - * }; - */ - internal void SetTargetAttributes(string key, string value) - { - PBXElementDict properties = project.project.GetPropertiesRaw(); - PBXElementDict attributes; - PBXElementDict targetAttributes; - if (properties.Contains("attributes")) - { - attributes = properties["attributes"] as PBXElementDict; - } - else - { - attributes = properties.CreateDict("attributes"); - } - - if (attributes.Contains("TargetAttributes")) - { - targetAttributes = attributes["TargetAttributes"] as PBXElementDict; - } - else - { - targetAttributes = attributes.CreateDict("TargetAttributes"); - } - - foreach (KeyValuePair target in nativeTargets.GetEntries()) { - PBXElementDict targetAttributesRaw; - if (targetAttributes.Contains(target.Key)) - { - targetAttributesRaw = targetAttributes[target.Key].AsDict(); - } - else - { - targetAttributesRaw = targetAttributes.CreateDict(target.Key); - } - targetAttributesRaw.SetString(key, value); - } - project.project.UpdateVars(); - - } - } -} // namespace UnityEditor.iOS.Xcode diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXProject.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBXProject.cs.meta deleted file mode 100644 index a3b4800..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXProject.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 09995e4480b6644ceb5cca72659e94b1 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXProjectData.cs b/Assets/Zapic/Editor/Xcode.Custom/PBXProjectData.cs deleted file mode 100644 index 1a2e02a..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXProjectData.cs +++ /dev/null @@ -1,719 +0,0 @@ -using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; -using System.IO; -using System; -#if UNITY_XCODE_API_BUILD -using UnityEditor.iOS.Xcode.PBX; -#else -using UnityEditor.iOS.Xcode.Custom.PBX; -#endif - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode -#else -namespace UnityEditor.iOS.Xcode.Custom -#endif -{ - using PBXBuildFileSection = KnownSectionBase; - using PBXFileReferenceSection = KnownSectionBase; - using PBXGroupSection = KnownSectionBase; - using PBXContainerItemProxySection = KnownSectionBase; - using PBXReferenceProxySection = KnownSectionBase; - using PBXSourcesBuildPhaseSection = KnownSectionBase; - using PBXFrameworksBuildPhaseSection= KnownSectionBase; - using PBXResourcesBuildPhaseSection = KnownSectionBase; - using PBXCopyFilesBuildPhaseSection = KnownSectionBase; - using PBXShellScriptBuildPhaseSection = KnownSectionBase; - using PBXVariantGroupSection = KnownSectionBase; - using PBXNativeTargetSection = KnownSectionBase; - using PBXTargetDependencySection = KnownSectionBase; - using XCBuildConfigurationSection = KnownSectionBase; - using XCConfigurationListSection = KnownSectionBase; - using UnknownSection = KnownSectionBase; - - internal class PBXProjectData - { - private Dictionary m_Section = null; - private PBXElementDict m_RootElements = null; - private PBXElementDict m_UnknownObjects = null; - private string m_ObjectVersion = null; - private List m_SectionOrder = null; - - private Dictionary m_UnknownSections; - private PBXBuildFileSection buildFiles = null; // use BuildFiles* methods instead of manipulating directly - private PBXFileReferenceSection fileRefs = null; // use FileRefs* methods instead of manipulating directly - private PBXGroupSection groups = null; // use Groups* methods instead of manipulating directly - public PBXContainerItemProxySection containerItems = null; - public PBXReferenceProxySection references = null; - public PBXSourcesBuildPhaseSection sources = null; - public PBXFrameworksBuildPhaseSection frameworks = null; - public PBXResourcesBuildPhaseSection resources = null; - public PBXCopyFilesBuildPhaseSection copyFiles = null; - public PBXShellScriptBuildPhaseSection shellScripts = null; - public PBXNativeTargetSection nativeTargets = null; - public PBXTargetDependencySection targetDependencies = null; - public PBXVariantGroupSection variantGroups = null; - public XCBuildConfigurationSection buildConfigs = null; - public XCConfigurationListSection buildConfigLists = null; - public PBXProjectSection project = null; - - // FIXME: create a separate PBXObject tree to represent these relationships - - // A build file can be represented only once in all *BuildPhaseSection sections, thus - // we can simplify the cache by not caring about the file extension - private Dictionary> m_FileGuidToBuildFileMap = null; - private Dictionary m_ProjectPathToFileRefMap = null; - private Dictionary m_FileRefGuidToProjectPathMap = null; - private Dictionary> m_RealPathToFileRefMap = null; - private Dictionary m_ProjectPathToGroupMap = null; - private Dictionary m_GroupGuidToProjectPathMap = null; - private Dictionary m_GuidToParentGroupMap = null; - - public PBXBuildFileData BuildFilesGet(string guid) - { - return buildFiles[guid]; - } - - // targetGuid is the guid of the target that contains the section that contains the buildFile - public void BuildFilesAdd(string targetGuid, PBXBuildFileData buildFile) - { - if (!m_FileGuidToBuildFileMap.ContainsKey(targetGuid)) - m_FileGuidToBuildFileMap[targetGuid] = new Dictionary(); - m_FileGuidToBuildFileMap[targetGuid][buildFile.fileRef] = buildFile; - buildFiles.AddEntry(buildFile); - } - - public void BuildFilesRemove(string targetGuid, string fileGuid) - { - var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid); - if (buildFile != null) - { - m_FileGuidToBuildFileMap[targetGuid].Remove(buildFile.fileRef); - buildFiles.RemoveEntry(buildFile.guid); - } - } - - public PBXBuildFileData BuildFilesGetForSourceFile(string targetGuid, string fileGuid) - { - if (!m_FileGuidToBuildFileMap.ContainsKey(targetGuid)) - return null; - if (!m_FileGuidToBuildFileMap[targetGuid].ContainsKey(fileGuid)) - return null; - return m_FileGuidToBuildFileMap[targetGuid][fileGuid]; - } - - public IEnumerable BuildFilesGetAll() - { - return buildFiles.GetObjects(); - } - - public void FileRefsAdd(string realPath, string projectPath, PBXGroupData parent, PBXFileReferenceData fileRef) - { - fileRefs.AddEntry(fileRef); - m_ProjectPathToFileRefMap.Add(projectPath, fileRef); - m_FileRefGuidToProjectPathMap.Add(fileRef.guid, projectPath); - m_RealPathToFileRefMap[fileRef.tree].Add(realPath, fileRef); // FIXME - m_GuidToParentGroupMap.Add(fileRef.guid, parent); - } - - public PBXFileReferenceData FileRefsGet(string guid) - { - return fileRefs[guid]; - } - - public PBXFileReferenceData FileRefsGetByRealPath(string path, PBXSourceTree sourceTree) - { - if (m_RealPathToFileRefMap[sourceTree].ContainsKey(path)) - return m_RealPathToFileRefMap[sourceTree][path]; - return null; - } - - public PBXFileReferenceData FileRefsGetByProjectPath(string path) - { - if (m_ProjectPathToFileRefMap.ContainsKey(path)) - return m_ProjectPathToFileRefMap[path]; - return null; - } - - public void FileRefsRemove(string guid) - { - PBXFileReferenceData fileRef = fileRefs[guid]; - fileRefs.RemoveEntry(guid); - m_ProjectPathToFileRefMap.Remove(m_FileRefGuidToProjectPathMap[guid]); - m_FileRefGuidToProjectPathMap.Remove(guid); - foreach (var tree in FileTypeUtils.AllAbsoluteSourceTrees()) - m_RealPathToFileRefMap[tree].Remove(fileRef.path); - m_GuidToParentGroupMap.Remove(guid); - } - - public PBXGroupData GroupsGet(string guid) - { - return groups[guid]; - } - - public PBXGroupData GroupsGetByChild(string childGuid) - { - return m_GuidToParentGroupMap[childGuid]; - } - - public PBXGroupData GroupsGetMainGroup() - { - return groups[project.project.mainGroup]; - } - - /// Returns the source group identified by sourceGroup. If sourceGroup is empty or null, - /// root group is returned. If no group is found, null is returned. - public PBXGroupData GroupsGetByProjectPath(string sourceGroup) - { - if (m_ProjectPathToGroupMap.ContainsKey(sourceGroup)) - return m_ProjectPathToGroupMap[sourceGroup]; - return null; - } - - public void GroupsAdd(string projectPath, PBXGroupData parent, PBXGroupData gr) - { - m_ProjectPathToGroupMap.Add(projectPath, gr); - m_GroupGuidToProjectPathMap.Add(gr.guid, projectPath); - m_GuidToParentGroupMap.Add(gr.guid, parent); - groups.AddEntry(gr); - } - - public void GroupsAddDuplicate(PBXGroupData gr) - { - groups.AddEntry(gr); - } - - public void GroupsRemove(string guid) - { - m_ProjectPathToGroupMap.Remove(m_GroupGuidToProjectPathMap[guid]); - m_GroupGuidToProjectPathMap.Remove(guid); - m_GuidToParentGroupMap.Remove(guid); - groups.RemoveEntry(guid); - } - - // This function returns a build section that a particular file should be automatically added to. - // Returns null for non-buildable file types. - // Throws an exception if the file should be added to a section, but that particular section does not exist for given target - // Note that for unknown file types we add them to resource build sections - public FileGUIDListBase BuildSectionAny(PBXNativeTargetData target, string path, bool isFolderRef) - { - string ext = Path.GetExtension(path); - var phase = FileTypeUtils.GetFileType(ext, isFolderRef); - switch (phase) { - case PBXFileType.Framework: - foreach (var guid in target.phases) - if (frameworks.HasEntry(guid)) - return frameworks[guid]; - break; - case PBXFileType.Resource: - foreach (var guid in target.phases) - if (resources.HasEntry(guid)) - return resources[guid]; - break; - case PBXFileType.Source: - foreach (var guid in target.phases) - if (sources.HasEntry(guid)) - return sources[guid]; - break; - case PBXFileType.CopyFile: - foreach (var guid in target.phases) - if (copyFiles.HasEntry(guid)) - return copyFiles[guid]; - break; - case PBXFileType.ShellScript: - foreach (var guid in target.phases) - if (shellScripts.HasEntry(guid)) - return shellScripts[guid]; - break; - case PBXFileType.NotBuildable: - return null; - } - throw new Exception(String.Format("The given path {0} does not refer to a file in a known build section", path)); - } - - public FileGUIDListBase BuildSectionAny(string sectionGuid) - { - if (frameworks.HasEntry(sectionGuid)) - return frameworks[sectionGuid]; - if (resources.HasEntry(sectionGuid)) - return resources[sectionGuid]; - if (sources.HasEntry(sectionGuid)) - return sources[sectionGuid]; - if (copyFiles.HasEntry(sectionGuid)) - return copyFiles[sectionGuid]; - if (shellScripts.HasEntry(sectionGuid)) - return shellScripts[sectionGuid]; - return null; - } - - void RefreshBuildFilesMapForBuildFileGuidList(Dictionary mapForTarget, - FileGUIDListBase list) - { - foreach (string guid in list.files) - { - var buildFile = buildFiles[guid]; - mapForTarget[buildFile.fileRef] = buildFile; - } - } - - void RefreshMapsForGroupChildren(string projectPath, string realPath, PBXSourceTree realPathTree, PBXGroupData parent) - { - var children = new List(parent.children); - foreach (string guid in children) - { - PBXFileReferenceData fileRef = fileRefs[guid]; - string pPath; - string rPath; - PBXSourceTree rTree; - - if (fileRef != null) - { - pPath = PBXPath.Combine(projectPath, fileRef.name); - PBXPath.Combine(realPath, realPathTree, fileRef.path, fileRef.tree, out rPath, out rTree); - - if (!m_ProjectPathToFileRefMap.ContainsKey(pPath)) - { - m_ProjectPathToFileRefMap.Add(pPath, fileRef); - } - if (!m_FileRefGuidToProjectPathMap.ContainsKey(fileRef.guid)) - { - m_FileRefGuidToProjectPathMap.Add(fileRef.guid, pPath); - } - if (!m_RealPathToFileRefMap[rTree].ContainsKey(rPath)) - { - m_RealPathToFileRefMap[rTree].Add(rPath, fileRef); - } - if (!m_GuidToParentGroupMap.ContainsKey(guid)) - { - m_GuidToParentGroupMap.Add(guid, parent); - } - - continue; - } - - PBXGroupData gr = groups[guid]; - if (gr != null) - { - pPath = PBXPath.Combine(projectPath, gr.name); - PBXPath.Combine(realPath, realPathTree, gr.path, gr.tree, out rPath, out rTree); - - if (!m_ProjectPathToGroupMap.ContainsKey(pPath)) - { - m_ProjectPathToGroupMap.Add(pPath, gr); - } - if (!m_GroupGuidToProjectPathMap.ContainsKey(gr.guid)) - { - m_GroupGuidToProjectPathMap.Add(gr.guid, pPath); - } - if (!m_GuidToParentGroupMap.ContainsKey(guid)) - { - m_GuidToParentGroupMap.Add(guid, parent); - } - - RefreshMapsForGroupChildren(pPath, rPath, rTree, gr); - } - } - } - - void RefreshAuxMaps() - { - foreach (var targetEntry in nativeTargets.GetEntries()) - { - var map = new Dictionary(); - foreach (string phaseGuid in targetEntry.Value.phases) - { - if (frameworks.HasEntry(phaseGuid)) - RefreshBuildFilesMapForBuildFileGuidList(map, frameworks[phaseGuid]); - if (resources.HasEntry(phaseGuid)) - RefreshBuildFilesMapForBuildFileGuidList(map, resources[phaseGuid]); - if (sources.HasEntry(phaseGuid)) - RefreshBuildFilesMapForBuildFileGuidList(map, sources[phaseGuid]); - if (copyFiles.HasEntry(phaseGuid)) - RefreshBuildFilesMapForBuildFileGuidList(map, copyFiles[phaseGuid]); - } - m_FileGuidToBuildFileMap[targetEntry.Key] = map; - } - RefreshMapsForGroupChildren("", "", PBXSourceTree.Source, GroupsGetMainGroup()); - } - - public void Clear() - { - buildFiles = new PBXBuildFileSection("PBXBuildFile"); - fileRefs = new PBXFileReferenceSection("PBXFileReference"); - groups = new PBXGroupSection("PBXGroup"); - containerItems = new PBXContainerItemProxySection("PBXContainerItemProxy"); - references = new PBXReferenceProxySection("PBXReferenceProxy"); - sources = new PBXSourcesBuildPhaseSection("PBXSourcesBuildPhase"); - frameworks = new PBXFrameworksBuildPhaseSection("PBXFrameworksBuildPhase"); - resources = new PBXResourcesBuildPhaseSection("PBXResourcesBuildPhase"); - copyFiles = new PBXCopyFilesBuildPhaseSection("PBXCopyFilesBuildPhase"); - shellScripts = new PBXShellScriptBuildPhaseSection("PBXShellScriptBuildPhase"); - nativeTargets = new PBXNativeTargetSection("PBXNativeTarget"); - targetDependencies = new PBXTargetDependencySection("PBXTargetDependency"); - variantGroups = new PBXVariantGroupSection("PBXVariantGroup"); - buildConfigs = new XCBuildConfigurationSection("XCBuildConfiguration"); - buildConfigLists = new XCConfigurationListSection("XCConfigurationList"); - project = new PBXProjectSection(); - m_UnknownSections = new Dictionary(); - - m_Section = new Dictionary - { - { "PBXBuildFile", buildFiles }, - { "PBXFileReference", fileRefs }, - { "PBXGroup", groups }, - { "PBXContainerItemProxy", containerItems }, - { "PBXReferenceProxy", references }, - { "PBXSourcesBuildPhase", sources }, - { "PBXFrameworksBuildPhase", frameworks }, - { "PBXResourcesBuildPhase", resources }, - { "PBXCopyFilesBuildPhase", copyFiles }, - { "PBXShellScriptBuildPhase", shellScripts }, - { "PBXNativeTarget", nativeTargets }, - { "PBXTargetDependency", targetDependencies }, - { "PBXVariantGroup", variantGroups }, - { "XCBuildConfiguration", buildConfigs }, - { "XCConfigurationList", buildConfigLists }, - - { "PBXProject", project }, - }; - m_RootElements = new PBXElementDict(); - m_UnknownObjects = new PBXElementDict(); - m_ObjectVersion = null; - m_SectionOrder = new List{ - "PBXBuildFile", "PBXContainerItemProxy", "PBXCopyFilesBuildPhase", "PBXFileReference", - "PBXFrameworksBuildPhase", "PBXGroup", "PBXNativeTarget", "PBXProject", "PBXReferenceProxy", - "PBXResourcesBuildPhase", "PBXShellScriptBuildPhase", "PBXSourcesBuildPhase", "PBXTargetDependency", - "PBXVariantGroup", "XCBuildConfiguration", "XCConfigurationList" - }; - m_FileGuidToBuildFileMap = new Dictionary>(); - m_ProjectPathToFileRefMap = new Dictionary(); - m_FileRefGuidToProjectPathMap = new Dictionary(); - m_RealPathToFileRefMap = new Dictionary>(); - foreach (var tree in FileTypeUtils.AllAbsoluteSourceTrees()) - m_RealPathToFileRefMap.Add(tree, new Dictionary()); - m_ProjectPathToGroupMap = new Dictionary(); - m_GroupGuidToProjectPathMap = new Dictionary(); - m_GuidToParentGroupMap = new Dictionary(); - } - - private void BuildCommentMapForBuildFiles(GUIDToCommentMap comments, List guids, string sectName) - { - foreach (var guid in guids) - { - var buildFile = BuildFilesGet(guid); - if (buildFile != null) - { - var fileRef = FileRefsGet(buildFile.fileRef); - if (fileRef != null) - comments.Add(guid, String.Format("{0} in {1}", fileRef.name, sectName)); - else - { - var reference = references[buildFile.fileRef]; - if (reference != null) - comments.Add(guid, String.Format("{0} in {1}", reference.path, sectName)); - } - } - } - } - - private GUIDToCommentMap BuildCommentMap() - { - GUIDToCommentMap comments = new GUIDToCommentMap(); - - // buildFiles are handled below - // filerefs are handled below - foreach (var e in groups.GetObjects()) - comments.Add(e.guid, e.name); - foreach (var e in containerItems.GetObjects()) - comments.Add(e.guid, "PBXContainerItemProxy"); - foreach (var e in references.GetObjects()) - comments.Add(e.guid, e.path); - foreach (var e in sources.GetObjects()) - { - comments.Add(e.guid, "Sources"); - BuildCommentMapForBuildFiles(comments, e.files, "Sources"); - } - foreach (var e in resources.GetObjects()) - { - comments.Add(e.guid, "Resources"); - BuildCommentMapForBuildFiles(comments, e.files, "Resources"); - } - foreach (var e in frameworks.GetObjects()) - { - comments.Add(e.guid, "Frameworks"); - BuildCommentMapForBuildFiles(comments, e.files, "Frameworks"); - } - foreach (var e in copyFiles.GetObjects()) - { - string sectName = e.name; - if (sectName == null) - sectName = "CopyFiles"; - comments.Add(e.guid, sectName); - BuildCommentMapForBuildFiles(comments, e.files, sectName); - } - foreach (var e in shellScripts.GetObjects()) - comments.Add(e.guid, "ShellScript"); - foreach (var e in targetDependencies.GetObjects()) - comments.Add(e.guid, "PBXTargetDependency"); - foreach (var e in nativeTargets.GetObjects()) - { - comments.Add(e.guid, e.name); - comments.Add(e.buildConfigList, String.Format("Build configuration list for PBXNativeTarget \"{0}\"", e.name)); - } - foreach (var e in variantGroups.GetObjects()) - comments.Add(e.guid, e.name); - foreach (var e in buildConfigs.GetObjects()) - comments.Add(e.guid, e.name); - foreach (var e in project.GetObjects()) - { - comments.Add(e.guid, "Project object"); - comments.Add(e.buildConfigList, "Build configuration list for PBXProject \"Unity-iPhone\""); // FIXME: project name is hardcoded - } - foreach (var e in fileRefs.GetObjects()) - comments.Add(e.guid, e.name); - if (m_RootElements.Contains("rootObject") && m_RootElements["rootObject"] is PBXElementString) - comments.Add(m_RootElements["rootObject"].AsString(), "Project object"); - - return comments; - } - - private static PBXElementDict ParseContent(string content) - { - TokenList tokens = Lexer.Tokenize(content); - var parser = new Parser(tokens); - TreeAST ast = parser.ParseTree(); - return Serializer.ParseTreeAST(ast, tokens, content); - } - - public void ReadFromStream(TextReader sr) - { - Clear(); - m_RootElements = ParseContent(sr.ReadToEnd()); - - if (!m_RootElements.Contains("objects")) - throw new Exception("Invalid PBX project file: no objects element"); - - var objects = m_RootElements["objects"].AsDict(); - m_RootElements.Remove("objects"); - m_RootElements.SetString("objects", "OBJMARKER"); - - if (m_RootElements.Contains("objectVersion")) - { - m_ObjectVersion = m_RootElements["objectVersion"].AsString(); - m_RootElements.Remove("objectVersion"); - } - - var allGuids = new List(); - string prevSectionName = null; - foreach (var kv in objects.values) - { - allGuids.Add(kv.Key); - var el = kv.Value; - - if (!(el is PBXElementDict) || !el.AsDict().Contains("isa")) - { - m_UnknownObjects.values.Add(kv.Key, el); - continue; - } - var dict = el.AsDict(); - var sectionName = dict["isa"].AsString(); - - if (m_Section.ContainsKey(sectionName)) - { - var section = m_Section[sectionName]; - section.AddObject(kv.Key, dict); - } - else - { - UnknownSection section; - if (m_UnknownSections.ContainsKey(sectionName)) - section = m_UnknownSections[sectionName]; - else - { - section = new UnknownSection(sectionName); - m_UnknownSections.Add(sectionName, section); - } - section.AddObject(kv.Key, dict); - - // update section order - if (!m_SectionOrder.Contains(sectionName)) - { - int pos = 0; - if (prevSectionName != null) - { - // this never fails, because we already added any previous unknown sections - // to m_SectionOrder - pos = m_SectionOrder.FindIndex(x => x == prevSectionName); - pos += 1; - } - m_SectionOrder.Insert(pos, sectionName); - } - } - prevSectionName = sectionName; - } - RepairStructure(allGuids); - RefreshAuxMaps(); - } - - - public string WriteToString() - { - var commentMap = BuildCommentMap(); - var emptyChecker = new PropertyCommentChecker(); - var emptyCommentMap = new GUIDToCommentMap(); - - // since we need to add custom comments, the serialization is much more complex - StringBuilder objectsSb = new StringBuilder(); - if (m_ObjectVersion != null) // objectVersion comes right before objects - objectsSb.AppendFormat("objectVersion = {0};\n\t", m_ObjectVersion); - objectsSb.Append("objects = {"); - foreach (string sectionName in m_SectionOrder) - { - if (m_Section.ContainsKey(sectionName)) - m_Section[sectionName].WriteSection(objectsSb, commentMap); - else if (m_UnknownSections.ContainsKey(sectionName)) - m_UnknownSections[sectionName].WriteSection(objectsSb, commentMap); - } - foreach (var kv in m_UnknownObjects.values) - Serializer.WriteDictKeyValue(objectsSb, kv.Key, kv.Value, 2, false, emptyChecker, emptyCommentMap); - objectsSb.Append("\n\t};"); - - StringBuilder contentSb = new StringBuilder(); - contentSb.Append("// !$*UTF8*$!\n"); - Serializer.WriteDict(contentSb, m_RootElements, 0, false, - new PropertyCommentChecker(new string[]{"rootObject/*"}), commentMap); - contentSb.Append("\n"); - string content = contentSb.ToString(); - - content = content.Replace("objects = OBJMARKER;", objectsSb.ToString()); - return content; - } - - // This method walks the project structure and removes invalid entries. - void RepairStructure(List allGuids) - { - var guidSet = new Dictionary(); // emulate HashSet on .Net 2.0 - foreach (var guid in allGuids) - guidSet.Add(guid, false); - - while (RepairStructureImpl(guidSet) == true) - ; - } - - /* Iterates the given guid list and removes all guids that are not in allGuids dictionary. - */ - static void RemoveMissingGuidsFromGuidList(PBX.GUIDList guidList, Dictionary allGuids) - { - List guidsToRemove = null; - foreach (var guid in guidList) - { - if (!allGuids.ContainsKey(guid)) - { - if (guidsToRemove == null) - guidsToRemove = new List(); - guidsToRemove.Add(guid); - } - } - if (guidsToRemove != null) - { - foreach (var guid in guidsToRemove) - guidList.RemoveGUID(guid); - } - } - - /* Removes objects from the given @a section for which @a checker returns true. - Also removes the guids of the removed elements from allGuids dictionary. - Returns true if any objects were removed. - */ - static bool RemoveObjectsFromSection(KnownSectionBase section, - Dictionary allGuids, - Func checker) where T : PBXObjectData, new() - { - List guidsToRemove = null; - foreach (var kv in section.GetEntries()) - { - if (checker(kv.Value)) - { - if (guidsToRemove == null) - guidsToRemove = new List(); - guidsToRemove.Add(kv.Key); - } - } - if (guidsToRemove != null) - { - foreach (var guid in guidsToRemove) - { - section.RemoveEntry(guid); - allGuids.Remove(guid); - } - return true; - } - return false; - } - - // Returns true if changes were done and one should call RepairStructureImpl again - bool RepairStructureImpl(Dictionary allGuids) - { - bool changed = false; - - // PBXBuildFile - changed |= RemoveObjectsFromSection(buildFiles, allGuids, - o => (o.fileRef == null || !allGuids.ContainsKey(o.fileRef))); - // PBXFileReference / fileRefs not cleaned - - // PBXGroup - changed |= RemoveObjectsFromSection(groups, allGuids, o => o.children == null); - foreach (var o in groups.GetObjects()) - RemoveMissingGuidsFromGuidList(o.children, allGuids); - - // PBXContainerItem / containerItems not cleaned - // PBXReferenceProxy / references not cleaned - - // PBXSourcesBuildPhase - changed |= RemoveObjectsFromSection(sources, allGuids, o => o.files == null); - foreach (var o in sources.GetObjects()) - RemoveMissingGuidsFromGuidList(o.files, allGuids); - // PBXFrameworksBuildPhase - changed |= RemoveObjectsFromSection(frameworks, allGuids, o => o.files == null); - foreach (var o in frameworks.GetObjects()) - RemoveMissingGuidsFromGuidList(o.files, allGuids); - // PBXResourcesBuildPhase - changed |= RemoveObjectsFromSection(resources, allGuids, o => o.files == null); - foreach (var o in resources.GetObjects()) - RemoveMissingGuidsFromGuidList(o.files, allGuids); - // PBXCopyFilesBuildPhase - changed |= RemoveObjectsFromSection(copyFiles, allGuids, o => o.files == null); - foreach (var o in copyFiles.GetObjects()) - RemoveMissingGuidsFromGuidList(o.files, allGuids); - // PBXShellScriptsBuildPhase - changed |= RemoveObjectsFromSection(shellScripts, allGuids, o => o.files == null); - foreach (var o in shellScripts.GetObjects()) - RemoveMissingGuidsFromGuidList(o.files, allGuids); - - // PBXNativeTarget - changed |= RemoveObjectsFromSection(nativeTargets, allGuids, o => o.phases == null); - foreach (var o in nativeTargets.GetObjects()) - RemoveMissingGuidsFromGuidList(o.phases, allGuids); - - // PBXTargetDependency / targetDependencies not cleaned - - // PBXVariantGroup - changed |= RemoveObjectsFromSection(variantGroups, allGuids, o => o.children == null); - foreach (var o in variantGroups.GetObjects()) - RemoveMissingGuidsFromGuidList(o.children, allGuids); - - // XCBuildConfiguration / buildConfigs not cleaned - - // XCConfigurationList - changed |= RemoveObjectsFromSection(buildConfigLists, allGuids, o => o.buildConfigs == null); - foreach (var o in buildConfigLists.GetObjects()) - RemoveMissingGuidsFromGuidList(o.buildConfigs, allGuids); - - // PBXProject project not cleaned - return changed; - } - } - -} // namespace UnityEditor.iOS.Xcode - diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXProjectData.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBXProjectData.cs.meta deleted file mode 100644 index 6d96233..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXProjectData.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 94c2f7bc0454a4275a7ba5dd794e51b0 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXProjectExtensions.cs b/Assets/Zapic/Editor/Xcode.Custom/PBXProjectExtensions.cs deleted file mode 100644 index 6def8fe..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXProjectExtensions.cs +++ /dev/null @@ -1,423 +0,0 @@ -using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; -using System.IO; -using System; -#if UNITY_XCODE_API_BUILD -using UnityEditor.iOS.Xcode.PBX; -#else -using UnityEditor.iOS.Xcode.Custom.PBX; -#endif - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode.Extensions -#else -namespace UnityEditor.iOS.Xcode.Custom.Extensions -#endif -{ - /* This class implements a number of static methods for performing common tasks - on xcode projects. - TODO: Make sure enough stuff is exposed so that it's possible to perform the tasks - without using internal APIs - */ - public static class PBXProjectExtensions - { - // Create a wrapper class so that collection initializers work and we can have a - // compact notation. Note that we can't use Dictionary because the keys may be duplicate - internal class FlagList : List> - { - public void Add(string flag, string value) - { - Add(new KeyValuePair(flag, value)); - } - } - - internal static FlagList appExtensionReleaseBuildFlags = new FlagList - { - // { "INFOPLIST_FILE", }, - { "LD_RUNPATH_SEARCH_PATHS", "$(inherited)" }, - { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks" }, - { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/../../Frameworks" }, - // { "PRODUCT_BUNDLE_IDENTIFIER", "" }, - { "PRODUCT_NAME", "$(TARGET_NAME)" }, - { "SKIP_INSTALL", "YES" }, - }; - - internal static FlagList appExtensionDebugBuildFlags = new FlagList - { - // { "INFOPLIST_FILE", }, - { "LD_RUNPATH_SEARCH_PATHS", "$(inherited)" }, - { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks" }, - { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/../../Frameworks" }, - // { "PRODUCT_BUNDLE_IDENTIFIER", "" }, - { "PRODUCT_NAME", "$(TARGET_NAME)" }, - { "SKIP_INSTALL", "YES" }, - }; - - internal static FlagList watchExtensionReleaseBuildFlags = new FlagList - { - { "ASSETCATALOG_COMPILER_COMPLICATION_NAME", "Complication" }, - { "CLANG_ANALYZER_NONNULL", "YES" }, - { "CLANG_WARN_DOCUMENTATION_COMMENTS", "YES" }, - { "CLANG_WARN_INFINITE_RECURSION", "YES" }, - { "CLANG_WARN_SUSPICIOUS_MOVE", "YES" }, - { "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym" }, - { "GCC_NO_COMMON_BLOCKS", "YES" }, - //{ "INFOPLIST_FILE", "" }, - { "LD_RUNPATH_SEARCH_PATHS", "$(inherited)" }, - { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks" }, - { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/../../Frameworks" }, - // { "PRODUCT_BUNDLE_IDENTIFIER", "" }, - { "PRODUCT_NAME", "${TARGET_NAME}" }, - { "SDKROOT", "watchos" }, - { "SKIP_INSTALL", "YES" }, - { "TARGETED_DEVICE_FAMILY", "4" }, - { "WATCHOS_DEPLOYMENT_TARGET", "3.1" }, - // the following are needed to override project settings in Unity Xcode project - { "ARCHS", "$(ARCHS_STANDARD)" }, - { "SUPPORTED_PLATFORMS", "watchos" }, - { "SUPPORTED_PLATFORMS", "watchsimulator" }, - }; - - internal static FlagList watchExtensionDebugBuildFlags = new FlagList - { - { "ASSETCATALOG_COMPILER_COMPLICATION_NAME", "Complication" }, - { "CLANG_ANALYZER_NONNULL", "YES" }, - { "CLANG_WARN_DOCUMENTATION_COMMENTS", "YES" }, - { "CLANG_WARN_INFINITE_RECURSION", "YES" }, - { "CLANG_WARN_SUSPICIOUS_MOVE", "YES" }, - { "DEBUG_INFORMATION_FORMAT", "dwarf" }, - { "ENABLE_TESTABILITY", "YES" }, - { "GCC_NO_COMMON_BLOCKS", "YES" }, - // { "INFOPLIST_FILE", "" }, - { "LD_RUNPATH_SEARCH_PATHS", "$(inherited)" }, - { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks" }, - { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/../../Frameworks" }, - // { "PRODUCT_BUNDLE_IDENTIFIER", "" }, - { "PRODUCT_NAME", "${TARGET_NAME}" }, - { "SDKROOT", "watchos" }, - { "SKIP_INSTALL", "YES" }, - { "TARGETED_DEVICE_FAMILY", "4" }, - { "WATCHOS_DEPLOYMENT_TARGET", "3.1" }, - // the following are needed to override project settings in Unity Xcode project - { "ARCHS", "$(ARCHS_STANDARD)" }, - { "SUPPORTED_PLATFORMS", "watchos" }, - { "SUPPORTED_PLATFORMS", "watchsimulator" }, - }; - - internal static FlagList watchAppReleaseBuildFlags = new FlagList - { - { "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon" }, - { "CLANG_ANALYZER_NONNULL", "YES" }, - { "CLANG_WARN_DOCUMENTATION_COMMENTS", "YES" }, - { "CLANG_WARN_INFINITE_RECURSION", "YES" }, - { "CLANG_WARN_SUSPICIOUS_MOVE", "YES" }, - { "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym" }, - { "GCC_NO_COMMON_BLOCKS", "YES" }, - //{ "IBSC_MODULE", "the extension target name with ' ' replaced with '_'" }, - //{ "INFOPLIST_FILE", "" }, - //{ "PRODUCT_BUNDLE_IDENTIFIER", "" }, - { "PRODUCT_NAME", "$(TARGET_NAME)" }, - { "SDKROOT", "watchos" }, - { "SKIP_INSTALL", "YES" }, - { "TARGETED_DEVICE_FAMILY", "4" }, - { "WATCHOS_DEPLOYMENT_TARGET", "3.1" }, - // the following are needed to override project settings in Unity Xcode project - { "ARCHS", "$(ARCHS_STANDARD)" }, - { "SUPPORTED_PLATFORMS", "watchos" }, - { "SUPPORTED_PLATFORMS", "watchsimulator" }, - }; - - internal static FlagList watchAppDebugBuildFlags = new FlagList - { - { "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon" }, - { "CLANG_ANALYZER_NONNULL", "YES" }, - { "CLANG_WARN_DOCUMENTATION_COMMENTS", "YES" }, - { "CLANG_WARN_INFINITE_RECURSION", "YES" }, - { "CLANG_WARN_SUSPICIOUS_MOVE", "YES" }, - { "DEBUG_INFORMATION_FORMAT", "dwarf" }, - { "ENABLE_TESTABILITY", "YES" }, - { "GCC_NO_COMMON_BLOCKS", "YES" }, - //{ "IBSC_MODULE", "the extension target name with ' ' replaced with '_'" }, - //{ "INFOPLIST_FILE", "" }, - //{ "PRODUCT_BUNDLE_IDENTIFIER", "" }, - { "PRODUCT_NAME", "$(TARGET_NAME)" }, - { "SDKROOT", "watchos" }, - { "SKIP_INSTALL", "YES" }, - { "TARGETED_DEVICE_FAMILY", "4" }, - { "WATCHOS_DEPLOYMENT_TARGET", "3.1" }, - // the following are needed to override project settings in Unity Xcode project - { "ARCHS", "$(ARCHS_STANDARD)" }, - { "SUPPORTED_PLATFORMS", "watchos" }, - { "SUPPORTED_PLATFORMS", "watchsimulator" }, - }; - - static void SetBuildFlagsFromDict(this PBXProject proj, string configGuid, IEnumerable> data) - { - foreach (var kv in data) - proj.AddBuildPropertyForConfig(configGuid, kv.Key, kv.Value); - } - - internal static void SetDefaultAppExtensionReleaseBuildFlags(this PBXProject proj, string configGuid) - { - SetBuildFlagsFromDict(proj, configGuid, appExtensionReleaseBuildFlags); - } - - internal static void SetDefaultAppExtensionDebugBuildFlags(this PBXProject proj, string configGuid) - { - SetBuildFlagsFromDict(proj, configGuid, appExtensionDebugBuildFlags); - } - - internal static void SetDefaultWatchExtensionReleaseBuildFlags(this PBXProject proj, string configGuid) - { - SetBuildFlagsFromDict(proj, configGuid, watchExtensionReleaseBuildFlags); - } - - internal static void SetDefaultWatchExtensionDebugBuildFlags(this PBXProject proj, string configGuid) - { - SetBuildFlagsFromDict(proj, configGuid, watchExtensionDebugBuildFlags); - } - - internal static void SetDefaultWatchAppReleaseBuildFlags(this PBXProject proj, string configGuid) - { - SetBuildFlagsFromDict(proj, configGuid, watchAppReleaseBuildFlags); - } - - internal static void SetDefaultWatchAppDebugBuildFlags(this PBXProject proj, string configGuid) - { - SetBuildFlagsFromDict(proj, configGuid, watchAppDebugBuildFlags); - } - - /// - /// Creates an app extension. - /// - /// The GUID of the new target. - /// A project passed as this argument. - /// The GUID of the main target to link the app to. - /// The name of the app extension. - /// The bundle ID of the app extension. The bundle ID must be - /// prefixed with the parent app bundle ID. - /// Path to the app extension Info.plist document. - public static string AddAppExtension(this PBXProject proj, string mainTargetGuid, - string name, string bundleId, string infoPlistPath) - { - string ext = ".appex"; - var newTargetGuid = proj.AddTarget(name, ext, "com.apple.product-type.app-extension"); - - foreach (var configName in proj.BuildConfigNames()) - { - var configGuid = proj.BuildConfigByName(newTargetGuid, configName); - if (configName.Contains("Debug")) - SetDefaultAppExtensionDebugBuildFlags(proj, configGuid); - else - SetDefaultAppExtensionReleaseBuildFlags(proj, configGuid); - proj.SetBuildPropertyForConfig(configGuid, "INFOPLIST_FILE", infoPlistPath); - proj.SetBuildPropertyForConfig(configGuid, "PRODUCT_BUNDLE_IDENTIFIER", bundleId); - } - - proj.AddSourcesBuildPhase(newTargetGuid); - proj.AddResourcesBuildPhase(newTargetGuid); - proj.AddFrameworksBuildPhase(newTargetGuid); - string copyFilesPhaseGuid = proj.AddCopyFilesBuildPhase(mainTargetGuid, "Embed App Extensions", "", "13"); - proj.AddFileToBuildSection(mainTargetGuid, copyFilesPhaseGuid, proj.GetTargetProductFileRef(newTargetGuid)); - - proj.AddTargetDependency(mainTargetGuid, newTargetGuid); - - return newTargetGuid; - } - - /// - /// Creates a watch application. - /// - /// The GUID of the new target. - /// A project passed as this argument. - /// The GUID of the main target to link the watch app to. - /// The GUID of watch extension as returned by [[AddWatchExtension()]]. - /// The name of the watch app. It must the same as the name of the watch extension. - /// The bundle ID of the watch app. - /// Path to the watch app Info.plist document. - public static string AddWatchApp(this PBXProject proj, string mainTargetGuid, string watchExtensionTargetGuid, - string name, string bundleId, string infoPlistPath) - { - var newTargetGuid = proj.AddTarget(name, ".app", "com.apple.product-type.application.watchapp2"); - - var isbcModuleName = proj.nativeTargets[watchExtensionTargetGuid].name.Replace(" ", "_"); - - foreach (var configName in proj.BuildConfigNames()) - { - var configGuid = proj.BuildConfigByName(newTargetGuid, configName); - if (configName.Contains("Debug")) - SetDefaultWatchAppDebugBuildFlags(proj, configGuid); - else - SetDefaultWatchAppReleaseBuildFlags(proj, configGuid); - proj.SetBuildPropertyForConfig(configGuid, "PRODUCT_BUNDLE_IDENTIFIER", bundleId); - proj.SetBuildPropertyForConfig(configGuid, "INFOPLIST_FILE", infoPlistPath); - proj.SetBuildPropertyForConfig(configGuid, "IBSC_MODULE", isbcModuleName); - } - - proj.AddResourcesBuildPhase(newTargetGuid); - string copyFilesGuid = proj.AddCopyFilesBuildPhase(newTargetGuid, "Embed App Extensions", "", "13"); - proj.AddFileToBuildSection(newTargetGuid, copyFilesGuid, proj.GetTargetProductFileRef(watchExtensionTargetGuid)); - - string copyWatchFilesGuid = proj.AddCopyFilesBuildPhase(mainTargetGuid, "Embed Watch Content", "$(CONTENTS_FOLDER_PATH)/Watch", "16"); - proj.AddFileToBuildSection(mainTargetGuid, copyWatchFilesGuid, proj.GetTargetProductFileRef(newTargetGuid)); - - proj.AddTargetDependency(newTargetGuid, watchExtensionTargetGuid); - proj.AddTargetDependency(mainTargetGuid, newTargetGuid); - - return newTargetGuid; - } - - /// - /// Creates a watch extension. - /// - /// The GUID of the new target. - /// A project passed as this argument. - /// The GUID of the main target to link the watch extension to. - /// The name of the watch extension. - /// The bundle ID of the watch extension. The bundle ID must be - /// prefixed with the parent watch app bundle ID. - /// Path to the watch extension Info.plist document. - public static string AddWatchExtension(this PBXProject proj, string mainTarget, - string name, string bundleId, string infoPlistPath) - { - var newTargetGuid = proj.AddTarget(name, ".appex", "com.apple.product-type.watchkit2-extension"); - - foreach (var configName in proj.BuildConfigNames()) - { - var configGuid = proj.BuildConfigByName(newTargetGuid, configName); - if (configName.Contains("Debug")) - SetDefaultWatchExtensionDebugBuildFlags(proj, configGuid); - else - SetDefaultWatchExtensionReleaseBuildFlags(proj, configGuid); - proj.SetBuildPropertyForConfig(configGuid, "PRODUCT_BUNDLE_IDENTIFIER", bundleId); - proj.SetBuildPropertyForConfig(configGuid, "INFOPLIST_FILE", infoPlistPath); - } - - proj.AddSourcesBuildPhase(newTargetGuid); - proj.AddResourcesBuildPhase(newTargetGuid); - proj.AddFrameworksBuildPhase(newTargetGuid); - - return newTargetGuid; - } - - /// - /// Adds an external project dependency to the project. - /// - /// The path to the external Xcode project (the .xcodeproj file). - /// The project path to the new project. - /// The source tree the path is relative to. The [[PBXSourceTree.Group]] tree is not supported. - internal static void AddExternalProjectDependency(this PBXProject proj, string path, string projectPath, PBXSourceTree sourceTree) - { - if (sourceTree == PBXSourceTree.Group) - throw new Exception("sourceTree must not be PBXSourceTree.Group"); - path = PBXPath.FixSlashes(path); - projectPath = PBXPath.FixSlashes(projectPath); - - // note: we are duplicating products group for the project reference. Otherwise Xcode crashes. - PBXGroupData productGroup = PBXGroupData.CreateRelative("Products"); - proj.GroupsAddDuplicate(productGroup); // don't use GroupsAdd here - - PBXFileReferenceData fileRef = PBXFileReferenceData.CreateFromFile(path, Path.GetFileName(projectPath), - sourceTree); - proj.FileRefsAdd(path, projectPath, null, fileRef); - proj.CreateSourceGroup(PBXPath.GetDirectory(projectPath)).children.AddGUID(fileRef.guid); - - proj.project.project.AddReference(productGroup.guid, fileRef.guid); - } - - /** This function must be called only after the project the library is in has - been added as a dependency via AddExternalProjectDependency. projectPath must be - the same as the 'path' parameter passed to the AddExternalProjectDependency. - remoteFileGuid must be the guid of the referenced file as specified in - PBXFileReference section of the external project - - TODO: what. is remoteInfo entry in PBXContainerItemProxy? Is in referenced project name or - referenced library name without extension? - */ - internal static void AddExternalLibraryDependency(this PBXProject proj, string targetGuid, string filename, string remoteFileGuid, string projectPath, - string remoteInfo) - { - PBXNativeTargetData target = proj.nativeTargets[targetGuid]; - filename = PBXPath.FixSlashes(filename); - projectPath = PBXPath.FixSlashes(projectPath); - - // find the products group to put the new library in - string projectGuid = proj.FindFileGuidByRealPath(projectPath); - if (projectGuid == null) - throw new Exception("No such project"); - - string productsGroupGuid = null; - foreach (var projRef in proj.project.project.projectReferences) - { - if (projRef.projectRef == projectGuid) - { - productsGroupGuid = projRef.group; - break; - } - } - - if (productsGroupGuid == null) - throw new Exception("Malformed project: no project in project references"); - - PBXGroupData productGroup = proj.GroupsGet(productsGroupGuid); - - // verify file extension - string ext = Path.GetExtension(filename); - if (!FileTypeUtils.IsBuildableFile(ext)) - throw new Exception("Wrong file extension"); - - // create ContainerItemProxy object - var container = PBXContainerItemProxyData.Create(projectGuid, "2", remoteFileGuid, remoteInfo); - proj.containerItems.AddEntry(container); - - // create a reference and build file for the library - string typeName = FileTypeUtils.GetTypeName(ext); - - var libRef = PBXReferenceProxyData.Create(filename, typeName, container.guid, "BUILT_PRODUCTS_DIR"); - proj.references.AddEntry(libRef); - PBXBuildFileData libBuildFile = PBXBuildFileData.CreateFromFile(libRef.guid, false, null); - proj.BuildFilesAdd(targetGuid, libBuildFile); - proj.BuildSectionAny(target, ext, false).files.AddGUID(libBuildFile.guid); - - // add to products folder - productGroup.children.AddGUID(libRef.guid); - } - - /// - /// Configures file for embed framework section for the given native target. - /// - /// This function also internally calls proj.AddFileToBuild(targetGuid, fileGuid) - /// to ensure that the framework is added to the list of linked frameworks. - /// - /// If the target has already configured the given file as embedded framework, this function has - /// no effect. - /// - /// A projects containing multiple native targets, a single file or folder reference can be - /// configured to be built in all, some or none of the targets. The file or folder reference is - /// added to appropriate build section depending on the file extension. - /// - /// A project passed as this argument. - /// The GUID of the target as returned by [[TargetGuidByName()]]. - /// The file GUID returned by [[AddFile]] or [[AddFolderReference]]. - public static void AddFileToEmbedFrameworks(this PBXProject proj, string targetGuid, string fileGuid) - { - PBXNativeTargetData target = proj.nativeTargets[targetGuid]; - - var phaseGuid = proj.AddCopyFilesBuildPhase(targetGuid, "Embed Frameworks", "", "10"); - var phase = proj.copyFiles[phaseGuid]; - var frameworkEmbedFileData = proj.FindFrameworkByFileGuid(phase, fileGuid); - - if (frameworkEmbedFileData == null) - { - frameworkEmbedFileData = PBXBuildFileData.CreateFromFile(fileGuid, false, null); - proj.BuildFilesAdd(targetGuid, frameworkEmbedFileData); - - phase.files.AddGUID(frameworkEmbedFileData.guid); - } - - frameworkEmbedFileData.codeSignOnCopy = true; - frameworkEmbedFileData.removeHeadersOnCopy = true; - } - } -} // namespace UnityEditor.iOS.Xcode diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBXProjectExtensions.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PBXProjectExtensions.cs.meta deleted file mode 100644 index 9ce9fbb..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PBXProjectExtensions.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 2a1250cb380d64a87a123e4e711334f9 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/PlistParser.cs b/Assets/Zapic/Editor/Xcode.Custom/PlistParser.cs deleted file mode 100644 index 44c7dde..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PlistParser.cs +++ /dev/null @@ -1,423 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml; -using System.Xml.Linq; -using System.Xml.XPath; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode -#else -namespace UnityEditor.iOS.Xcode.Custom -#endif -{ - - public class PlistElement - { - protected PlistElement() {} - - // convenience methods - public string AsString() { return ((PlistElementString)this).value; } - public int AsInteger() { return ((PlistElementInteger)this).value; } - public bool AsBoolean() { return ((PlistElementBoolean)this).value; } - public PlistElementArray AsArray() { return (PlistElementArray)this; } - public PlistElementDict AsDict() { return (PlistElementDict)this; } - public float AsReal() { return ((PlistElementReal)this).value; } - public DateTime AsDate() { return ((PlistElementDate)this).value; } - - public PlistElement this[string key] - { - get { return AsDict()[key]; } - set { AsDict()[key] = value; } - } - } - - public class PlistElementString : PlistElement - { - public PlistElementString(string v) { value = v; } - - public string value; - } - - public class PlistElementInteger : PlistElement - { - public PlistElementInteger(int v) { value = v; } - - public int value; - } - - public class PlistElementReal : PlistElement - { - public PlistElementReal(float v) { value = v; } - - public float value; - } - - public class PlistElementBoolean : PlistElement - { - public PlistElementBoolean(bool v) { value = v; } - - public bool value; - } - - public class PlistElementDate : PlistElement - { - public PlistElementDate(DateTime date) { value = date; } - - public DateTime value; - } - - public class PlistElementDict : PlistElement - { - public PlistElementDict() : base() {} - - private SortedDictionary m_PrivateValue = new SortedDictionary(); - public IDictionary values { get { return m_PrivateValue; }} - - new public PlistElement this[string key] - { - get { - if (values.ContainsKey(key)) - return values[key]; - return null; - } - set { this.values[key] = value; } - } - - - // convenience methods - public void SetInteger(string key, int val) - { - values[key] = new PlistElementInteger(val); - } - - public void SetString(string key, string val) - { - values[key] = new PlistElementString(val); - } - - public void SetBoolean(string key, bool val) - { - values[key] = new PlistElementBoolean(val); - } - - public void SetDate(string key, DateTime val) - { - values[key] = new PlistElementDate(val); - } - - public void SetReal(string key, float val) - { - values[key] = new PlistElementReal(val); - } - - public PlistElementArray CreateArray(string key) - { - var v = new PlistElementArray(); - values[key] = v; - return v; - } - - public PlistElementDict CreateDict(string key) - { - var v = new PlistElementDict(); - values[key] = v; - return v; - } - } - - public class PlistElementArray : PlistElement - { - public PlistElementArray() : base() {} - public List values = new List(); - - // convenience methods - public void AddString(string val) - { - values.Add(new PlistElementString(val)); - } - - public void AddInteger(int val) - { - values.Add(new PlistElementInteger(val)); - } - - public void AddBoolean(bool val) - { - values.Add(new PlistElementBoolean(val)); - } - - public void AddDate(DateTime val) - { - values.Add(new PlistElementDate(val)); - } - - public void AddReal(float val) - { - values.Add(new PlistElementReal(val)); - } - - public PlistElementArray AddArray() - { - var v = new PlistElementArray(); - values.Add(v); - return v; - } - - public PlistElementDict AddDict() - { - var v = new PlistElementDict(); - values.Add(v); - return v; - } - } - - public class PlistDocument - { - public PlistElementDict root; - public string version; - - private XDocumentType documentType; - - public PlistDocument() - { - root = new PlistElementDict(); - version = "1.0"; - } - - // Parses a string that contains a XML file. No validation is done. - internal static XDocument ParseXmlNoDtd(string text) - { - XmlReaderSettings settings = new XmlReaderSettings(); - settings.ProhibitDtd = false; - settings.XmlResolver = null; // prevent DTD download - - XmlReader xmlReader = XmlReader.Create(new StringReader(text), settings); - return XDocument.Load(xmlReader); - } - - // LINQ serializes XML DTD declaration with an explicit empty 'internal subset' - // (a pair of square brackets at the end of Doctype declaration). - // Even though this is valid XML, XCode does not like it, hence this workaround. - internal static string CleanDtdToString(XDocument doc, XDocumentType documentType) - { - // LINQ does not support changing the DTD of existing XDocument instances, - // so we create a dummy document for printing of the Doctype declaration. - // A single dummy element is added to force LINQ not to omit the declaration. - // Also, utf-8 encoding is forced since this is the encoding we use when writing to file in UpdateInfoPlist. - if (documentType != null) - { - XDocument tmpDoc = - new XDocument(new XDeclaration("1.0", "utf-8", null), - new XDocumentType(documentType.Name, documentType.PublicId, documentType.SystemId, null), - new XElement(doc.Root.Name)); - return "" + tmpDoc.Declaration + "\n" + tmpDoc.DocumentType + "\n" + doc.Root + "\n"; - } - else - { - XDocument tmpDoc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement(doc.Root.Name)); - return "" + tmpDoc.Declaration + Environment.NewLine + doc.Root + "\n"; - } - } - - internal static string CleanDtdToString(XDocument doc) - { - return CleanDtdToString(doc, doc.DocumentType); - } - - private static string GetText(XElement xml) - { - return String.Join("", xml.Nodes().OfType().Select(x => x.Value).ToArray()); - } - - private static PlistElement ReadElement(XElement xml) - { - switch (xml.Name.LocalName) - { - case "dict": - { - List children = xml.Elements().ToList(); - var el = new PlistElementDict(); - - if (children.Count % 2 == 1) - throw new Exception("Malformed plist file"); - - for (int i = 0; i < children.Count - 1; i++) - { - if (children[i].Name != "key") - throw new Exception("Malformed plist file. Found '"+children[i].Name+"' where 'key' was expected."); - string key = GetText(children[i]).Trim(); - var newChild = ReadElement(children[i+1]); - if (newChild != null) - { - i++; - el[key] = newChild; - } - } - return el; - } - case "array": - { - List children = xml.Elements().ToList(); - var el = new PlistElementArray(); - - foreach (var childXml in children) - { - var newChild = ReadElement(childXml); - if (newChild != null) - el.values.Add(newChild); - } - return el; - } - case "string": - return new PlistElementString(GetText(xml)); - case "integer": - { - int r; - if (int.TryParse(GetText(xml), out r)) - return new PlistElementInteger(r); - return null; - } - case "real": - { - float f; - if (float.TryParse(GetText(xml), out f)) - return new PlistElementReal(f); - return null; - } - case "date": - { - DateTime date; - if (DateTime.TryParse(GetText(xml), out date)) - return new PlistElementDate(date.ToUniversalTime()); - return null; - } - case "true": - return new PlistElementBoolean(true); - case "false": - return new PlistElementBoolean(false); - default: - return null; - } - } - - public void Create() - { - const string doc = "" + - "" + - "" + - "" + - "" + - ""; - ReadFromString(doc); - } - - public void ReadFromFile(string path) - { - ReadFromString(File.ReadAllText(path)); - } - - public void ReadFromStream(TextReader tr) - { - ReadFromString(tr.ReadToEnd()); - } - - public void ReadFromString(string text) - { - XDocument doc = ParseXmlNoDtd(text); - version = (string) doc.Root.Attribute("version"); - XElement xml = doc.XPathSelectElement("plist/dict"); - - var dict = ReadElement(xml); - if (dict == null) - throw new Exception("Error parsing plist file"); - root = dict as PlistElementDict; - if (root == null) - throw new Exception("Malformed plist file"); - documentType = doc.DocumentType; - } - - private static XElement WriteElement(PlistElement el) - { - if (el is PlistElementBoolean) - { - var realEl = el as PlistElementBoolean; - return new XElement(realEl.value ? "true" : "false"); - } - if (el is PlistElementInteger) - { - var realEl = el as PlistElementInteger; - return new XElement("integer", realEl.value.ToString()); - } - if (el is PlistElementString) - { - var realEl = el as PlistElementString; - return new XElement("string", realEl.value); - } - if (el is PlistElementReal) - { - var realEl = el as PlistElementReal; - return new XElement("real", realEl.value.ToString()); - } - if (el is PlistElementDate) - { - var realEl = el as PlistElementDate; - return new XElement("date", realEl.value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")); - } - if (el is PlistElementDict) - { - var realEl = el as PlistElementDict; - var dictXml = new XElement("dict"); - foreach (var kv in realEl.values) - { - var keyXml = new XElement("key", kv.Key); - var valueXml = WriteElement(kv.Value); - if (valueXml != null) - { - dictXml.Add(keyXml); - dictXml.Add(valueXml); - } - } - return dictXml; - } - if (el is PlistElementArray) - { - var realEl = el as PlistElementArray; - var arrayXml = new XElement("array"); - foreach (var v in realEl.values) - { - var elXml = WriteElement(v); - if (elXml != null) - arrayXml.Add(elXml); - } - return arrayXml; - } - return null; - } - - public void WriteToFile(string path) - { - System.Text.Encoding utf8WithoutBom = new System.Text.UTF8Encoding(false); - File.WriteAllText(path, WriteToString(), utf8WithoutBom); - } - - public void WriteToStream(TextWriter tw) - { - tw.Write(WriteToString()); - } - - public string WriteToString() - { - var el = WriteElement(root); - var rootEl = new XElement("plist"); - rootEl.Add(new XAttribute("version", version)); - rootEl.Add(el); - - var doc = new XDocument(); - doc.Add(rootEl); - return CleanDtdToString(doc, documentType).Replace("\r\n", "\n"); - } - } - -} // namespace UnityEditor.iOS.XCode diff --git a/Assets/Zapic/Editor/Xcode.Custom/PlistParser.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/PlistParser.cs.meta deleted file mode 100644 index feb689b..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/PlistParser.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: f134ed831904a4425919641092db9c1a -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/ProjectCapabilityManager.cs b/Assets/Zapic/Editor/Xcode.Custom/ProjectCapabilityManager.cs deleted file mode 100644 index 310ea40..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/ProjectCapabilityManager.cs +++ /dev/null @@ -1,681 +0,0 @@ -using System; -using System.IO; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode -#else -namespace UnityEditor.iOS.Xcode.Custom -#endif -{ - /// - /// The ProjectCapabilityManager class helps to add capabilities to the Xcode - /// project. This operation potentially involves modification of any of the - /// pbxproj file, the entitlements file(s) and Info.plist file(s). The - /// manager assumes ownership of all of these files until the last - /// WriteToFile() invocation. - /// - public class ProjectCapabilityManager - { - private readonly string m_BuildPath; - private readonly string m_TargetGuid; - private readonly string m_PBXProjectPath; - private readonly string m_EntitlementFilePath; - private PlistDocument m_Entitlements; - private PlistDocument m_InfoPlist; - protected internal PBXProject project; - - /// - /// Creates a new instance of ProjectCapabilityManager. The returned - /// instance assumes ownership of the referenced pbxproj project file, - /// the entitlements file and project Info.plist files until the last - /// WriteToFile() call. - /// - /// Path to the pbxproj file. - /// Path to the entitlements file. - /// The name of the target to add entitlements for. - public ProjectCapabilityManager(string pbxProjectPath, string entitlementFilePath, string targetName) - { - m_BuildPath = Directory.GetParent(Path.GetDirectoryName(pbxProjectPath)).FullName; - - m_EntitlementFilePath = entitlementFilePath; - m_PBXProjectPath = pbxProjectPath; - project = new PBXProject(); - project.ReadFromString(File.ReadAllText(m_PBXProjectPath)); - m_TargetGuid = project.TargetGuidByName(targetName); - } - - /// - /// Writes the modifications to the project file, entitlements file and - /// the Info.plist file. Any external changes to these files after - /// the ProjectCapabilityManager instance has been created and before - /// the call to WriteToFile() will be overwritten. - /// - public void WriteToFile() - { - File.WriteAllText(m_PBXProjectPath, project.WriteToString()); - if (m_Entitlements != null) - m_Entitlements.WriteToFile(PBXPath.Combine(m_BuildPath, m_EntitlementFilePath)); - if (m_InfoPlist != null) - m_InfoPlist.WriteToFile(PBXPath.Combine(m_BuildPath, "Info.plist")); - } - - /// - /// Adds iCloud capability to project - /// - /// Enables key-value storage option if set to true - /// Enables iCloud document option if set to true - /// A list of custom containers to add - public void AddiCloud(bool enableKeyValueStorage, bool enableiCloudDocument, - string[] customContainers) - { - AddiCloud(enableKeyValueStorage, enableiCloudDocument, true, true, - customContainers); - } - - /// - /// Adds iCloud capability to project - /// - /// Enables key-value storage option if set to true - /// Enables iCloud document option if set to true - /// Enables cloudKit option if set to true - /// Default containers are added if this option is set to true - /// A list of custom containers to add - public void AddiCloud(bool enableKeyValueStorage, bool enableiCloudDocument, bool enablecloudKit, bool addDefaultContainers, string[] customContainers) - { - var ent = GetOrCreateEntitlementDoc(); - var val = (ent.root[ICloudEntitlements.ContainerIdKey] = new PlistElementArray()) as PlistElementArray; - - // Cloud document storage and CloudKit require specifying services. - PlistElementArray ser = null; - if (enableiCloudDocument || enablecloudKit) - ser = (ent.root[ICloudEntitlements.ServicesKey] = new PlistElementArray()) as PlistElementArray; - - if (enableiCloudDocument) - { - val.values.Add(new PlistElementString(ICloudEntitlements.ContainerIdValue)); - ser.values.Add(new PlistElementString(ICloudEntitlements.ServicesDocValue)); - var ubiquity = (ent.root[ICloudEntitlements.UbiquityContainerIdKey] = new PlistElementArray()) as PlistElementArray; - - if (addDefaultContainers) - ubiquity.values.Add(new PlistElementString(ICloudEntitlements.UbiquityContainerIdValue)); - - if (customContainers != null && customContainers.Length > 0) - { - // For cloud document, custom containers go in the ubiquity values. - for (var i = 0; i < customContainers.Length; i++) - ubiquity.values.Add(new PlistElementString(customContainers[i])); - } - } - - if (enablecloudKit) - { - if (addDefaultContainers && !enableiCloudDocument) - val.values.Add(new PlistElementString(ICloudEntitlements.ContainerIdValue)); - - if (customContainers != null && customContainers.Length > 0) - { - // For CloudKit, custom containers also go in the container id values. - for (var i = 0; i < customContainers.Length; i++) - val.values.Add(new PlistElementString(customContainers[i])); - } - - ser.values.Add(new PlistElementString(ICloudEntitlements.ServicesKitValue)); - } - - if (enableKeyValueStorage) - ent.root[ICloudEntitlements.KeyValueStoreKey] = new PlistElementString(ICloudEntitlements.KeyValueStoreValue); - - project.AddCapability(m_TargetGuid, PBXCapabilityType.iCloud, m_EntitlementFilePath, enablecloudKit); - } - - /// - /// Add Push (or remote) Notifications capability to the project - /// - /// Sets the development option if set to true - public void AddPushNotifications(bool development) - { - GetOrCreateEntitlementDoc().root[PushNotificationEntitlements.Key] = new PlistElementString(development ? PushNotificationEntitlements.DevelopmentValue : PushNotificationEntitlements.ProductionValue); - project.AddCapability(m_TargetGuid, PBXCapabilityType.PushNotifications, m_EntitlementFilePath); - } - - /// - /// Adds Game Center capability to the project - /// - public void AddGameCenter() - { - var arr = (GetOrCreateInfoDoc().root[GameCenterInfo.Key] ?? (GetOrCreateInfoDoc().root[GameCenterInfo.Key] = new PlistElementArray())) as PlistElementArray; - arr.values.Add(new PlistElementString(GameCenterInfo.Value)); - project.AddCapability(m_TargetGuid, PBXCapabilityType.GameCenter); - } - - /// - /// Adds wallet capability to the project. - /// - /// Controls the allowed pass types. If null or - /// empty, then all team pass types are allowed. Otherwise, only the - /// specified subset of pass types is allowed - public void AddWallet(string[] passSubset) - { - var arr = (GetOrCreateEntitlementDoc().root[WalletEntitlements.Key] = new PlistElementArray()) as PlistElementArray; - if ((passSubset == null || passSubset.Length == 0) && arr != null) - { - arr.values.Add(new PlistElementString(WalletEntitlements.BaseValue + WalletEntitlements.BaseValue)); - } - else - { - for (var i = 0; i < passSubset.Length; i++) - { - if (arr != null) - arr.values.Add(new PlistElementString(WalletEntitlements.BaseValue + passSubset[i])); - } - } - - project.AddCapability(m_TargetGuid, PBXCapabilityType.Wallet, m_EntitlementFilePath); - } - - /// - /// Adds Siri capability to project. - /// - public void AddSiri() - { - GetOrCreateEntitlementDoc().root[SiriEntitlements.Key] = new PlistElementBoolean(true); - - project.AddCapability(m_TargetGuid, PBXCapabilityType.Siri, m_EntitlementFilePath); - } - - /// - /// Adds Apple Pay capability to the project. - /// - /// The list of merchant IDs to configure - public void AddApplePay(string[] merchants) - { - var arr = (GetOrCreateEntitlementDoc().root[ApplePayEntitlements.Key] = new PlistElementArray()) as PlistElementArray; - for (var i = 0; i < merchants.Length; i++) - { - arr.values.Add(new PlistElementString(merchants[i])); - } - - project.AddCapability(m_TargetGuid, PBXCapabilityType.ApplePay, m_EntitlementFilePath); - } - - /// - /// Adds In App Purchase capability to the project. - /// - public void AddInAppPurchase() - { - project.AddCapability(m_TargetGuid, PBXCapabilityType.InAppPurchase); - } - - /// - /// Adds Maps capability to the project. - /// - /// The routing options to configure. - public void AddMaps(MapsOptions options) - { - var bundleArr = (GetOrCreateInfoDoc().root[MapsInfo.BundleKey] ?? (GetOrCreateInfoDoc().root[MapsInfo.BundleKey] = new PlistElementArray())) as PlistElementArray; - bundleArr.values.Add(new PlistElementDict()); - PlistElementDict bundleDic = GetOrCreateUniqueDictElementInArray(bundleArr); - bundleDic[MapsInfo.BundleNameKey] = new PlistElementString(MapsInfo.BundleNameValue); - var bundleTypeArr = (bundleDic[MapsInfo.BundleTypeKey] ?? (bundleDic[MapsInfo.BundleTypeKey] = new PlistElementArray())) as PlistElementArray; - GetOrCreateStringElementInArray(bundleTypeArr, MapsInfo.BundleTypeValue); - - var optionArr = (GetOrCreateInfoDoc().root[MapsInfo.ModeKey] ?? - (GetOrCreateInfoDoc().root[MapsInfo.ModeKey] = new PlistElementArray())) as PlistElementArray; - if ((options & MapsOptions.Airplane) == MapsOptions.Airplane) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModePlaneValue); - } - if ((options & MapsOptions.Bike) == MapsOptions.Bike) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeBikeValue); - } - if ((options & MapsOptions.Bus) == MapsOptions.Bus) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeBusValue); - } - if ((options & MapsOptions.Car) == MapsOptions.Car) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeCarValue); - } - if ((options & MapsOptions.Ferry) == MapsOptions.Ferry) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeFerryValue); - } - if ((options & MapsOptions.Other) == MapsOptions.Other) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeOtherValue); - } - if ((options & MapsOptions.Pedestrian) == MapsOptions.Pedestrian) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModePedestrianValue); - } - if ((options & MapsOptions.RideSharing) == MapsOptions.RideSharing) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeRideShareValue); - } - if ((options & MapsOptions.StreetCar) == MapsOptions.StreetCar) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeStreetCarValue); - } - if ((options & MapsOptions.Subway) == MapsOptions.Subway) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeSubwayValue); - } - if ((options & MapsOptions.Taxi) == MapsOptions.Taxi) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeTaxiValue); - } - if ((options & MapsOptions.Train) == MapsOptions.Train) - { - GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeTrainValue); - } - - project.AddCapability(m_TargetGuid, PBXCapabilityType.Maps); - } - - /// - /// Adds Personal VPN capability to the project. - /// - public void AddPersonalVPN() - { - var arr = (GetOrCreateEntitlementDoc().root[VPNEntitlements.Key] = new PlistElementArray()) as PlistElementArray; - arr.values.Add(new PlistElementString(VPNEntitlements.Value)); - - project.AddCapability(m_TargetGuid, PBXCapabilityType.PersonalVPN, m_EntitlementFilePath); - } - - /// - /// Adds Background capability to the project. - /// - /// The list of background modes to configure. - public void AddBackgroundModes(BackgroundModesOptions options) - { - var optionArr = (GetOrCreateInfoDoc().root[BackgroundInfo.Key] ?? - (GetOrCreateInfoDoc().root[BackgroundInfo.Key] = new PlistElementArray())) as PlistElementArray; - - if ((options & BackgroundModesOptions.ActsAsABluetoothLEAccessory) == BackgroundModesOptions.ActsAsABluetoothLEAccessory) - { - GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeActsBluetoothValue); - } - if ((options & BackgroundModesOptions.AudioAirplayPiP) == BackgroundModesOptions.AudioAirplayPiP) - { - GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeAudioValue); - } - if ((options & BackgroundModesOptions.BackgroundFetch) == BackgroundModesOptions.BackgroundFetch) - { - GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeFetchValue); - } - if ((options & BackgroundModesOptions.ExternalAccessoryCommunication) == BackgroundModesOptions.ExternalAccessoryCommunication) - { - GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeExtAccessoryValue); - } - if ((options & BackgroundModesOptions.LocationUpdates) == BackgroundModesOptions.LocationUpdates) - { - GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeLocationValue); - } - if ((options & BackgroundModesOptions.NewsstandDownloads) == BackgroundModesOptions.NewsstandDownloads) - { - GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeNewsstandValue); - } - if ((options & BackgroundModesOptions.RemoteNotifications) == BackgroundModesOptions.RemoteNotifications) - { - GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModePushValue); - } - if ((options & BackgroundModesOptions.VoiceOverIP) == BackgroundModesOptions.VoiceOverIP) - { - GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeVOIPValue); - } - project.AddCapability(m_TargetGuid, PBXCapabilityType.BackgroundModes); - } - - /// - /// Adds Keychain Sharing capability to the project. - /// - /// The list of keychain access groups to configure. - public void AddKeychainSharing(string[] accessGroups) - { - var arr = (GetOrCreateEntitlementDoc().root[KeyChainEntitlements.Key] = new PlistElementArray()) as PlistElementArray; - if (accessGroups != null) - { - for (var i = 0; i < accessGroups.Length; i++) - { - arr.values.Add(new PlistElementString(accessGroups[i])); - } - } - else - { - arr.values.Add(new PlistElementString(KeyChainEntitlements.DefaultValue)); - } - - project.AddCapability(m_TargetGuid, PBXCapabilityType.KeychainSharing, m_EntitlementFilePath); - } - - /// - /// Adds Inter App Audio capability to the project. - /// - public void AddInterAppAudio() - { - GetOrCreateEntitlementDoc().root[AudioEntitlements.Key] = new PlistElementBoolean(true); - project.AddCapability(m_TargetGuid, PBXCapabilityType.InterAppAudio, m_EntitlementFilePath); - } - - /// - /// Adds Associated Domains capability to the project. - /// - /// The list of domains to configure. - public void AddAssociatedDomains(string[] domains) - { - var arr = (GetOrCreateEntitlementDoc().root[AssociatedDomainsEntitlements.Key] = new PlistElementArray()) as PlistElementArray; - for (var i = 0; i < domains.Length; i++) - { - arr.values.Add(new PlistElementString(domains[i])); - } - - project.AddCapability(m_TargetGuid, PBXCapabilityType.AssociatedDomains, m_EntitlementFilePath); - } - - /// - /// Adds App Groups capability to the project. - /// - /// The list of app groups to configure. - public void AddAppGroups(string[] groups) - { - var arr = (GetOrCreateEntitlementDoc().root[AppGroupsEntitlements.Key] = new PlistElementArray()) as PlistElementArray; - for (var i = 0; i < groups.Length; i++) - { - arr.values.Add(new PlistElementString(groups[i])); - } - - project.AddCapability(m_TargetGuid, PBXCapabilityType.AppGroups, m_EntitlementFilePath); - } - - /// - /// Adds HomeKit capability to the project. - /// - public void AddHomeKit() - { - GetOrCreateEntitlementDoc().root[HomeKitEntitlements.Key] = new PlistElementBoolean(true); - project.AddCapability(m_TargetGuid, PBXCapabilityType.HomeKit, m_EntitlementFilePath); - } - - /// - /// Adds Data Protection capability to the project. - /// - public void AddDataProtection() - { - GetOrCreateEntitlementDoc().root[DataProtectionEntitlements.Key] = new PlistElementString(DataProtectionEntitlements.Value); - project.AddCapability(m_TargetGuid, PBXCapabilityType.DataProtection, m_EntitlementFilePath); - } - - /// - /// Adds HealthKit capability to the project. - /// - public void AddHealthKit() - { - var capabilityArr = (GetOrCreateInfoDoc().root[HealthInfo.Key] ?? - (GetOrCreateInfoDoc().root[HealthInfo.Key] = new PlistElementArray())) as PlistElementArray; - GetOrCreateStringElementInArray(capabilityArr, HealthInfo.Value); - GetOrCreateEntitlementDoc().root[HealthKitEntitlements.Key] = new PlistElementBoolean(true); - project.AddCapability(m_TargetGuid, PBXCapabilityType.HealthKit, m_EntitlementFilePath); - } - - /// - /// Adds Wireless Accessory Configuration capability to the project. - /// - public void AddWirelessAccessoryConfiguration() - { - GetOrCreateEntitlementDoc().root[WirelessAccessoryConfigurationEntitlements.Key] = new PlistElementBoolean(true); - project.AddCapability(m_TargetGuid, PBXCapabilityType.WirelessAccessoryConfiguration, m_EntitlementFilePath); - } - - private PlistDocument GetOrCreateEntitlementDoc() - { - if (m_Entitlements == null) - { - m_Entitlements = new PlistDocument(); - string[] entitlementsFiles = Directory.GetFiles(m_BuildPath, m_EntitlementFilePath); - if (entitlementsFiles.Length > 0) - { - m_Entitlements.ReadFromFile(entitlementsFiles[0]); - } - else - { - m_Entitlements.Create(); - } - } - - return m_Entitlements; - } - - private PlistDocument GetOrCreateInfoDoc() - { - if (m_InfoPlist == null) - { - m_InfoPlist = new PlistDocument(); - string[] infoFiles = Directory.GetFiles(m_BuildPath + "/", "Info.plist"); - if (infoFiles.Length > 0) - { - m_InfoPlist.ReadFromFile(infoFiles[0]); - } - else - { - m_InfoPlist.Create(); - } - } - - return m_InfoPlist; - } - - private PlistElementString GetOrCreateStringElementInArray(PlistElementArray root, string value) - { - PlistElementString r = null; - var c = root.values.Count; - var exist = false; - for (var i = 0; i < c; i++) - { - if (root.values[i] is PlistElementString && (root.values[i] as PlistElementString).value == value) - { - r = root.values[i] as PlistElementString; - exist = true; - } - } - if (!exist) - { - r = new PlistElementString(value); - root.values.Add(r); - } - return r; - } - - private PlistElementDict GetOrCreateUniqueDictElementInArray(PlistElementArray root) - { - PlistElementDict r; - if (root.values.Count == 0) - { - r = root.values[0] as PlistElementDict; - } - else - { - r = new PlistElementDict(); - root.values.Add(r); - } - return r; - } - } - - // The list of options available for Background Mode. - [Flags] - [Serializable] - public enum BackgroundModesOptions - { - None = 0, - AudioAirplayPiP = 1<<0, - LocationUpdates = 1<<1, - VoiceOverIP = 1<<2, - NewsstandDownloads = 1<<3, - ExternalAccessoryCommunication = 1<<4, - UsesBluetoothLEAccessory = 1<<5, - ActsAsABluetoothLEAccessory = 1<<6, - BackgroundFetch = 1<<7, - RemoteNotifications = 1<<8 - } - - // The list of options available for Maps. - [Serializable] - [Flags] - public enum MapsOptions - { - None = 0, - Airplane = 1<<0, - Bike = 1<<1, - Bus = 1<<2, - Car = 1<<3, - Ferry = 1<<4, - Pedestrian = 1<<5, - RideSharing = 1<<6, - StreetCar = 1<<7, - Subway = 1<<8, - Taxi = 1<<9, - Train = 1<<10, - Other = 1<<11 - } - - /* Follows the large quantity of string used as key and value all over the place in the info.plist or entitlements file. */ - internal class GameCenterInfo - { - internal static readonly string Key = "UIRequiredDeviceCapabilities"; - internal static readonly string Value = "gamekit"; - } - - internal class MapsInfo - { - internal static readonly string BundleKey = "CFBundleDocumentTypes"; - internal static readonly string BundleNameKey = "CFBundleTypeName"; - internal static readonly string BundleNameValue = "MKDirectionsRequest"; - internal static readonly string BundleTypeKey = "LSItemContentTypes"; - internal static readonly string BundleTypeValue = "com.apple.maps.directionsrequest"; - internal static readonly string ModeKey = "MKDirectionsApplicationSupportedModes"; - internal static readonly string ModePlaneValue = "MKDirectionsModePlane"; - internal static readonly string ModeBikeValue = "MKDirectionsModeBike"; - internal static readonly string ModeBusValue = "MKDirectionsModeBus"; - internal static readonly string ModeCarValue = "MKDirectionsModeCar"; - internal static readonly string ModeFerryValue = "MKDirectionsModeFerry"; - internal static readonly string ModeOtherValue = "MKDirectionsModeOther"; - internal static readonly string ModePedestrianValue = "MKDirectionsModePedestrian"; - internal static readonly string ModeRideShareValue = "MKDirectionsModeRideShare"; - internal static readonly string ModeStreetCarValue = "MKDirectionsModeStreetCar"; - internal static readonly string ModeSubwayValue = "MKDirectionsModeSubway"; - internal static readonly string ModeTaxiValue = "MKDirectionsModeTaxi"; - internal static readonly string ModeTrainValue = "MKDirectionsModeTrain"; - } - - internal class BackgroundInfo - { - internal static readonly string Key = "UIBackgroundModes"; - internal static readonly string ModeAudioValue = "audio"; - internal static readonly string ModeBluetoothValue = "bluetooth-central"; - internal static readonly string ModeActsBluetoothValue = "bluetooth-peripheral"; - internal static readonly string ModeExtAccessoryValue = "external-accessory"; - internal static readonly string ModeFetchValue = "fetch"; - internal static readonly string ModeLocationValue = "location"; - internal static readonly string ModeNewsstandValue = "newsstand-content"; - internal static readonly string ModePushValue = "remote-notification"; - internal static readonly string ModeVOIPValue = "voip"; - } - - internal class HealthInfo - { - internal static readonly string Key = "UIRequiredDeviceCapabilities"; - internal static readonly string Value = "healthkit"; - } - - internal class ICloudEntitlements - { - internal static readonly string ContainerIdKey = "com.apple.developer.icloud-container-identifiers"; - internal static readonly string ContainerIdValue = "iCloud.$(CFBundleIdentifier)"; - internal static readonly string UbiquityContainerIdKey = "com.apple.developer.ubiquity-container-identifiers"; - internal static readonly string UbiquityContainerIdValue = "iCloud.$(CFBundleIdentifier)"; - internal static readonly string ServicesKey = "com.apple.developer.icloud-services"; - internal static readonly string ServicesDocValue = "CloudDocuments"; - internal static readonly string ServicesKitValue = "CloudKit"; - internal static readonly string KeyValueStoreKey = "com.apple.developer.ubiquity-kvstore-identifier"; - internal static readonly string KeyValueStoreValue = "$(TeamIdentifierPrefix)$(CFBundleIdentifier)"; - } - - internal class PushNotificationEntitlements - { - internal static readonly string Key = "aps-environment"; - internal static readonly string DevelopmentValue = "development"; - internal static readonly string ProductionValue = "production"; - } - - internal class WalletEntitlements - { - internal static readonly string Key = "com.apple.developer.pass-type-identifiers"; - internal static readonly string BaseValue = "$(TeamIdentifierPrefix)"; - internal static readonly string DefaultValue = "*"; - } - - internal class SiriEntitlements - { - internal static readonly string Key = "com.apple.developer.siri"; - } - - internal class ApplePayEntitlements - { - internal static readonly string Key = "com.apple.developer.in-app-payments"; - } - - internal class VPNEntitlements - { - internal static readonly string Key = "com.apple.developer.networking.vpn.api"; - internal static readonly string Value = "allow-vpn"; - } - - internal class KeyChainEntitlements - { - internal static readonly string Key = "keychain-access-groups"; - internal static readonly string DefaultValue = "$(AppIdentifierPrefix)$(CFBundleIdentifier)"; - } - - internal class AudioEntitlements - { - internal static readonly string Key = "inter-app-audio"; - } - - internal class AssociatedDomainsEntitlements - { - // value is an array of string of domains - internal static readonly string Key = "com.apple.developer.associated-domains"; - } - - internal class AppGroupsEntitlements - { - // value is an array of string of groups - internal static readonly string Key = "com.apple.security.application-groups"; - } - - internal class HomeKitEntitlements - { - // value is bool true. - internal static readonly string Key = "com.apple.developer.homekit"; - } - - internal class DataProtectionEntitlements - { - internal static readonly string Key = "com.apple.developer.default-data-protection"; - internal static readonly string Value = "NSFileProtectionComplete"; - } - - internal class HealthKitEntitlements - { - // value is bool true. - internal static readonly string Key = "com.apple.developer.healthkit"; - } - - internal class WirelessAccessoryConfigurationEntitlements - { - // value is bool true. - internal static readonly string Key = "com.apple.external-accessory.wireless-configuration"; - } -} diff --git a/Assets/Zapic/Editor/Xcode.Custom/ProjectCapabilityManager.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/ProjectCapabilityManager.cs.meta deleted file mode 100644 index 6ee7a71..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/ProjectCapabilityManager.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: cc6ab150fe835400895667089f8a9c47 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/Properties/AssemblyInfo.cs b/Assets/Zapic/Editor/Xcode.Custom/Properties/AssemblyInfo.cs deleted file mode 100644 index e12bc74..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Unity.iOS.Extensions.Xcode")] -[assembly: AssemblyDescription("Unity Xcode editor's extensions for iOS")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Unity Technologies")] -[assembly: AssemblyProduct("Unity.iOS.Extensions.Xcode")] -[assembly: AssemblyCopyright("Copyright © Unity Technologies 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("d14b0723-623a-4603-a9b1-7135970e9ae2")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] - -// Show the internal functions to the tests -[assembly: InternalsVisibleTo("Xcode.Tests")] - diff --git a/Assets/Zapic/Editor/Xcode.Custom/Properties/AssemblyInfo.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/Properties/AssemblyInfo.cs.meta deleted file mode 100644 index 3ffb8e8..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/Properties/AssemblyInfo.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: e5be7900a07be4799af5058ab14c0bf9 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/Xcode.Custom/XcScheme.cs b/Assets/Zapic/Editor/Xcode.Custom/XcScheme.cs deleted file mode 100644 index 4dfaac5..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/XcScheme.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml; -using System.Xml.Linq; -using System.Xml.XPath; - -#if UNITY_XCODE_API_BUILD -namespace UnityEditor.iOS.Xcode -#else -namespace UnityEditor.iOS.Xcode.Custom -#endif -{ - internal class XcScheme - { - XDocument m_Doc; - - // Returns the current build configuration. Returns null if it is not set. - public string GetBuildConfiguration() - { - var el = m_Doc.Root.XPathSelectElement("./LaunchAction"); - if (el == null) - throw new Exception("The xcscheme document does not contain build configuration setting"); - var attr = el.Attribute("buildConfiguration"); - if (attr == null) - return null; - return attr.Value; - } - - public void SetBuildConfiguration(string buildConfigName) - { - var el = m_Doc.Root.XPathSelectElement("./LaunchAction"); - if (el == null) - throw new Exception("The xcscheme document does not contain build configuration setting"); - el.SetAttributeValue("buildConfiguration", buildConfigName); - } - - public void ReadFromFile(string path) - { - ReadFromString(File.ReadAllText(path)); - } - - public void ReadFromStream(TextReader tr) - { - ReadFromString(tr.ReadToEnd()); - } - - public void ReadFromString(string text) - { - m_Doc = PlistDocument.ParseXmlNoDtd(text); - } - - public void WriteToFile(string path) - { - System.Text.Encoding utf8WithoutBom = new System.Text.UTF8Encoding(false); - File.WriteAllText(path, WriteToString(), utf8WithoutBom); - } - - public void WriteToStream(TextWriter tw) - { - tw.Write(WriteToString()); - } - - public string WriteToString() - { - return PlistDocument.CleanDtdToString(m_Doc, null).Replace("\r\n", "\n"); - } - } - -} // namespace UnityEditor.iOS.XCode diff --git a/Assets/Zapic/Editor/Xcode.Custom/XcScheme.cs.meta b/Assets/Zapic/Editor/Xcode.Custom/XcScheme.cs.meta deleted file mode 100644 index f225daa..0000000 --- a/Assets/Zapic/Editor/Xcode.Custom/XcScheme.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 0a14eeaac73a24d068ca020be6cc4df8 -timeCreated: 1522126362 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/Editor/ZapicPostProcessBuild.cs b/Assets/Zapic/Editor/ZapicPostProcessBuild.cs new file mode 100755 index 0000000..642e6dd --- /dev/null +++ b/Assets/Zapic/Editor/ZapicPostProcessBuild.cs @@ -0,0 +1,69 @@ +#if UNITY_IOS +using System.Collections; +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEditor.iOS.Xcode; +using UnityEditor.iOS.Xcode.Extensions; +using UnityEngine; + +namespace Zapic +{ + public class ZapicPostProcessBuild + { + [PostProcessBuild(999)] + public static void OnPostprocessBuild(BuildTarget buildTarget, string pathToBuiltProject) + { + ConfigureXcodeSettings(buildTarget, pathToBuiltProject); + ConfigureXcodePlist(buildTarget, pathToBuiltProject); + } + + private static void ConfigureXcodeSettings(BuildTarget buildTarget, string pathToBuiltProject) + { + if (buildTarget != BuildTarget.iOS) + return; + + Debug.Log("Running Zapic Xcode Build Scripts"); + + string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject); + + //Find and load the xcode project + var proj = new PBXProject(); + proj.ReadFromString(File.ReadAllText(projPath)); + + //Find the unity target + string targetGuid = proj.TargetGuidByName(PBXProject.GetUnityTargetName()); + + //Enable modules so @import can be used to resolve frameworks + proj.SetBuildProperty(targetGuid, "CLANG_ENABLE_MODULES", "YES"); + + File.WriteAllText(projPath, proj.WriteToString()); + + Debug.Log("Done with Zapic Xcode Build Scripts"); + } + + private static void ConfigureXcodePlist(BuildTarget buildTarget, string pathToBuiltProject) + { + if (buildTarget != BuildTarget.iOS) + return; + + Debug.Log("Zapic:Configuring plist"); + + var plistPath = Path.Combine(pathToBuiltProject, "Info.plist"); + var plist = new PlistDocument(); + plist.ReadFromFile(plistPath); + + // Add string setting + plist.root.SetString("NSPhotoLibraryUsageDescription", "Zapic will only use the Photos you select."); + plist.root.SetString("NSCameraUsageDescription", "Zapic allows you to take photos."); + + // Apply editing settings to Info.plist + plist.WriteToFile(plistPath); + + Debug.Log("Zapic:Done configuring plist"); + } + } +} +#endif \ No newline at end of file diff --git a/Assets/Zapic/Editor/Xcode.Custom/PBX/Elements.cs.meta b/Assets/Zapic/Editor/ZapicPostProcessBuild.cs.meta similarity index 71% rename from Assets/Zapic/Editor/Xcode.Custom/PBX/Elements.cs.meta rename to Assets/Zapic/Editor/ZapicPostProcessBuild.cs.meta index d69e2fc..58a2745 100644 --- a/Assets/Zapic/Editor/Xcode.Custom/PBX/Elements.cs.meta +++ b/Assets/Zapic/Editor/ZapicPostProcessBuild.cs.meta @@ -1,7 +1,5 @@ fileFormatVersion: 2 -guid: 786c865d3119449ae8301ce4309f4dd2 -timeCreated: 1522126362 -licenseType: Free +guid: bcfaf725314a845bebd1507c68b99725 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/Zapic/Editor/iOSBuildSettings.cs b/Assets/Zapic/Editor/iOSBuildSettings.cs deleted file mode 100644 index a45c205..0000000 --- a/Assets/Zapic/Editor/iOSBuildSettings.cs +++ /dev/null @@ -1,185 +0,0 @@ -#if UNITY_IOS -using System.Collections; -using System.IO; -using System.Reflection; -using System.Text.RegularExpressions; -using UnityEditor; -using UnityEditor.Callbacks; -using UnityEditor.iOS.Xcode.Custom; -using UnityEditor.iOS.Xcode.Custom.Extensions; -using UnityEngine; - -namespace Zapic -{ - public class iOSBuildSettings - { - [PostProcessBuild(999)] - public static void OnPostprocessBuild(BuildTarget buildTarget, string pathToBuiltProject) - { - ConfigureXcodeSettings(buildTarget, pathToBuiltProject); - ConfigureXcodePlist(buildTarget, pathToBuiltProject); - } - - private static void ConfigureXcodeSettings(BuildTarget buildTarget, string pathToBuiltProject) - { - if (buildTarget != BuildTarget.iOS) - return; - - Debug.Log("Running Zapic Xcode Scripts"); - - string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject); - - //Find and load the xcode project - var proj = new PBXProject(); - proj.ReadFromString(File.ReadAllText(projPath)); - - //Find the unity target - string targetGuid = proj.TargetGuidByName(PBXProject.GetUnityTargetName()); - - //Force swift to be included - Debug.Log("Zapic: Including Swift Libraries"); - proj.SetBuildProperty(targetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES"); - - //Include the frameworks directory in search path to find Zapic.framework - Debug.Log("Zapic: Setting search path"); - proj.SetBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks"); - - //Find the id for Zapic.framework fild - var frameworkId = proj.FindFileGuidByProjectPath("Frameworks/Plugins/iOS/Zapic.framework"); - - if (string.IsNullOrEmpty(frameworkId)) - { - Debug.LogError("Zapic: Unable to find iOS framework"); - } - - //Get or Add a copy files build phase - Debug.Log("Zapic:Adding embedded framework"); - - proj.AddFileToEmbedFrameworks(targetGuid, frameworkId); - - //Stip the framework to the propery build type - proj.AddStripFatFrameworkScript(targetGuid); - - //Save the project - proj.WriteToFile(projPath); - - Debug.Log("Zapic:Done configuring xcode settings"); - } - - private static void ConfigureXcodePlist(BuildTarget buildTarget, string pathToBuiltProject) - { - if (buildTarget != BuildTarget.iOS) - return; - - Debug.Log("Zapic:Configuring plist"); - - // Samlpe of editing Info.plist - var plistPath = Path.Combine(pathToBuiltProject, "Info.plist"); - var plist = new PlistDocument(); - plist.ReadFromFile(plistPath); - - // Add string setting - plist.root.SetString("NSPhotoLibraryUsageDescription", "Zapic will only use the Photos you select."); - plist.root.SetString("NSCameraUsageDescription", "Zapic allows your to take photos."); - - // Apply editing settings to Info.plist - plist.WriteToFile(plistPath); - - Debug.Log("Zapic:Done configuring plist"); - } - } - - internal static class PBXExtensions - { - /// - /// This is a hack to access the internal method. Replace this one unity makes it public - /// - /// - /// - /// - /// - /// - public static void AppendShellScriptBuildPhase(this PBXProject project, string targetGuid, string name, string shellPath, string shellScript) - { - Debug.Log("Zapic: Adding Shell script"); - - MethodInfo dynMethod = project.GetType().GetMethod( - "AppendShellScriptBuildPhase", - BindingFlags.NonPublic | BindingFlags.Instance, - null, - CallingConventions.Any, - new System.Type[] { typeof(string), typeof(string), typeof(string), typeof(string) }, - null); - - dynMethod.Invoke(project, new object[] { targetGuid, name, shellPath, shellScript }); - } - - public static string ShellScriptByName(this PBXProject project, string targetGuid, string name) - { - Debug.Log("Zapic: Getting Shell script"); - - MethodInfo dynMethod = project.GetType().GetMethod( - "ShellScriptByName", - BindingFlags.NonPublic | BindingFlags.Instance); - - var result = dynMethod.Invoke(project, new object[] { targetGuid, name }); - - return result as string; - } - - public static void AddStripFatFrameworkScript(this PBXProject proj, string targetGuid) - { - Debug.Log("Zapic: Adding strip framework"); - - const string ScriptName = "Strip Fat Library"; - - var scriptId = proj.ShellScriptByName(targetGuid, ScriptName); - - if (string.IsNullOrEmpty(scriptId)) - proj.AppendShellScriptBuildPhase(targetGuid, ScriptName, "/bin/sh", StripArchScript); - } - - private static readonly string StripArchScript = - @" -echo ""Target architectures: $ARCHS"" - -APP_PATH=""${TARGET_BUILD_DIR}/${WRAPPER_NAME}"" - -find ""$APP_PATH"" -name '*.framework' -type d | while read -r FRAMEWORK -do -FRAMEWORK_EXECUTABLE_NAME=$(defaults read ""$FRAMEWORK/Info.plist"" CFBundleExecutable) -FRAMEWORK_EXECUTABLE_PATH=""$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"" -echo ""Executable is $FRAMEWORK_EXECUTABLE_PATH"" -echo $(lipo -info ""$FRAMEWORK_EXECUTABLE_PATH"") - -FRAMEWORK_TMP_PATH=""$FRAMEWORK_EXECUTABLE_PATH-tmp"" - -case ""${TARGET_BUILD_DIR}"" in -*""iphonesimulator"") -echo ""No need to remove archs"" -;; -*) -if $(lipo ""$FRAMEWORK_EXECUTABLE_PATH"" -verify_arch ""i386"") ; then -lipo -output ""$FRAMEWORK_TMP_PATH"" -remove ""i386"" ""$FRAMEWORK_EXECUTABLE_PATH"" -echo ""i386 architecture removed"" -rm ""$FRAMEWORK_EXECUTABLE_PATH"" -mv ""$FRAMEWORK_TMP_PATH"" ""$FRAMEWORK_EXECUTABLE_PATH"" -fi -if $(lipo ""$FRAMEWORK_EXECUTABLE_PATH"" -verify_arch ""x86_64"") ; then -lipo -output ""$FRAMEWORK_TMP_PATH"" -remove ""x86_64"" ""$FRAMEWORK_EXECUTABLE_PATH"" -echo ""x86_64 architecture removed"" -rm ""$FRAMEWORK_EXECUTABLE_PATH"" -mv ""$FRAMEWORK_TMP_PATH"" ""$FRAMEWORK_EXECUTABLE_PATH"" -fi -;; -esac - -echo ""Completed for executable $FRAMEWORK_EXECUTABLE_PATH"" -echo $(lipo -info ""$FRAMEWORK_EXECUTABLE_PATH"") - -done - "; - - } -} -#endif \ No newline at end of file diff --git a/Assets/Zapic/Editor/iOSBuildSettings.cs.meta b/Assets/Zapic/Editor/iOSBuildSettings.cs.meta deleted file mode 100644 index 210a08e..0000000 --- a/Assets/Zapic/Editor/iOSBuildSettings.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 05ed7c0e6b34f45eda08039368ae8c87 -timeCreated: 1508167068 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Zapic/IZapicInterface.cs b/Assets/Zapic/IZapicInterface.cs index d4c587c..58d9422 100644 --- a/Assets/Zapic/IZapicInterface.cs +++ b/Assets/Zapic/IZapicInterface.cs @@ -32,11 +32,11 @@ internal interface IZapicInterface /// void ShowDefaultPage(); - /// + /// /// Shows the given Zapic page /// /// Page to show. - void ShowPage(ZapicPages page); + void ShowPage(string page); /// /// Gets the current players unique id. @@ -56,4 +56,4 @@ internal interface IZapicInterface /// Collection of parameter names and associate values (numeric, string, bool) void SubmitEvent(Dictionary param); } -} +} \ No newline at end of file diff --git a/Assets/Zapic/Plugins.meta b/Assets/Zapic/Plugins.meta new file mode 100644 index 0000000..391363a --- /dev/null +++ b/Assets/Zapic/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1897ba5c2dcc97b468f9567a3b774d12 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Zapic/Plugins/iOS.meta b/Assets/Zapic/Plugins/iOS.meta new file mode 100644 index 0000000..bebb1bb --- /dev/null +++ b/Assets/Zapic/Plugins/iOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b708fbd6e583c47f68f850c756243e2b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Zapic/Plugins/iOS/ZapicInterface.mm b/Assets/Zapic/Plugins/iOS/ZapicInterface.mm new file mode 100644 index 0000000..fa686bb --- /dev/null +++ b/Assets/Zapic/Plugins/iOS/ZapicInterface.mm @@ -0,0 +1,108 @@ +#import +#import "Zapic.h" +#import "ZPCWebApp.h" +#import "ZPCLog.h" +#import "ZPCUtils.h" + +typedef struct +{ + char* identifier; + char* notificationToken; +} ZPCUPlayer; + +/// Converts C style string to NSString +NSString* fromCString (const char* string) +{ + if (string) + return [NSString stringWithUTF8String: string]; + else + return [NSString stringWithUTF8String: ""]; +} + +/// Converts an NSString to a C string +char* toCString(NSString *string){ + if(string == nil || [string isEqual:[NSNull null]]) + return NULL; + + const char *str = [string UTF8String]; + + if (str == NULL) + return NULL; + + char* res = (char*)malloc(strlen(str) + 1); + strcpy(res, str); + return res; +} + +NSDictionary* deserilizeJson(const char* string){ + //Convert the data to a string + NSString* json = fromCString(string); + NSError* error; + //Deserialize the string into a dictionary + NSData *jData = [json dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jData + options:kNilOptions + error:&error]; + return dict; +} + +ZPCUPlayer toUnityPlayer(ZPCPlayer *p){ + ZPCUPlayer player; + player.identifier = toCString(p.identifier); + player.notificationToken = toCString(p.notificationToken); + return player; +} + +BOOL hasValue(id object){ + return !(object == nil || [object isEqual:[NSNull null]]); +} + +extern "C" { + +#pragma mark - Callback definitions + typedef void (*ZAPIC_LOGIN_CALLBACK)(ZPCUPlayer player); + typedef void (*ZAPIC_LOGOUT_CALLBACK)(ZPCUPlayer player); + +#pragma mark - API Methods + void zpc_start(){ + [Zapic start]; + } + + void zpc_show(char* pageName){ + [Zapic showPage:fromCString(pageName)]; + } + + void zpc_showDefault(){ + [Zapic showDefaultPage]; + } + + void zpc_submitEventWithParams(char* data){ + NSDictionary *event = deserilizeJson(data); + [Zapic submitEvent:event]; + } + + ZPCUPlayer zpc_player(){ + ZPCPlayer *p = [Zapic player]; + return toUnityPlayer(p); + } + + /// Sets the login handler + void zpc_setLoginHandler(ZAPIC_LOGIN_CALLBACK callback){ + Zapic.loginHandler = ^(ZPCPlayer *p) { + callback(toUnityPlayer(p)); + }; + } + + /// Sets the logout handler + void zpc_setLogoutHandler(ZAPIC_LOGOUT_CALLBACK callback){ + Zapic.logoutHandler = ^(ZPCPlayer *p) { + callback(toUnityPlayer(p)); + }; + } + + /// Handle data provided by Zapic to an external source (push notification, deep link...) + void zpc_handleInteraction(char* data){ + NSDictionary *json = deserilizeJson(data); + [Zapic handleInteractionData:json]; + } +} diff --git a/Assets/Zapic/Plugins/iOS/ZapicInterface.mm.meta b/Assets/Zapic/Plugins/iOS/ZapicInterface.mm.meta new file mode 100644 index 0000000..f79549f --- /dev/null +++ b/Assets/Zapic/Plugins/iOS/ZapicInterface.mm.meta @@ -0,0 +1,34 @@ +fileFormatVersion: 2 +guid: e60d3cce6467c46d591483c811ee843a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + - first: + tvOS: tvOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Zapic/Zapic.cs b/Assets/Zapic/Zapic.cs index ede76d5..04a76a0 100644 --- a/Assets/Zapic/Zapic.cs +++ b/Assets/Zapic/Zapic.cs @@ -82,6 +82,15 @@ public static void ShowDefaultPage() /// /// Page to show. public static void ShowPage(ZapicPages page) + { + _interface.ShowPage(page.ToString()); + } + + /// + /// Shows the given Zapic page + /// + /// Page to show. + public static void ShowPage(string page) { _interface.ShowPage(page); } @@ -112,4 +121,4 @@ public static void SubmitEvent(Dictionary param) { _interface.SubmitEvent(param); } -} +} \ No newline at end of file diff --git a/Assets/Zapic/ZapicAndroidInterface.cs b/Assets/Zapic/ZapicAndroidInterface.cs index 1745dad..56ab5ed 100644 --- a/Assets/Zapic/ZapicAndroidInterface.cs +++ b/Assets/Zapic/ZapicAndroidInterface.cs @@ -26,10 +26,10 @@ public void Start() private void StartOnUI() { - using (var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) + using(var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) { - using (var unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) - using (var gameActivityObject = unityPlayerClass.GetStatic("currentActivity")) + using(var unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) + using(var gameActivityObject = unityPlayerClass.GetStatic("currentActivity")) { var methodId = AndroidJNI.GetStaticMethodID( zapicClass.GetRawClass(), @@ -52,9 +52,9 @@ private void StartOnUI() { _authenticationHandler = new ZapicPlayerAuthenticationHandler(this); var methodId = AndroidJNI.GetStaticMethodID( - zapicClass.GetRawClass(), - "setPlayerAuthenticationHandler", - "(Lcom/zapic/sdk/android/ZapicPlayerAuthenticationHandler;)V"); + zapicClass.GetRawClass(), + "setPlayerAuthenticationHandler", + "(Lcom/zapic/sdk/android/ZapicPlayerAuthenticationHandler;)V"); var objectArray = new object[1]; var argArray = AndroidJNIHelper.CreateJNIArgArray(objectArray); try @@ -72,9 +72,9 @@ private void StartOnUI() public void ShowDefaultPage() { - using (var unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) - using (var gameActivityObject = unityPlayerClass.GetStatic("currentActivity")) - using (var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) + using(var unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) + using(var gameActivityObject = unityPlayerClass.GetStatic("currentActivity")) + using(var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) { var methodId = AndroidJNI.GetStaticMethodID( zapicClass.GetRawClass(), @@ -94,12 +94,12 @@ public void ShowDefaultPage() } } - public void ShowPage(ZapicPages page) + public void ShowPage(string page) { - using (var unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) - using (var gameActivityObject = unityPlayerClass.GetStatic("currentActivity")) - using (var pageObject = new AndroidJavaObject("java.lang.String", page.ToString().ToLower())) - using (var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) + using(var unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) + using(var gameActivityObject = unityPlayerClass.GetStatic("currentActivity")) + using(var pageObject = new AndroidJavaObject("java.lang.String", page.ToLower())) + using(var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) { var methodId = AndroidJNI.GetStaticMethodID( zapicClass.GetRawClass(), @@ -123,7 +123,7 @@ public void ShowPage(ZapicPages page) public ZapicPlayer Player() { var playerPointer = IntPtr.Zero; - using (var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) + using(var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) { var methodId = AndroidJNI.GetStaticMethodID( zapicClass.GetRawClass(), @@ -160,8 +160,8 @@ public void HandleInteraction(Dictionary data) { var json = MiniJSON.Json.Serialize(data); - using (var parametersObject = new AndroidJavaObject("java.lang.String", json)) - using (var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) + using(var parametersObject = new AndroidJavaObject("java.lang.String", json)) + using(var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) { var methodId = AndroidJNI.GetStaticMethodID( zapicClass.GetRawClass(), @@ -185,8 +185,8 @@ public void SubmitEvent(Dictionary param) { var json = MiniJSON.Json.Serialize(param); - using (var parametersObject = new AndroidJavaObject("java.lang.String", json)) - using (var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) + using(var parametersObject = new AndroidJavaObject("java.lang.String", json)) + using(var zapicClass = new AndroidJavaClass("com.zapic.sdk.android.Zapic")) { var methodId = AndroidJNI.GetStaticMethodID( zapicClass.GetRawClass(), @@ -215,7 +215,7 @@ private static ZapicPlayer ConvertPlayer(IntPtr playerPointer) string notificationToken; string playerId; - using (var zapicPlayerClass = new AndroidJavaClass("com.zapic.sdk.android.ZapicPlayer")) + using(var zapicPlayerClass = new AndroidJavaClass("com.zapic.sdk.android.ZapicPlayer")) { var methodId = AndroidJNI.GetMethodID( zapicPlayerClass.GetRawClass(), @@ -251,7 +251,7 @@ private static ZapicPlayer ConvertPlayer(IntPtr playerPointer) return new ZapicPlayer { NotificationToken = notificationToken ?? string.Empty, - PlayerId = playerId ?? string.Empty, + PlayerId = playerId ?? string.Empty, }; } @@ -259,8 +259,7 @@ private sealed class ZapicPlayerAuthenticationHandler : AndroidJavaProxy, IDispo { private IZapicInterface _zapicInterface; - public ZapicPlayerAuthenticationHandler(IZapicInterface zapicInterface) - : base("com.zapic.sdk.android.ZapicPlayerAuthenticationHandler") + public ZapicPlayerAuthenticationHandler(IZapicInterface zapicInterface) : base("com.zapic.sdk.android.ZapicPlayerAuthenticationHandler") { _zapicInterface = zapicInterface; } @@ -295,4 +294,4 @@ public void onLogout(AndroidJavaObject androidPlayer) } } } -} +} \ No newline at end of file diff --git a/Assets/Zapic/ZapicEditorInterface.cs b/Assets/Zapic/ZapicEditorInterface.cs index d450567..c50e9f9 100644 --- a/Assets/Zapic/ZapicEditorInterface.cs +++ b/Assets/Zapic/ZapicEditorInterface.cs @@ -85,7 +85,7 @@ public void ShowDefaultPage() Debug.LogFormat("Zapic:Show Default page"); } - public void ShowPage(ZapicPages page) + public void ShowPage(string page) { CheckStarted(); Debug.LogFormat("Zapic:Show {0}", page); @@ -130,4 +130,4 @@ public void HandleInteraction(Dictionary data) Debug.LogFormat("Zapic:HandleInteraction"); } } -} +} \ No newline at end of file diff --git a/Assets/Zapic/ZapiciOSInterface.cs b/Assets/Zapic/ZapiciOSInterface.cs index 4d51bd2..fb7b45e 100644 --- a/Assets/Zapic/ZapiciOSInterface.cs +++ b/Assets/Zapic/ZapiciOSInterface.cs @@ -6,56 +6,60 @@ namespace ZapicSDK { + internal struct ZPCUPlayer + { + public string id; + + public string notificationToken; + } + internal sealed class ZapiciOSInterface : IZapicInterface { - private delegate void internal_PlayerLogin(string playerJson); + private delegate void internal_PlayerLogin(ZPCUPlayer player); - private delegate void internal_PlayerLogout(string playerJson); + private delegate void internal_PlayerLogout(ZPCUPlayer player); #region DLLImports [DllImport("__Internal")] - private static extern void z_start(); + private static extern void zpc_start(); [DllImport("__Internal")] - private static extern void z_showDefault(); + private static extern void zpc_showDefault(); [DllImport("__Internal")] - private static extern void z_show(string pageName); + private static extern void zpc_show(string pageName); [DllImport("__Internal")] - private static extern void z_submitEventWithParams(string eventJson); + private static extern void zpc_submitEventWithParams(string eventJson); [DllImport("__Internal")] - private static extern void z_handleInteraction(string dataJson); + private static extern void zpc_handleInteraction(string dataJson); [DllImport("__Internal")] - private static extern void z_setLoginHandler(internal_PlayerLogin loginCallback); + private static extern void zpc_setLoginHandler(internal_PlayerLogin loginCallback); [DllImport("__Internal")] - private static extern void z_setLogoutHandler(internal_PlayerLogin logoutCallback); + private static extern void zpc_setLogoutHandler(internal_PlayerLogin logoutCallback); [DllImport("__Internal")] - private static extern string z_player(); + private static extern ZPCUPlayer zpc_player(); [MonoPInvokeCallback(typeof(internal_PlayerLogin))] - private static void _player_login(string playerJson) + private static void _player_login(ZPCUPlayer p) { if (_loginHandler == null) return; - var player = DeserializePlayer(playerJson); - _loginHandler(player); + _loginHandler(p.ToPlayer()); } [MonoPInvokeCallback(typeof(internal_PlayerLogout))] - private static void _player_logout(string playerJson) + private static void _player_logout(ZPCUPlayer p) { if (_logoutHandler == null) return; - - var player = DeserializePlayer(playerJson); - _logoutHandler(player); + _logoutHandler(p.ToPlayer()); } #endregion DLLImports @@ -66,8 +70,8 @@ private static void _player_logout(string playerJson) public ZapiciOSInterface() { - z_setLoginHandler(_player_login); - z_setLogoutHandler(_player_logout); + zpc_setLoginHandler(_player_login); + zpc_setLogoutHandler(_player_logout); } public Action OnLogin @@ -103,7 +107,7 @@ public Action OnLogout /// App version id. public void Start() { - z_start(); + zpc_start(); } /// @@ -111,35 +115,33 @@ public void Start() /// public void ShowDefaultPage() { - z_showDefault(); + zpc_showDefault(); } /// /// Shows the given Zapic page /// /// Page to show. - public void ShowPage(ZapicPages page) + public void ShowPage(string page) { - z_show(page.ToString().ToLower()); + zpc_show(page.ToLower()); } - /// /// Gets the current player /// /// The player. public ZapicPlayer Player() { - var playerJson = z_player(); - var player = DeserializePlayer(playerJson); - return player; + var p = zpc_player(); + return p.ToPlayer(); } public void HandleInteraction(Dictionary data) { var json = Json.Serialize(data); - z_handleInteraction(json); + zpc_handleInteraction(json); } /// @@ -150,27 +152,19 @@ public void SubmitEvent(Dictionary param) { var json = Json.Serialize(param); - z_submitEventWithParams(json); + zpc_submitEventWithParams(json); } + } - private static ZapicPlayer DeserializePlayer(string playerJson) + internal static class ZapicExtensions + { + internal static ZapicPlayer ToPlayer(this ZPCUPlayer p) { - UnityEngine.Debug.Log("Deserializing " + playerJson); - if (playerJson == null) - { - UnityEngine.Debug.Log("Null player deserialized"); - return null; - } - - var dict = Json.Deserialize(playerJson) as Dictionary; - - var player = new ZapicPlayer + return new ZapicPlayer { - PlayerId = (string)dict["playerId"], - NotificationToken = (string)dict["notificationToken"], + PlayerId = p.id, + NotificationToken = p.notificationToken }; - - return player; } } -} +} \ No newline at end of file diff --git a/Scripts/install-ios-sdk.sh b/Scripts/install-ios-sdk.sh new file mode 100755 index 0000000..4c0f0f0 --- /dev/null +++ b/Scripts/install-ios-sdk.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# + +bold=$(tput bold) +normal=$(tput sgr0) + +echo "" +echo "====================================" +echo " Copying iOS source files " +echo "====================================" +echo "" + +#Repo to clone +reporUrl=https://github.com/ZapicInc/Zapic-SDK-iOS.git +#TODO:switch to the proper version/tag +iOS_REPO=./zapic-ios +iOS_PLUGIN=../Assets/Plugins/iOS/Zapic + +#Ensure the repo directory is clear +rm -rf $iOS_REPO + +#Ensure the plugin directory is clear +rm -rf $iOS_PLUGIN + +#Clone the repo +git clone $reporUrl $iOS_REPO + +#Ensure the dir exists +mkdir -p $iOS_PLUGIN + +#Copy the source code into the plugin folder +cp -r $iOS_REPO/Zapic/. $iOS_PLUGIN/ + +#Remove the repo +rm -rf $iOS_REPO + +echo "" +echo "====================================" +echo " Done! " +echo "====================================" +echo ""