Merge pull request #11494 from t895/orientation-jank

Android: Rewrite Wii system updates in Kotlin
This commit is contained in:
Mai 2023-03-08 01:42:53 -05:00 committed by GitHub
commit f1e4b6a141
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 384 additions and 513 deletions

View File

@ -144,8 +144,10 @@ dependencies {
implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.profileinstaller:profileinstaller:1.2.2'
// Force dependency version to solve build conflict with androidx preferences
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
// Kotlin extensions for lifecycle components
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
// Android TV UI libraries.
implementation 'androidx.leanback:leanback:1.0.0'

View File

@ -1,44 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui;
import android.app.Dialog;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.dolphinemu.dolphinemu.R;
public class OnlineUpdateRegionSelectDialogFragment extends DialogFragment
{
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState)
{
String[] items =
{getString(R.string.country_europe), getString(R.string.country_japan), getString(
R.string.country_korea), getString(R.string.country_usa)};
int checkedItem = -1;
return new MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.region_select_title)
.setSingleChoiceItems(items, checkedItem, (dialog, which) ->
{
SystemUpdateViewModel viewModel =
new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);
viewModel.setRegion(which);
SystemUpdateProgressBarDialogFragment progressBarFragment =
new SystemUpdateProgressBarDialogFragment();
progressBarFragment
.show(getParentFragmentManager(), "OnlineUpdateProgressBarDialogFragment");
dismiss();
})
.create();
}
}

View File

@ -0,0 +1,40 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.dolphinemu.dolphinemu.R
class OnlineUpdateRegionSelectDialogFragment : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val items = arrayOf(
getString(R.string.country_europe),
getString(R.string.country_japan),
getString(R.string.country_korea),
getString(R.string.country_usa)
)
val checkedItem = -1
return MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.region_select_title)
.setSingleChoiceItems(items, checkedItem) { _: DialogInterface?, which: Int ->
val viewModel =
ViewModelProvider(requireActivity())[SystemUpdateViewModel::class.java]
viewModel.region = which
SystemUpdateProgressBarDialogFragment().show(
parentFragmentManager,
SystemUpdateProgressBarDialogFragment.TAG
)
dismiss()
}
.create()
}
companion object {
const val TAG = "OnlineUpdateRegionSelectDialogFragment"
}
}

View File

@ -1,34 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui;
import android.app.Dialog;
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.dolphinemu.dolphinemu.R;
public class SystemMenuNotInstalledDialogFragment extends DialogFragment
{
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
return new MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.system_menu_not_installed_title)
.setMessage(R.string.system_menu_not_installed_message)
.setPositiveButton(R.string.yes, (dialog, which) ->
{
FragmentManager fragmentManager = getParentFragmentManager();
OnlineUpdateRegionSelectDialogFragment dialogFragment =
new OnlineUpdateRegionSelectDialogFragment();
dialogFragment.show(fragmentManager, "OnlineUpdateRegionSelectDialogFragment");
dismiss();
})
.setNegativeButton(R.string.no, (dialog, which) -> dismiss())
.create();
}
}

View File

@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.dolphinemu.dolphinemu.R
class SystemMenuNotInstalledDialogFragment : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.system_menu_not_installed_title)
.setMessage(R.string.system_menu_not_installed_message)
.setPositiveButton(R.string.yes) { _: DialogInterface?, _: Int ->
OnlineUpdateRegionSelectDialogFragment().show(
parentFragmentManager,
OnlineUpdateRegionSelectDialogFragment.TAG
)
dismiss()
}
.setNegativeButton(R.string.no) { _: DialogInterface?, _: Int -> dismiss() }
.create()
}
companion object {
const val TAG = "SystemMenuNotInstalledDialogFragment"
}
}

View File

