mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-26 15:55:31 +01:00
Merge pull request #11494 from t895/orientation-jank
Android: Rewrite Wii system updates in Kotlin
This commit is contained in:
commit
f1e4b6a141
@ -144,8 +144,10 @@ dependencies {
|
|||||||
implementation 'androidx.preference:preference:1.2.0'
|
implementation 'androidx.preference:preference:1.2.0'
|
||||||
implementation 'androidx.profileinstaller:profileinstaller:1.2.2'
|
implementation 'androidx.profileinstaller:profileinstaller:1.2.2'
|
||||||
|
|
||||||
// Force dependency version to solve build conflict with androidx preferences
|
// Kotlin extensions for lifecycle components
|
||||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
|
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.
|
// Android TV UI libraries.
|
||||||
implementation 'androidx.leanback:leanback:1.0.0'
|
implementation 'androidx.leanback:leanback:1.0.0'
|
||||||
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -319,7 +319,7 @@ public final class MainPresenter
|
|||||||
SystemUpdateProgressBarDialogFragment progressBarFragment =
|
SystemUpdateProgressBarDialogFragment progressBarFragment =
|
||||||
new SystemUpdateProgressBarDialogFragment();
|
new SystemUpdateProgressBarDialogFragment();
|
||||||
progressBarFragment
|
progressBarFragment
|
||||||
.show(activity.getSupportFragmentManager(), "SystemUpdateProgressBarDialogFragment");
|
.show(activity.getSupportFragmentManager(), SystemUpdateProgressBarDialogFragment.TAG);
|
||||||
progressBarFragment.setCancelable(false);
|
progressBarFragment.setCancelable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
|
||||||
}
|
|
@ -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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user