| @@ -227,11 +227,20 @@ public: | |||
| props.add (new BooleanPropertyComponent (getMicrophonePermissionValue(), "Microphone access", "Enabled"), | |||
| "Enable this to allow your app to use the microphone. " | |||
| "The user of your app will be prompted to grant microphone access permissions."); | |||
| } | |||
| else if (projectType.isGUIApplication()) | |||
| { | |||
| props.add (new TextPropertyComponent (getSetting ("documentExtensions"), "Document file extensions", 128, false), | |||
| "A comma-separated list of file extensions for documents that your app can open. " | |||
| "Using a leading '.' is optional, and the extensions are not case-sensitive."); | |||
| } | |||
| props.add (new BooleanPropertyComponent (getInAppPurchasesValue(), "In-App purchases capability", "Enabled"), | |||
| "Enable this to grant your app the capability for in-app purchases. " | |||
| "This option requires that you specify a valid Development Team ID."); | |||
| props.add (new BooleanPropertyComponent (getInAppPurchasesValue(), "In-App purchases capability", "Enabled"), | |||
| "Enable this to grant your app the capability for in-app purchases. " | |||
| "This option requires that you specify a valid Development Team ID."); | |||
| if (iOS) | |||
| { | |||
| props.add (new BooleanPropertyComponent (getBackgroundAudioValue(), "Audio background capability", "Enabled"), | |||
| "Enable this to grant your app the capability to access audio when in background mode."); | |||
| @@ -244,12 +253,6 @@ public: | |||
| props.add (new BooleanPropertyComponent (getAppGroupsEnabledValue(), "App groups capability", "Enabled"), | |||
| "Enable this to grant your app the capability to share resources between apps using the same app group ID."); | |||
| } | |||
| else if (projectType.isGUIApplication()) | |||
| { | |||
| props.add (new TextPropertyComponent (getSetting ("documentExtensions"), "Document file extensions", 128, false), | |||
| "A comma-separated list of file extensions for documents that your app can open. " | |||
| "Using a leading '.' is optional, and the extensions are not case-sensitive."); | |||
| } | |||
| props.add (new TextPropertyComponent (getPListToMergeValue(), "Custom PList", 8192, true), | |||
| "You can paste the contents of an XML PList file in here, and the settings that it contains will override any " | |||
| @@ -783,7 +786,7 @@ public: | |||
| attributes << "DevelopmentTeam = " << developmentTeamID << "; "; | |||
| auto appGroupsEnabled = (owner.iOS && owner.isAppGroupsEnabled() ? 1 : 0); | |||
| auto inAppPurchasesEnabled = (owner.iOS && owner.isInAppPurchasesEnabled()) ? 1 : 0; | |||
| auto inAppPurchasesEnabled = owner.isInAppPurchasesEnabled() ? 1 : 0; | |||
| auto interAppAudioEnabled = (owner.iOS | |||
| && type == Target::StandalonePlugIn | |||
| && owner.getProject().shouldEnableIAA()) ? 1 : 0; | |||
| @@ -1059,7 +1062,7 @@ public: | |||
| s.add ("SEPARATE_STRIP = YES"); | |||
| } | |||
| if (owner.iOS && owner.isInAppPurchasesEnabled()) | |||
| if (owner.isInAppPurchasesEnabled()) | |||
| defines.set ("JUCE_IN_APP_PURCHASES", "1"); | |||
| defines = mergePreprocessorDefs (defines, owner.getAllPreprocessorDefs (config, type)); | |||
| @@ -2146,7 +2149,7 @@ private: | |||
| { | |||
| if (! projectType.isStaticLibrary()) | |||
| { | |||
| if (iOS && isInAppPurchasesEnabled()) | |||
| if (isInAppPurchasesEnabled()) | |||
| xcodeFrameworks.addIfNotAlreadyThere ("StoreKit"); | |||
| xcodeFrameworks.addTokens (getExtraFrameworksString(), ",;", "\"'"); | |||
| @@ -28,7 +28,7 @@ namespace juce | |||
| { | |||
| InAppPurchases::InAppPurchases() | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| : pimpl (new Pimpl (*this)) | |||
| #endif | |||
| {} | |||
| @@ -37,7 +37,7 @@ InAppPurchases::~InAppPurchases() {} | |||
| bool InAppPurchases::isInAppPurchasesSupported() const | |||
| { | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| return pimpl->isInAppPurchasesSupported(); | |||
| #else | |||
| return false; | |||
| @@ -46,7 +46,7 @@ bool InAppPurchases::isInAppPurchasesSupported() const | |||
| void InAppPurchases::getProductsInformation (const StringArray& productIdentifiers) | |||
| { | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| pimpl->getProductsInformation (productIdentifiers); | |||
| #else | |||
| Array<Product> products; | |||
| @@ -62,7 +62,7 @@ void InAppPurchases::purchaseProduct (const String& productIdentifier, | |||
| const StringArray& upgradeProductIdentifiers, | |||
| bool creditForUnusedSubscription) | |||
| { | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| pimpl->purchaseProduct (productIdentifier, isSubscription, | |||
| upgradeProductIdentifiers, creditForUnusedSubscription); | |||
| #else | |||
| @@ -75,7 +75,7 @@ void InAppPurchases::purchaseProduct (const String& productIdentifier, | |||
| void InAppPurchases::restoreProductsBoughtList (bool includeDownloadInfo, const String& subscriptionsSharedSecret) | |||
| { | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| pimpl->restoreProductsBoughtList (includeDownloadInfo, subscriptionsSharedSecret); | |||
| #else | |||
| listeners.call (&Listener::purchasesListRestored, Array<Listener::PurchaseInfo>(), false, "In-app purchases unavailable"); | |||
| @@ -85,7 +85,7 @@ void InAppPurchases::restoreProductsBoughtList (bool includeDownloadInfo, const | |||
| void InAppPurchases::consumePurchase (const String& productIdentifier, const String& purchaseToken) | |||
| { | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| pimpl->consumePurchase (productIdentifier, purchaseToken); | |||
| #else | |||
| listeners.call (&Listener::productConsumed, productIdentifier, false, "In-app purchases unavailable"); | |||
| @@ -98,7 +98,7 @@ void InAppPurchases::removeListener (Listener* l) { listeners.remove (l); } | |||
| void InAppPurchases::startDownloads (const Array<Download*>& downloads) | |||
| { | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| pimpl->startDownloads (downloads); | |||
| #else | |||
| ignoreUnused (downloads); | |||
| @@ -107,7 +107,7 @@ void InAppPurchases::startDownloads (const Array<Download*>& downloads) | |||
| void InAppPurchases::pauseDownloads (const Array<Download*>& downloads) | |||
| { | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| pimpl->pauseDownloads (downloads); | |||
| #else | |||
| ignoreUnused (downloads); | |||
| @@ -116,7 +116,7 @@ void InAppPurchases::pauseDownloads (const Array<Download*>& downloads) | |||
| void InAppPurchases::resumeDownloads (const Array<Download*>& downloads) | |||
| { | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| pimpl->resumeDownloads (downloads); | |||
| #else | |||
| ignoreUnused (downloads); | |||
| @@ -125,7 +125,7 @@ void InAppPurchases::resumeDownloads (const Array<Download*>& downloads) | |||
| void InAppPurchases::cancelDownloads (const Array<Download*>& downloads) | |||
| { | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| pimpl->cancelDownloads (downloads); | |||
| #else | |||
| ignoreUnused (downloads); | |||
| @@ -267,7 +267,7 @@ private: | |||
| friend void juce_inAppPurchaseCompleted (void*); | |||
| #endif | |||
| #if JUCE_ANDROID || JUCE_IOS | |||
| #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC | |||
| struct Pimpl; | |||
| friend struct Pimpl; | |||
| @@ -51,8 +51,8 @@ | |||
| #if JUCE_IN_APP_PURCHASES | |||
| #if JUCE_ANDROID | |||
| #include "native/juce_android_InAppPurchases.cpp" | |||
| #elif JUCE_IOS | |||
| #include "native/juce_ios_InAppPurchases.cpp" | |||
| #elif JUCE_IOS || JUCE_MAC | |||
| #include "native/juce_ios_InAppPurchases.cpp" | |||
| #endif | |||
| #include "in_app_purchases/juce_InAppPurchases.cpp" | |||
| @@ -100,9 +100,15 @@ struct InAppPurchases::Pimpl : public SKDelegateAndPaymentObserver | |||
| DownloadImpl (SKDownload* downloadToUse) : download (downloadToUse) {} | |||
| String getProductId() const override { return nsStringToJuce (download.contentIdentifier); } | |||
| int64 getContentLength() const override { return download.contentLength; } | |||
| String getContentVersion() const override { return nsStringToJuce (download.contentVersion); } | |||
| #if JUCE_IOS | |||
| int64 getContentLength() const override { return download.contentLength; } | |||
| Status getStatus() const override { return SKDownloadStateToDownloadStatus (download.downloadState); } | |||
| #else | |||
| int64 getContentLength() const override { return [download.contentLength longLongValue]; } | |||
| Status getStatus() const override { return SKDownloadStateToDownloadStatus (download.state); } | |||
| #endif | |||
| SKDownload* download; | |||
| }; | |||
| @@ -146,9 +152,14 @@ struct InAppPurchases::Pimpl : public SKDelegateAndPaymentObserver | |||
| { | |||
| for (SKDownload* d in transaction.downloads) | |||
| { | |||
| if (d.downloadState != SKDownloadStateFinished | |||
| && d.downloadState != SKDownloadStateFailed | |||
| && d.downloadState != SKDownloadStateCancelled) | |||
| #if JUCE_IOS | |||
| SKDownloadState state = d.downloadState; | |||
| #else | |||
| SKDownloadState state = d.state; | |||
| #endif | |||
| if (state != SKDownloadStateFinished | |||
| && state != SKDownloadStateFailed | |||
| && state != SKDownloadStateCancelled) | |||
| { | |||
| return false; | |||
| } | |||
| @@ -308,7 +319,11 @@ struct InAppPurchases::Pimpl : public SKDelegateAndPaymentObserver | |||
| { | |||
| if (auto* pendingDownload = getPendingDownloadFor (download)) | |||
| { | |||
| #if JUCE_IOS | |||
| switch (download.downloadState) | |||
| #else | |||
| switch (download.state) | |||
| #endif | |||
| { | |||
| case SKDownloadStateWaiting: break; | |||
| case SKDownloadStatePaused: owner.listeners.call (&Listener::productDownloadPaused, *pendingDownload); break; | |||
| @@ -467,7 +482,13 @@ struct InAppPurchases::Pimpl : public SKDelegateAndPaymentObserver | |||
| { | |||
| if (auto* pdt = getPendingDownloadsTransactionSKDownloadFor (download)) | |||
| { | |||
| auto contentURL = download.downloadState == SKDownloadStateFinished | |||
| #if JUCE_IOS | |||
| SKDownloadState state = download.downloadState; | |||
| #else | |||
| SKDownloadState state = download.state; | |||
| #endif | |||
| auto contentURL = state == SKDownloadStateFinished | |||
| ? URL (nsStringToJuce (download.contentURL.absoluteString)) | |||
| : URL(); | |||