This commit is contained in:
Henrik Rydgård committed 2025-05-25 11:22:04 +02:00
1 parent 445de0b5f4
commit 2dbb54667d
22 files changed
+322 -24

No files matched your search

+5 -1
View File
@@ -1334,6 +1334,8 @@ elseif(IOS AND NOT LIBRETRO)
ios/ViewControllerMetal.h
ios/iOSCoreAudio.mm
ios/iOSCoreAudio.h
ios/IAPManager.mm
ios/IAPManager.h
ios/CameraHelper.mm
ios/CameraHelper.h
ios/LocationHelper.mm
@@ -1536,6 +1538,8 @@ list(APPEND NativeAppSource
UI/EmuScreen.cpp
UI/GameInfoCache.h
UI/GameInfoCache.cpp
UI/IAPScreen.cpp
UI/IAPScreen.h
UI/MainScreen.h
UI/MainScreen.cpp
UI/MiscScreens.h
@@ -3011,7 +3015,7 @@ if(IOS AND NOT LIBRETRO)
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${DEVELOPMENT_TEAM_ID}
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Development"
XCODE_ATTRIBUTE_CODE_SIGN_STYLE "Automatic"
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${BUNDLE_ENTITLEMENTS}
#XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${BUNDLE_ENTITLEMENTS}
XCODE_ATTRIBUTE_SKIP_INSTALL NO
XCODE_ATTRIBUTE_INSTALL_PATH "$(LOCAL_APPS_DIR)"
)
+1
View File
@@ -53,6 +53,7 @@ enum class Log {
TexReplacement,
GeDebugger,
UI,
IAP,
sceAudio,
sceCtrl,
+1
View File
@@ -92,6 +92,7 @@ static const char * const g_logTypeNames[] = {
"TEXREPLACE",
"DEBUGGER",
"UI",
"IAP",
"SCEAUDIO",
"SCECTRL",
"SCEDISP",
+8
View File
@@ -192,6 +192,14 @@ inline void System_SendDebugScreenshot(std::string_view data, int height) {
g_requestManager.MakeSystemRequest(SystemRequestType::SEND_DEBUG_SCREENSHOT, NO_REQUESTER_TOKEN, nullptr, nullptr, data, "", height);
}
inline void System_IAPRestorePurchases(RequesterToken token, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
g_requestManager.MakeSystemRequest(SystemRequestType::IAP_RESTORE_PURCHASES, token, callback, failedCallback, "", "", 0);
}
inline void System_IAPMakePurchase(RequesterToken token, std::string_view productID, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
g_requestManager.MakeSystemRequest(SystemRequestType::IAP_MAKE_PURCHASE, token, callback, failedCallback, productID, "", 0);
}
void System_MoveToTrash(const Path &path);
void System_RunCallbackInWndProc(void (*callback)(void *, void *), void *userdata);
+6
View File
@@ -100,6 +100,10 @@ enum class SystemRequestType {
RUN_CALLBACK_IN_WNDPROC,
MOVE_TO_TRASH,
// for iOS IAP support
IAP_RESTORE_PURCHASES,
IAP_MAKE_PURCHASE,
};
// Run a closure on the main thread. Used to safely implement UI that runs on another thread.
@@ -224,6 +228,8 @@ enum SystemProperty {
SYSPROP_ENOUGH_RAM_FOR_FULL_ISO,
SYSPROP_HAS_TRASH_BIN,
SYSPROP_USE_IAP,
};
enum class SystemNotification {
+14 -1
View File
@@ -693,7 +693,7 @@ bool System_GetPropertyBool(SystemProperty prop) {
#ifdef GOLD
return true;
#else
return false;
return true;
#endif
case SYSPROP_CAN_JIT:
return true;
@@ -724,6 +724,10 @@ case SYSPROP_HAS_FILE_BROWSER:
#else
return true;
#endif
// hack for testing - do not commit
case SYSPROP_USE_IAP:
return false;
default:
return false;
}
@@ -999,6 +1003,15 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta
System_PostUIMessage(UIMessage::REQUEST_GAME_RESET);
Core_Resume();
}
/*
// TODO: Enable this?
if (k == SDLK_F11) {
#if !defined(MOBILE_DEVICE)
g_Config.bFullScreen = !g_Config.bFullScreen;
System_ToggleFullscreenState("");
#endif
}
*/
}
break;
}
+1 -1
View File
@@ -184,7 +184,7 @@ void DeveloperToolsScreen::CreateGeneralTab(UI::LinearLayout *list) {
});
#endif
#if PPSSPP_PLATFORM(IOS_APP_STORE)
#if PPSSPP_PLATFORM(IOS)
list->Add(new NoticeView(NoticeLevel::WARN, ms->T("Moving the memstick directory is NOT recommended on iOS"), ""));
list->Add(new Choice(sy->T("Set Memory Stick folder")))->OnClick.Add(
[=](UI::EventParams &) {
-3
View File
@@ -781,9 +781,6 @@ void EmuScreen::onVKey(VirtKey virtualKeyCode, bool down) {
case VIRTKEY_PAUSE:
if (down) {
// Trigger on key-up to partially avoid repetition problems.
// This is needed whenever we pop up a menu since the mapper
// might miss the key-up. Same as VIRTKEY_OPENCHAT.
// Note: We don't check NetworkWarnUserIfOnlineAndCantSpeed, because we can keep
// running in the background of the menu.
pauseTrigger_ = true;
+3
View File
@@ -210,4 +210,7 @@ private:
};
void TriggerRestart(const char *why, bool editThenRestore, const Path &gamePath);
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
void SetMemStickDirDarwin(int requesterToken);
#endif
+67
View File
@@ -0,0 +1,67 @@
// NOTE: This is only used on iOS, to present the availablility of getting PPSSPP Gold through IAP.
#include "UI/IAPScreen.h"
#include "Common/System/System.h"
#include "Common/Data/Text/I18n.h"
#include "Common/System/OSD.h"
void IAPScreen::CreateViews() {
using namespace UI;
auto di = GetI18NCategory(I18NCat::DIALOG);
auto mm = GetI18NCategory(I18NCat::MAINMENU);
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
const bool bought = System_GetPropertyBool(SYSPROP_APP_GOLD);
if (bought) {
root_->Add(new TextView("You have PPSSPP Gold! Thank you!"));
} else {
root_->Add(new TextView("PPSSPP Gold", ALIGN_LEFT | FLAG_WRAP_TEXT, false, new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, 15, 105, 330, 10)))->SetClip(false);
}
ViewGroup *rightColumnItems = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(300, WRAP_CONTENT, NONE, 105, 15, NONE));
root_->Add(rightColumnItems);
if (!bought) {
Choice *buyButton = rightColumnItems->Add(new Choice(mm->T("Buy PPSSPP Gold")));
const int requesterToken = GetRequesterToken();
buyButton->OnClick.Add([this, requesterToken](UI::EventParams &) {
INFO_LOG(Log::System, "Showing purchase UI...");
System_IAPMakePurchase(requesterToken, "org.ppsspp.gold", [this](const char *responseString, int intValue) {
INFO_LOG(Log::System, "Purchase successful!");
RecreateViews();
}, []() {
WARN_LOG(Log::System, "Purchase failed or cancelled!");
});
// TODO: What do we do here?
return UI::EVENT_DONE;
});
}
Choice *moreInfo = rightColumnItems->Add(new Choice(di->T("More info")));
moreInfo->OnClick.Add([](UI::EventParams &) {
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/docs/reference/whygold/");
return UI::EVENT_DONE;
});
Choice *backButton = rightColumnItems->Add(new Choice(di->T("Back")));
backButton->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
// Put the restore purchases button in the bottom right corner. It's rarely useful, but needed.
rightColumnItems->Add(new Spacer(new LinearLayoutParams(1.0f)));
Choice *restorePurchases = new Choice(di->T("Restore purchase"));
const int requesterToken = GetRequesterToken();
restorePurchases->OnClick.Add([requesterToken, restorePurchases](UI::EventParams &) {
restorePurchases->SetEnabled(false);
INFO_LOG(Log::System, "Requesting purchase restore");
System_IAPRestorePurchases(requesterToken, [restorePurchases](const char *responseString, int) {
INFO_LOG(Log::System, "Successfully restored purchases!");
}, []() {
WARN_LOG(Log::System, "Failed restoring purchases");
});
return UI::EVENT_DONE;
});
rightColumnItems->Add(restorePurchases);
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
// NOTE: This is only used on iOS, to present the availablility of getting PPSSPP Gold through IAP.
#include "ppsspp_config.h"
#include "UI/MiscScreens.h"
class IAPScreen : public UIDialogScreenWithBackground {
public:
void CreateViews() override;
const char *tag() const override { return "IAP"; }
};
+8 -3
View File
@@ -57,6 +57,7 @@
#include "UI/GameSettingsScreen.h"
#include "UI/MiscScreens.h"
#include "UI/ControlMappingScreen.h"
#include "UI/IAPScreen.h"
#include "UI/RemoteISOScreen.h"
#include "UI/DisplayLayoutScreen.h"
#include "UI/SavedataScreen.h"
@@ -1579,13 +1580,17 @@ UI::EventReturn MainScreen::OnCredits(UI::EventParams &e) {
}
void LaunchBuyGold(ScreenManager *screenManager) {
if (System_GetPropertyBool(SYSPROP_USE_IAP)) {
screenManager->push(new IAPScreen());
} else {
#if PPSSPP_PLATFORM(IOS_APP_STORE)
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://apps.apple.com/us/app/ppsspp-gold-psp-emulator/id6502287918");
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://apps.apple.com/us/app/ppsspp-gold-psp-emulator/id6502287918");
#elif PPSSPP_PLATFORM(ANDROID)
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "market://details?id=org.ppsspp.ppssppgold");
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "market://details?id=org.ppsspp.ppssppgold");
#else
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/buygold");
System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/buygold");
#endif
}
}
UI::EventReturn MainScreen::OnPPSSPPOrg(UI::EventParams &e) {
+3 -1
View File
@@ -52,6 +52,7 @@
<ClCompile Include="GameScreen.cpp" />
<ClCompile Include="GameSettingsScreen.cpp" />
<ClCompile Include="GPUDriverTestScreen.cpp" />
<ClCompile Include="IAPScreen.cpp" />
<ClCompile Include="ImDebugger\ImConsole.cpp" />
<ClCompile Include="ImDebugger\ImDebugger.cpp" />
<ClCompile Include="ImDebugger\ImDisasmView.cpp" />
@@ -99,6 +100,7 @@
<ClInclude Include="GameSettingsScreen.h" />
<ClInclude Include="CwCheatScreen.h" />
<ClInclude Include="GPUDriverTestScreen.h" />
<ClInclude Include="IAPScreen.h" />
<ClInclude Include="ImDebugger\ImConsole.h" />
<ClInclude Include="ImDebugger\ImDebugger.h" />
<ClInclude Include="ImDebugger\ImDisasmView.h" />
@@ -434,4 +436,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+7 -1
View File
@@ -18,6 +18,9 @@
</ClCompile>
<ClCompile Include="MiscScreens.cpp">
<Filter>Screens</Filter>
</ClCompile>
<ClCompile Include="IAPScreen.cpp">
<Filter>Screens</Filter>
</ClCompile>
<ClCompile Include="ControlMappingScreen.cpp">
<Filter>Screens</Filter>
@@ -137,6 +140,9 @@
</ClInclude>
<ClInclude Include="MiscScreens.h">
<Filter>Screens</Filter>
</ClInclude>
<ClInclude Include="IAPScreen.h">
<Filter>Screens</Filter>
</ClInclude>
<ClInclude Include="ControlMappingScreen.h">
<Filter>Screens</Filter>
@@ -250,4 +256,4 @@
<UniqueIdentifier>{fda6bc55-1386-4650-a274-44fac9605ea3}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>
+3 -1
View File
@@ -142,6 +142,7 @@
<ClInclude Include="..\..\UI\MainScreen.h" />
<ClInclude Include="..\..\UI\MemStickScreen.h" />
<ClInclude Include="..\..\UI\MiscScreens.h" />
<ClInclude Include="..\..\UI\IAPScreen.h" />
<ClInclude Include="..\..\UI\OnScreenDisplay.h" />
<ClInclude Include="..\..\UI\PauseScreen.h" />
<ClInclude Include="..\..\UI\ProfilerDraw.h" />
@@ -189,6 +190,7 @@
<ClCompile Include="..\..\UI\MainScreen.cpp" />
<ClCompile Include="..\..\UI\MemStickScreen.cpp" />
<ClCompile Include="..\..\UI\MiscScreens.cpp" />
<ClCompile Include="..\..\UI\IAPScreen.cpp" />
<ClCompile Include="..\..\UI\NativeApp.cpp" />
<ClCompile Include="..\..\UI\OnScreenDisplay.cpp" />
<ClCompile Include="..\..\UI\PauseScreen.cpp" />
@@ -218,4 +220,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+3 -1
View File
@@ -18,6 +18,7 @@
<ClCompile Include="..\..\UI\MainScreen.cpp" />
<ClCompile Include="..\..\UI\MemStickScreen.cpp" />
<ClCompile Include="..\..\UI\MiscScreens.cpp" />
<ClCompile Include="..\..\UI\IAPScreen.cpp" />
<ClCompile Include="..\..\UI\NativeApp.cpp" />
<ClCompile Include="..\..\UI\OnScreenDisplay.cpp" />
<ClCompile Include="..\..\UI\PauseScreen.cpp" />
@@ -78,6 +79,7 @@
<ClInclude Include="..\..\UI\MainScreen.h" />
<ClInclude Include="..\..\UI\MemStickScreen.h" />
<ClInclude Include="..\..\UI\MiscScreens.h" />
<ClInclude Include="..\..\UI\IAPScreen.h" />
<ClInclude Include="..\..\UI\OnScreenDisplay.h" />
<ClInclude Include="..\..\UI\PauseScreen.h" />
<ClInclude Include="..\..\UI\ProfilerDraw.h" />
@@ -123,4 +125,4 @@
<UniqueIdentifier>{4013cb89-6145-451c-9cb1-d63d01f66bd5}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>
+1
View File
@@ -908,6 +908,7 @@ LOCAL_SRC_FILES := \
$(SRC)/UI/MainScreen.cpp \
$(SRC)/UI/TabbedDialogScreen.cpp \
$(SRC)/UI/MemStickScreen.cpp \
$(SRC)/UI/IAPScreen.cpp \
$(SRC)/UI/MiscScreens.cpp \
$(SRC)/UI/RemoteISOScreen.cpp \
$(SRC)/UI/ReportScreen.cpp \
+3
View File
@@ -8,6 +8,7 @@
#import "Core/System.h"
#import "Core/Config.h"
#import "Common/Log.h"
#import "IAPManager.h"
#import <AVFoundation/AVFoundation.h>
@@ -89,6 +90,8 @@
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAudioSessionInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMediaServicesWereReset:) name:AVAudioSessionMediaServicesWereResetNotification object:nil];
[IAPManager sharedIAPManager]; // Kick off the IAPManager early.
return [self launchPPSSPP:argc argv:argv];
}
+13
View File
@@ -0,0 +1,13 @@
#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>
@interface IAPManager : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver>
+ (instancetype)sharedIAPManager;
- (void)buyGoldWithRequestID:(int)requestID;
- (void)restorePurchasesWithRequestID:(int)requestID;
- (BOOL)isGoldUnlocked;
- (void)startObserving;
@end
+136
View File
@@ -0,0 +1,136 @@
#import "IAPManager.h"
#import <UIKit/UIKit.h>
#include "Common/System/Request.h"
#include "Common/Log.h"
// Only one operation can be in progress at once.
@implementation IAPManager {
SKProduct *_goldProduct;
int _pendingRequestID;
}
+ (instancetype)sharedIAPManager {
static IAPManager *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[self alloc] init];
});
return shared;
}
- (instancetype)init {
if (self = [super init]) {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
return self;
}
- (void)startObserving {
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
- (BOOL)isGoldUnlocked {
return [[NSUserDefaults standardUserDefaults] boolForKey:@"isGold"];
}
- (void)buyGoldWithRequestID:(int)requestID {
if (_pendingRequestID) {
ERROR_LOG(Log::IAP, "A transaction is pending. Failing the new request.");
g_requestManager.PostSystemFailure(requestID);
return;
}
_pendingRequestID = requestID;
if ([SKPaymentQueue canMakePayments]) {
NSSet *productIds = [NSSet setWithObject:@"org.ppsspp.gold"];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIds];
request.delegate = self;
[request start];
} else {
NSLog(@"[IAPManager] In-App Purchases are disabled (requestID: %d)", requestID);
g_requestManager.PostSystemFailure(requestID);
}
}
- (void)restorePurchasesWithRequestID:(int)requestID {
if (_pendingRequestID) {
ERROR_LOG(Log::IAP, "A transaction is pending. Failing the new request.");
g_requestManager.PostSystemFailure(requestID);
return;
}
_pendingRequestID = requestID;
INFO_LOG(Log::IAP, "Restoring purchases (id=%d)", requestID);
// NOTE: This is deprecated, but StoreKit 2 is swift only. We'll keep using it until
// there's a replacement.
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
NSLog(@"Restore completed successfully (requestID: %d)", _pendingRequestID);
g_requestManager.PostSystemSuccess(_pendingRequestID, "", 0);
_pendingRequestID = 0;
// Notify your app/UI here
}
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
NSLog(@"Restore failed (requestID: %d): %@", _pendingRequestID, error.localizedDescription);
// Notify failure to game layer
g_requestManager.PostSystemFailure(_pendingRequestID);
_pendingRequestID = 0;
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
_goldProduct = response.products.firstObject;
if (_goldProduct) {
// Received a valid product. Send a payment.
SKPayment *payment = [SKPayment paymentWithProduct:_goldProduct];
[[SKPaymentQueue defaultQueue] addPayment:payment];
} else {
NSLog(@"[IAPManager] Gold product not found (requestID: %d)", _pendingRequestID);
g_requestManager.PostSystemFailure(_pendingRequestID);
_pendingRequestID = 0;
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:
case SKPaymentTransactionStateRestored:
INFO_LOG(Log::IAP, transaction.transactionState == SKPaymentTransactionStatePurchased ? "IAP Purchase" : "IAP Restore");
// Perform the unlock (updaing the variable and switching the icon).
[self unlockGold];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
g_requestManager.PostSystemSuccess(_pendingRequestID, "", 0);
_pendingRequestID = 0;
break;
case SKPaymentTransactionStateFailed:
NSLog(@"[IAPManager] Purchase failed (requestID: %d): %@", _pendingRequestID, transaction.error.localizedDescription);
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
// Optionally post failure callback here
g_requestManager.PostSystemFailure(_pendingRequestID);
_pendingRequestID = 0;
break;
default:
break;
}
}
}
- (void)unlockGold {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isGold"];
[[NSUserDefaults standardUserDefaults] synchronize];
if ([[UIApplication sharedApplication] supportsAlternateIcons]) {
[[UIApplication sharedApplication] setAlternateIconName:@"GoldIcon"
completionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"[IAPManager] Failed to set Gold icon: %@", error.localizedDescription);
}
}];
}
NSLog(@"[IAPManager] Gold unlocked!");
}
@end
+5 -5
View File
@@ -61,13 +61,13 @@ public:
bool InitAPI();
bool InitFromRenderThread(CAMetalLayer *layer, int desiredBackbufferSizeX, int desiredBackbufferSizeY);
void ShutdownFromRenderThread(); // Inverses InitFromRenderThread.
void ShutdownFromRenderThread() override; // Inverses InitFromRenderThread.
void Shutdown();
void Resize();
void Shutdown() override;
void Resize() override;
void *GetAPIContext() { return g_Vulkan; }
Draw::DrawContext *GetDrawContext() { return draw_; }
void *GetAPIContext() override { return g_Vulkan; }
Draw::DrawContext *GetDrawContext() override { return draw_; }
private:
VulkanContext *g_Vulkan = nullptr;
+21 -6
View File
@@ -25,6 +25,7 @@
#import "PPSSPPUIApplication.h"
#import "ViewController.h"
#import "iOSCoreAudio.h"
#import "IAPManager.h"
#include "Common/MemoryUtil.h"
#include "Common/System/NativeApp.h"
@@ -372,11 +373,15 @@ bool System_GetPropertyBool(SystemProperty prop) {
// If a hardware keyboard is connected, and we add support, we could return false here.
return true;
case SYSPROP_APP_GOLD:
// TODO: Check the IAP status.
#ifdef GOLD
// This is deprecated.
return true;
#else
return false;
return [[IAPManager sharedIAPManager] isGoldUnlocked];
#endif
case SYSPROP_USE_IAP:
return true;
case SYSPROP_CAN_JIT:
return g_jitAvailable;
case SYSPROP_LIMITED_FILE_BROWSING:
@@ -426,7 +431,7 @@ void System_Notify(SystemNotification notification) {
bool System_MakeRequest(SystemRequestType type, int requestId, const std::string &param1, const std::string &param2, int64_t param3, int64_t param4) {
switch (type) {
case SystemRequestType::RESTART_APP:
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[(AppDelegate *)[[UIApplication sharedApplication] delegate] restart:param1.c_str()];
});
return true;
@@ -511,6 +516,16 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
}
return true;
}
case SystemRequestType::IAP_RESTORE_PURCHASES:
{
[[IAPManager sharedIAPManager] restorePurchasesWithRequestID:requestId];
return true;
}
case SystemRequestType::IAP_MAKE_PURCHASE:
{
[[IAPManager sharedIAPManager] buyGoldWithRequestID:requestId];
return true;
}
/*
// Not 100% sure the threading is right
case SystemRequestType::COPY_TO_CLIPBOARD:
@@ -522,10 +537,10 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
}
*/
case SystemRequestType::SET_KEEP_SCREEN_BRIGHT:
dispatch_async(dispatch_get_main_queue(), ^{
INFO_LOG(Log::System, "SET_KEEP_SCREEN_BRIGHT: %d", (int)param3);
[[UIApplication sharedApplication] setIdleTimerDisabled: (param3 ? YES : NO)];
});
dispatch_async(dispatch_get_main_queue(), ^{
INFO_LOG(Log::System, "SET_KEEP_SCREEN_BRIGHT: %d", (int)param3);
[[UIApplication sharedApplication] setIdleTimerDisabled: (param3 ? YES : NO)];
});
return true;
default:
break;