@ -1,133 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui;
import android.app.Dialog;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.databinding.DialogProgressBinding;
import org.dolphinemu.dolphinemu.databinding.DialogProgressTvBinding;
public class SystemUpdateProgressBarDialogFragment extends DialogFragment
{
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState)
{
// Store the current orientation to be restored later
final int orientation = getActivity().getRequestedOrientation();
// Rotating the device while the update is running can result in a title failing to import.
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
SystemUpdateViewModel viewModel =
new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);
DialogProgressBinding dialogProgressBinding;
DialogProgressTvBinding dialogProgressTvBinding;
// We need to set the message to something here, otherwise the text will not appear when we set it later.
MaterialAlertDialogBuilder progressDialogBuilder =
new MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.updating))
.setMessage("")
.setNegativeButton(getString(R.string.cancel), null)
.setCancelable(false);
// TODO: Remove dialog_progress_tv if we switch to an AppCompatActivity for leanback
if (getActivity() instanceof AppCompatActivity)
{
dialogProgressBinding = DialogProgressBinding.inflate(getLayoutInflater());
progressDialogBuilder.setView(dialogProgressBinding.getRoot());
viewModel.getProgressData().observe(this,
(@Nullable Integer progress) -> dialogProgressBinding.updateProgress.setProgress(
progress));
viewModel.getTotalData().observe(this, (@Nullable Integer total) ->
{
if (total == 0)
{
return;
}
dialogProgressBinding.updateProgress.setMax(total);
});
}
else
{
dialogProgressTvBinding = DialogProgressTvBinding.inflate(getLayoutInflater());
progressDialogBuilder.setView(dialogProgressTvBinding.getRoot());
viewModel.getProgressData().observe(this,
(@Nullable Integer progress) -> dialogProgressTvBinding.updateProgress.setProgress(
progress));
viewModel.getTotalData().observe(this, (@Nullable Integer total) ->
{
if (total == 0)
{
return;
}
dialogProgressTvBinding.updateProgress.setMax(total);
});
}
AlertDialog progressDialog = progressDialogBuilder.create();
viewModel.getTitleIdData().observe(this, (@Nullable Long titleId) -> progressDialog.setMessage(
getString(R.string.updating_message, titleId)));
viewModel.getResultData().observe(this, (@Nullable Integer result) ->
{
if (result == -1)
{
// This is the default value, ignore
return;
}
SystemUpdateResultFragment progressBarFragment = new SystemUpdateResultFragment();
progressBarFragment.show(getParentFragmentManager(), "OnlineUpdateResultFragment");
getActivity().setRequestedOrientation(orientation);
dismiss();
});
if (savedInstanceState == null)
{
viewModel.startUpdate();
}
return progressDialog;
}
// By default, the ProgressDialog will immediately dismiss itself upon a button being pressed.
// Setting the OnClickListener again after the dialog is shown overrides this behavior.
@Override
public void onResume()
{
super.onResume();
AlertDialog alertDialog = (AlertDialog) getDialog();
SystemUpdateViewModel viewModel =
new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);
Button negativeButton = alertDialog.getButton(Dialog.BUTTON_NEGATIVE);
negativeButton.setOnClickListener(v ->
{
alertDialog.setTitle(getString(R.string.cancelling));
alertDialog.setMessage(getString(R.string.update_cancelling));
viewModel.setCanceled();
});
}
}

View File

