From 347551a01da643980fabfd3579ec34bb6cbb5419 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Mon, 18 Jan 2021 12:22:26 +0100 Subject: [PATCH] Android: Implement save overwrite confirmation --- .../dolphinemu/ui/main/MainPresenter.java | 37 ++++++++++++++++++- .../dolphinemu/utils/BooleanSupplier.java | 6 +++ .../dolphinemu/dolphinemu/utils/WiiUtils.java | 2 +- .../app/src/main/res/values/strings.xml | 1 + Source/Android/jni/AndroidCommon/IDCache.cpp | 13 +++++++ Source/Android/jni/AndroidCommon/IDCache.h | 2 + Source/Android/jni/WiiUtils.cpp | 11 ++++-- 7 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/BooleanSupplier.java diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java index c07fe5b388..1534b0c654 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java @@ -18,11 +18,14 @@ import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; import org.dolphinemu.dolphinemu.model.GameFileCache; import org.dolphinemu.dolphinemu.services.GameFileCacheService; import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner; +import org.dolphinemu.dolphinemu.utils.BooleanSupplier; import org.dolphinemu.dolphinemu.utils.ContentHandler; import org.dolphinemu.dolphinemu.utils.FileBrowserHelper; import org.dolphinemu.dolphinemu.utils.WiiUtils; import java.util.Arrays; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.function.Supplier; public final class MainPresenter @@ -168,9 +171,41 @@ public final class MainPresenter public void importWiiSave(String path) { + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N) + return; // TODO + + final Activity mainPresenterActivity = (Activity) mContext; + + CompletableFuture canOverwriteFuture = new CompletableFuture<>(); + runOnThreadAndShowResult(R.string.import_in_progress, () -> { - int result = WiiUtils.importWiiSave(path); + BooleanSupplier canOverwrite = () -> + { + mainPresenterActivity.runOnUiThread(() -> + { + AlertDialog.Builder builder = + new AlertDialog.Builder(mContext, R.style.DolphinDialogBase); + builder.setMessage(R.string.wii_save_exists); + builder.setCancelable(false); + builder.setPositiveButton(R.string.yes, (dialog, i) -> canOverwriteFuture.complete(true)); + builder.setNegativeButton(R.string.no, (dialog, i) -> canOverwriteFuture.complete(false)); + builder.show(); + }); + + try + { + return canOverwriteFuture.get(); + } + catch (ExecutionException | InterruptedException e) + { + // Shouldn't happen + throw new RuntimeException(e); + } + }; + + int result = WiiUtils.importWiiSave(path, canOverwrite); + int message; switch (result) { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/BooleanSupplier.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/BooleanSupplier.java new file mode 100644 index 0000000000..d1c490fe2a --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/BooleanSupplier.java @@ -0,0 +1,6 @@ +package org.dolphinemu.dolphinemu.utils; + +public interface BooleanSupplier +{ + boolean get(); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java index 404d7e9909..9a6440c9e5 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java @@ -10,5 +10,5 @@ public final class WiiUtils public static native boolean installWAD(String file); - public static native int importWiiSave(String file); + public static native int importWiiSave(String file, BooleanSupplier canOverwrite); } diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index 1e1739df92..6a53b7ce3c 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -333,6 +333,7 @@ Importing... Successfully installed this title to the NAND. Failed to install this title to the NAND. + Save data for this title already exists in the NAND. Consider backing up the current data before overwriting.\nOverwrite now? Successfully imported save file. Failed to import save file. Your NAND may be corrupt, or something is preventing access to files within it. Failed to import save file. The given file appears to be corrupted or is not a valid Wii save. diff --git a/Source/Android/jni/AndroidCommon/IDCache.cpp b/Source/Android/jni/AndroidCommon/IDCache.cpp index 4c6c4b2ce7..b5ca604c6e 100644 --- a/Source/Android/jni/AndroidCommon/IDCache.cpp +++ b/Source/Android/jni/AndroidCommon/IDCache.cpp @@ -56,6 +56,9 @@ static jmethodID s_network_helper_get_network_ip_address; static jmethodID s_network_helper_get_network_prefix_length; static jmethodID s_network_helper_get_network_gateway; +static jclass s_boolean_supplier_class; +static jmethodID s_boolean_supplier_get; + namespace IDCache { JNIEnv* GetEnvForThread() @@ -261,6 +264,11 @@ jmethodID GetNetworkHelperGetNetworkGateway() return s_network_helper_get_network_gateway; } +jmethodID GetBooleanSupplierGet() +{ + return s_boolean_supplier_get; +} + } // namespace IDCache #ifdef __cplusplus @@ -361,6 +369,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) s_network_helper_get_network_gateway = env->GetStaticMethodID(s_network_helper_class, "GetNetworkGateway", "()I"); + const jclass boolean_supplier_class = + env->FindClass("org/dolphinemu/dolphinemu/utils/BooleanSupplier"); + s_boolean_supplier_class = reinterpret_cast(env->NewGlobalRef(boolean_supplier_class)); + s_boolean_supplier_get = env->GetMethodID(s_boolean_supplier_class, "get", "()Z"); + return JNI_VERSION; } diff --git a/Source/Android/jni/AndroidCommon/IDCache.h b/Source/Android/jni/AndroidCommon/IDCache.h index b633267f55..b0e7a3d814 100644 --- a/Source/Android/jni/AndroidCommon/IDCache.h +++ b/Source/Android/jni/AndroidCommon/IDCache.h @@ -56,4 +56,6 @@ jmethodID GetNetworkHelperGetNetworkIpAddress(); jmethodID GetNetworkHelperGetNetworkPrefixLength(); jmethodID GetNetworkHelperGetNetworkGateway(); +jmethodID GetBooleanSupplierGet(); + } // namespace IDCache diff --git a/Source/Android/jni/WiiUtils.cpp b/Source/Android/jni/WiiUtils.cpp index a2f607d68a..9b0601c1df 100644 --- a/Source/Android/jni/WiiUtils.cpp +++ b/Source/Android/jni/WiiUtils.cpp @@ -7,6 +7,7 @@ #include #include "jni/AndroidCommon/AndroidCommon.h" +#include "jni/AndroidCommon/IDCache.h" #include "Core/HW/WiiSave.h" #include "Core/WiiUtils.h" @@ -44,12 +45,14 @@ JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_WiiUtils_install return static_cast(WiiUtils::InstallWAD(path)); } -JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_utils_WiiUtils_importWiiSave(JNIEnv* env, - jclass, - jstring jFile) +JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_utils_WiiUtils_importWiiSave( + JNIEnv* env, jclass, jstring jFile, jobject jCanOverwrite) { const std::string path = GetJString(env, jFile); - const auto can_overwrite = [] { return true; }; // TODO + const auto can_overwrite = [&] { + const jmethodID get = IDCache::GetBooleanSupplierGet(); + return static_cast(env->CallBooleanMethod(jCanOverwrite, get)); + }; return ConvertCopyResult(WiiSave::Import(path, can_overwrite)); }