diff options
Diffstat (limited to 'src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt')
-rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt new file mode 100644 index 000000000..10b1d3547 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt @@ -0,0 +1,185 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updatePadding +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.lifecycleScope +import androidx.navigation.findNavController +import androidx.recyclerview.widget.GridLayoutManager +import com.google.android.material.transition.MaterialSharedAxis +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch +import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.adapters.DriverAdapter +import org.yuzu.yuzu_emu.databinding.FragmentDriverManagerBinding +import org.yuzu.yuzu_emu.model.DriverViewModel +import org.yuzu.yuzu_emu.model.HomeViewModel +import org.yuzu.yuzu_emu.utils.FileUtil +import org.yuzu.yuzu_emu.utils.GpuDriverHelper +import java.io.IOException + +class DriverManagerFragment : Fragment() { + private var _binding: FragmentDriverManagerBinding? = null + private val binding get() = _binding!! + + private val homeViewModel: HomeViewModel by activityViewModels() + private val driverViewModel: DriverViewModel by activityViewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) + returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) + reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentDriverManagerBinding.inflate(inflater) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + homeViewModel.setNavigationVisibility(visible = false, animated = true) + homeViewModel.setStatusBarShadeVisibility(visible = false) + + if (!driverViewModel.isInteractionAllowed) { + DriversLoadingDialogFragment().show( + childFragmentManager, + DriversLoadingDialogFragment.TAG + ) + } + + binding.toolbarDrivers.setNavigationOnClickListener { + binding.root.findNavController().popBackStack() + } + + binding.buttonInstall.setOnClickListener { + getDriver.launch(arrayOf("application/zip")) + } + + binding.listDrivers.apply { + layoutManager = GridLayoutManager( + requireContext(), + resources.getInteger(R.integer.grid_columns) + ) + adapter = DriverAdapter(driverViewModel) + } + + viewLifecycleOwner.lifecycleScope.apply { + launch { + driverViewModel.driverList.collectLatest { + (binding.listDrivers.adapter as DriverAdapter).submitList(it) + } + } + launch { + driverViewModel.newDriverInstalled.collect { + if (_binding != null && it) { + (binding.listDrivers.adapter as DriverAdapter).apply { + notifyItemChanged(driverViewModel.previouslySelectedDriver) + notifyItemChanged(driverViewModel.selectedDriver) + driverViewModel.setNewDriverInstalled(false) + } + } + } + } + } + + setInsets() + } + + // Start installing requested driver + override fun onStop() { + super.onStop() + driverViewModel.onCloseDriverManager() + } + + private fun setInsets() = + ViewCompat.setOnApplyWindowInsetsListener( + binding.root + ) { _: View, windowInsets: WindowInsetsCompat -> + val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()) + + val leftInsets = barInsets.left + cutoutInsets.left + val rightInsets = barInsets.right + cutoutInsets.right + + val mlpAppBar = binding.toolbarDrivers.layoutParams as ViewGroup.MarginLayoutParams + mlpAppBar.leftMargin = leftInsets + mlpAppBar.rightMargin = rightInsets + binding.toolbarDrivers.layoutParams = mlpAppBar + + val mlplistDrivers = binding.listDrivers.layoutParams as ViewGroup.MarginLayoutParams + mlplistDrivers.leftMargin = leftInsets + mlplistDrivers.rightMargin = rightInsets + binding.listDrivers.layoutParams = mlplistDrivers + + val fabSpacing = resources.getDimensionPixelSize(R.dimen.spacing_fab) + val mlpFab = + binding.buttonInstall.layoutParams as ViewGroup.MarginLayoutParams + mlpFab.leftMargin = leftInsets + fabSpacing + mlpFab.rightMargin = rightInsets + fabSpacing + mlpFab.bottomMargin = barInsets.bottom + fabSpacing + binding.buttonInstall.layoutParams = mlpFab + + binding.listDrivers.updatePadding( + bottom = barInsets.bottom + + resources.getDimensionPixelSize(R.dimen.spacing_bottom_list_fab) + ) + + windowInsets + } + + private val getDriver = + registerForActivityResult(ActivityResultContracts.OpenDocument()) { result -> + if (result == null) { + return@registerForActivityResult + } + + IndeterminateProgressDialogFragment.newInstance( + requireActivity(), + R.string.installing_driver, + false + ) { + // Ignore file exceptions when a user selects an invalid zip + try { + GpuDriverHelper.copyDriverToInternalStorage(result) + } catch (_: IOException) { + return@newInstance getString(R.string.select_gpu_driver_error) + } + + val driverData = GpuDriverHelper.customDriverData + if (driverData.name == null) { + return@newInstance getString(R.string.select_gpu_driver_error) + } + + val driverInList = + driverViewModel.driverList.value.firstOrNull { it.second == driverData } + if (driverInList != null) { + return@newInstance getString(R.string.driver_already_installed) + } else { + driverViewModel.addDriver( + Pair( + "${GpuDriverHelper.driverStoragePath}/${FileUtil.getFilename(result)}", + driverData + ) + ) + driverViewModel.setNewDriverInstalled(true) + } + return@newInstance Any() + }.show(childFragmentManager, IndeterminateProgressDialogFragment.TAG) + } +} |