@ -0,0 +1,112 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui
import android.app.Dialog
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.databinding.DialogProgressBinding
import org.dolphinemu.dolphinemu.databinding.DialogProgressTvBinding
class SystemUpdateProgressBarDialogFragment : DialogFragment() {
private lateinit var viewModel: SystemUpdateViewModel
private lateinit var binding: DialogProgressBinding
private lateinit var bindingTv: DialogProgressTvBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
viewModel = ViewModelProvider(requireActivity())[SystemUpdateViewModel::class.java]
// We need to set the message to something here, otherwise the text will not appear when we set it later.
val progressDialogBuilder = MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.updating))
.setMessage("")
.setNegativeButton(getString(R.string.cancel), null)
.setCancelable(false)
// TODO: Remove dialog_progress_tv if we switch to an AppCompatActivity for leanback
if (activity is AppCompatActivity) {
binding = DialogProgressBinding.inflate(layoutInflater)
progressDialogBuilder.setView(binding.root)
viewModel.progressData.observe(
this
) { progress: Int ->
binding.updateProgress.progress = progress
}
viewModel.totalData.observe(this) { total: Int ->
if (total == 0) {
return@observe
}
binding.updateProgress.max = total
}
} else {
bindingTv = DialogProgressTvBinding.inflate(layoutInflater)
progressDialogBuilder.setView(bindingTv.root)
viewModel.progressData.observe(
this
) { progress: Int ->
bindingTv.updateProgress.progress = progress
}
viewModel.totalData.observe(this) { total: Int ->
if (total == 0) {
return@observe
}
bindingTv.updateProgress.max = total
}
}
val progressDialog = progressDialogBuilder.create()
viewModel.titleIdData.observe(this) { titleId: Long ->
progressDialog.setMessage(getString(R.string.updating_message, titleId))
}
viewModel.resultData.observe(this) { result: Int ->
if (result == -1) {
// This is the default value, ignore
return@observe
}
val progressBarFragment = SystemUpdateResultFragment()
progressBarFragment.show(parentFragmentManager, SystemUpdateResultFragment.TAG)
dismiss()
}
if (savedInstanceState == null) {
viewModel.startUpdate()
}
return progressDialog
}
// By default, the ProgressDialog will immediately dismiss itself upon a button being pressed.
// Setting the OnClickListener again after the dialog is shown overrides this behavior.
override fun onResume() {
super.onResume()
val alertDialog = dialog as AlertDialog
val negativeButton = alertDialog.getButton(Dialog.BUTTON_NEGATIVE)
negativeButton.setOnClickListener {
alertDialog.setTitle(getString(R.string.cancelling))
alertDialog.setMessage(getString(R.string.update_cancelling))
viewModel.setCanceled()
if (activity is AppCompatActivity)
binding.updateProgress.isIndeterminate = true
else
bindingTv.updateProgress.isIndeterminate = true
}
}
companion object {
const val TAG = "SystemUpdateProgressBarDialogFragment"
}
}

View File

@ -1,105 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui;
import android.app.Dialog;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.utils.WiiUtils;
public class SystemUpdateResultFragment extends DialogFragment
{
private int mResult;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
SystemUpdateViewModel viewModel =
new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);
if (savedInstanceState == null)
{
mResult = viewModel.getResultData().getValue().intValue();
viewModel.clear();
}
else
{
mResult = savedInstanceState.getInt("result");
}
String message;
switch (mResult)
{
case WiiUtils.UPDATE_RESULT_SUCCESS:
message = getString(R.string.update_success);
break;
case WiiUtils.UPDATE_RESULT_ALREADY_UP_TO_DATE:
message = getString(R.string.already_up_to_date);
break;
case WiiUtils.UPDATE_RESULT_REGION_MISMATCH:
message = getString(R.string.region_mismatch);
break;
case WiiUtils.UPDATE_RESULT_MISSING_UPDATE_PARTITION:
message = getString(R.string.missing_update_partition);
break;
case WiiUtils.UPDATE_RESULT_DISC_READ_FAILED:
message = getString(R.string.disc_read_failed);
break;
case WiiUtils.UPDATE_RESULT_SERVER_FAILED:
message = getString(R.string.server_failed);
break;
case WiiUtils.UPDATE_RESULT_DOWNLOAD_FAILED:
message = getString(R.string.download_failed);
break;
case WiiUtils.UPDATE_RESULT_IMPORT_FAILED:
message = getString(R.string.import_failed);
break;
case WiiUtils.UPDATE_RESULT_CANCELLED:
message = getString(R.string.update_cancelled);
break;
default:
throw new IllegalStateException("Unexpected value: " + mResult);
}
String title;
switch (mResult)
{
case WiiUtils.UPDATE_RESULT_SUCCESS:
case WiiUtils.UPDATE_RESULT_ALREADY_UP_TO_DATE:
title = getString(R.string.update_success_title);
break;
case WiiUtils.UPDATE_RESULT_REGION_MISMATCH:
case WiiUtils.UPDATE_RESULT_MISSING_UPDATE_PARTITION:
case WiiUtils.UPDATE_RESULT_DISC_READ_FAILED:
case WiiUtils.UPDATE_RESULT_SERVER_FAILED:
case WiiUtils.UPDATE_RESULT_DOWNLOAD_FAILED:
case WiiUtils.UPDATE_RESULT_IMPORT_FAILED:
title = getString(R.string.update_failed_title);
break;
case WiiUtils.UPDATE_RESULT_CANCELLED:
title = getString(R.string.update_cancelled_title);
break;
default:
throw new IllegalStateException("Unexpected value: " + mResult);
}
return new MaterialAlertDialogBuilder(requireContext())
.setTitle(title)
.setMessage(message)
.setPositiveButton(R.string.ok, (dialog, which) -> dismiss())
.create();
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putInt("result", mResult);
}
}

View File

@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.utils.WiiUtils
class SystemUpdateResultFragment : DialogFragment() {
private val resultKey = "result"
private var mResult = 0
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val viewModel = ViewModelProvider(requireActivity())[SystemUpdateViewModel::class.java]
if (savedInstanceState == null) {
mResult = viewModel.resultData.value!!.toInt()
viewModel.clear()
} else {
mResult = savedInstanceState.getInt(resultKey)
}
val message: String = when (mResult) {
WiiUtils.UPDATE_RESULT_SUCCESS -> getString(R.string.update_success)
WiiUtils.UPDATE_RESULT_ALREADY_UP_TO_DATE -> getString(R.string.already_up_to_date)
WiiUtils.UPDATE_RESULT_REGION_MISMATCH -> getString(R.string.region_mismatch)
WiiUtils.UPDATE_RESULT_MISSING_UPDATE_PARTITION -> getString(R.string.missing_update_partition)
WiiUtils.UPDATE_RESULT_DISC_READ_FAILED -> getString(R.string.disc_read_failed)
WiiUtils.UPDATE_RESULT_SERVER_FAILED -> getString(R.string.server_failed)
WiiUtils.UPDATE_RESULT_DOWNLOAD_FAILED -> getString(R.string.download_failed)
WiiUtils.UPDATE_RESULT_IMPORT_FAILED -> getString(R.string.import_failed)
WiiUtils.UPDATE_RESULT_CANCELLED -> getString(R.string.update_cancelled)
else -> throw IllegalStateException("Unexpected value: $mResult")
}
val title: String = when (mResult) {
WiiUtils.UPDATE_RESULT_SUCCESS,
WiiUtils.UPDATE_RESULT_ALREADY_UP_TO_DATE -> getString(R.string.update_success_title)
WiiUtils.UPDATE_RESULT_REGION_MISMATCH,
WiiUtils.UPDATE_RESULT_MISSING_UPDATE_PARTITION,
WiiUtils.UPDATE_RESULT_DISC_READ_FAILED,
WiiUtils.UPDATE_RESULT_SERVER_FAILED,
WiiUtils.UPDATE_RESULT_DOWNLOAD_FAILED,
WiiUtils.UPDATE_RESULT_IMPORT_FAILED -> getString(R.string.update_failed_title)
WiiUtils.UPDATE_RESULT_CANCELLED -> getString(R.string.update_cancelled_title)
else -> throw IllegalStateException("Unexpected value: $mResult")
}
return MaterialAlertDialogBuilder(requireContext())
.setTitle(title)
.setMessage(message)
.setPositiveButton(R.string.ok) { _: DialogInterface?, _: Int -> dismiss() }
.create()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt(resultKey, mResult)
}
companion object {
const val TAG = "SystemUpdateResultFragment"
}
}

View File

@ -1,152 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import org.dolphinemu.dolphinemu.utils.WiiUpdateCallback;
import org.dolphinemu.dolphinemu.utils.WiiUtils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SystemUpdateViewModel extends ViewModel
{
private static final ExecutorService executor = Executors.newFixedThreadPool(1);
private final MutableLiveData<Integer> mProgressData = new MutableLiveData<>();
private final MutableLiveData<Integer> mTotalData = new MutableLiveData<>();
private final MutableLiveData<Long> mTitleIdData = new MutableLiveData<>();
private final MutableLiveData<Integer> mResultData = new MutableLiveData<>();
private boolean mCanceled = false;
private int mRegion;
private String mDiscPath;
public SystemUpdateViewModel()
{
clear();
}
public void setRegion(int region)
{
mRegion = region;
}
public int getRegion()
{
return mRegion;
}
public void setDiscPath(String discPath)
{
mDiscPath = discPath;
}
public String getDiscPath()
{
return mDiscPath;
}
public MutableLiveData<Integer> getProgressData()
{
return mProgressData;
}
public MutableLiveData<Integer> getTotalData()
{
return mTotalData;
}
public MutableLiveData<Long> getTitleIdData()
{
return mTitleIdData;
}
public MutableLiveData<Integer> getResultData()
{
return mResultData;
}
public void setCanceled()
{
mCanceled = true;
}
public void startUpdate()
{
if (!mDiscPath.isEmpty())
{
startDiscUpdate(mDiscPath);
}
else
{
final String region;
switch (mRegion)
{
case 0:
region = "EUR";
break;
case 1:
region = "JPN";
break;
case 2:
region = "KOR";
break;
case 3:
region = "USA";
break;
default:
region = "";
break;
}
startOnlineUpdate(region);
}
}
public void startOnlineUpdate(String region)
{
mCanceled = false;
executor.execute(() ->
{
int result = WiiUtils.doOnlineUpdate(region, constructCallback());
mResultData.postValue(result);
});
}
public void startDiscUpdate(String path)
{
mCanceled = false;
executor.execute(() ->
{
int result = WiiUtils.doDiscUpdate(path, constructCallback());
mResultData.postValue(result);
});
}
public void clear()
{
mProgressData.setValue(0);
mTotalData.setValue(0);
mTitleIdData.setValue(0l);
mResultData.setValue(-1);
mCanceled = false;
mRegion = -1;
mDiscPath = "";
}
private WiiUpdateCallback constructCallback()
{
return (processed, total, titleId) ->
{
mProgressData.postValue(processed);
mTotalData.postValue(total);
mTitleIdData.postValue(titleId);
return !mCanceled;
};
}
}

View File

@ -0,0 +1,83 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.sysupdate.ui
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.dolphinemu.dolphinemu.utils.WiiUpdateCallback
import org.dolphinemu.dolphinemu.utils.WiiUtils
class SystemUpdateViewModel : ViewModel() {
val progressData = MutableLiveData<Int>()
val totalData = MutableLiveData<Int>()
val titleIdData = MutableLiveData<Long>()
val resultData = MutableLiveData<Int>()
private var isRunning = false
private var canceled = false
var region = -1
var discPath: String = ""
init {
clear()
}
fun setCanceled() {
canceled = true
}
fun startUpdate() {
if (isRunning) return
isRunning = true
viewModelScope.launch {
withContext(Dispatchers.IO) {
if (discPath.isNotEmpty()) {
startDiscUpdate(discPath)
} else {
val region: String = when (region) {
0 -> "EUR"
1 -> "JPN"
2 -> "KOR"
3 -> "USA"
else -> ""
}
startOnlineUpdate(region)
}
isRunning = false
}
}
}
private fun startOnlineUpdate(region: String) {
canceled = false
val result = WiiUtils.doOnlineUpdate(region, constructCallback())
resultData.postValue(result)
}
private fun startDiscUpdate(path: String) {
canceled = false
val result = WiiUtils.doDiscUpdate(path, constructCallback())
resultData.postValue(result)
}
fun clear() {
progressData.value = 0
totalData.value = 0
titleIdData.value = 0L
resultData.value = -1
}
private fun constructCallback(): WiiUpdateCallback {
return WiiUpdateCallback { processed: Int, total: Int, titleId: Long ->
progressData.postValue(processed)
totalData.postValue(total)
titleIdData.postValue(titleId)
!canceled
}
}
}

View File

@ -319,7 +319,7 @@ public final class MainPresenter
SystemUpdateProgressBarDialogFragment progressBarFragment =
new SystemUpdateProgressBarDialogFragment();
progressBarFragment
.show(activity.getSupportFragmentManager(), "SystemUpdateProgressBarDialogFragment");
.show(activity.getSupportFragmentManager(), SystemUpdateProgressBarDialogFragment.TAG);
progressBarFragment.setCancelable(false);
}

View File

@ -1,42 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.utils;
public final class WiiUtils
{
public static final int RESULT_SUCCESS = 0;
public static final int RESULT_ERROR = 1;
public static final int RESULT_CANCELLED = 2;
public static final int RESULT_CORRUPTED_SOURCE = 3;
public static final int RESULT_TITLE_MISSING = 4;
public static final int UPDATE_RESULT_SUCCESS = 0;
public static final int UPDATE_RESULT_ALREADY_UP_TO_DATE = 1;
public static final int UPDATE_RESULT_REGION_MISMATCH = 2;
public static final int UPDATE_RESULT_MISSING_UPDATE_PARTITION = 3;
public static final int UPDATE_RESULT_DISC_READ_FAILED = 4;
public static final int UPDATE_RESULT_SERVER_FAILED = 5;
public static final int UPDATE_RESULT_DOWNLOAD_FAILED = 6;
public static final int UPDATE_RESULT_IMPORT_FAILED = 7;
public static final int UPDATE_RESULT_CANCELLED = 8;
public static native boolean installWAD(String file);
public static native int importWiiSave(String file, BooleanSupplier canOverwrite);
public static native void importNANDBin(String file);
public static native int doOnlineUpdate(String region, WiiUpdateCallback callback);
public static native int doDiscUpdate(String path, WiiUpdateCallback callback);
public static native boolean isSystemMenuInstalled();
public static native boolean isSystemMenuvWii();
public static native String getSystemMenuVersion();
public static native boolean syncSdFolderToSdImage();
public static native boolean syncSdImageToSdFolder();
}

View File

@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.utils
object WiiUtils {
const val RESULT_SUCCESS = 0
const val RESULT_ERROR = 1
const val RESULT_CANCELLED = 2
const val RESULT_CORRUPTED_SOURCE = 3
const val RESULT_TITLE_MISSING = 4
const val UPDATE_RESULT_SUCCESS = 0
const val UPDATE_RESULT_ALREADY_UP_TO_DATE = 1
const val UPDATE_RESULT_REGION_MISMATCH = 2
const val UPDATE_RESULT_MISSING_UPDATE_PARTITION = 3
const val UPDATE_RESULT_DISC_READ_FAILED = 4
const val UPDATE_RESULT_SERVER_FAILED = 5
const val UPDATE_RESULT_DOWNLOAD_FAILED = 6
const val UPDATE_RESULT_IMPORT_FAILED = 7
const val UPDATE_RESULT_CANCELLED = 8
@JvmStatic
external fun installWAD(file: String): Boolean
@JvmStatic
external fun importWiiSave(file: String, canOverwrite: BooleanSupplier): Int
@JvmStatic
external fun importNANDBin(file: String)
external fun doOnlineUpdate(region: String, callback: WiiUpdateCallback): Int
external fun doDiscUpdate(path: String, callback: WiiUpdateCallback): Int
@JvmStatic
external fun isSystemMenuInstalled(): Boolean
@JvmStatic
external fun isSystemMenuvWii(): Boolean
@JvmStatic
external fun getSystemMenuVersion(): String
@JvmStatic
external fun syncSdFolderToSdImage(): Boolean
@JvmStatic
external fun syncSdImageToSdFolder(): Boolean
}