diff options
Diffstat (limited to 'src/android/app/src')
11 files changed, 370 insertions, 184 deletions
| diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/SetupAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/SetupAdapter.kt index 481ddd5a5..6b46d359e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/SetupAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/SetupAdapter.kt @@ -5,13 +5,19 @@ package org.yuzu.yuzu_emu.adapters  import android.text.Html  import android.view.LayoutInflater +import android.view.View  import android.view.ViewGroup  import androidx.appcompat.app.AppCompatActivity  import androidx.core.content.res.ResourcesCompat +import androidx.lifecycle.ViewModelProvider  import androidx.recyclerview.widget.RecyclerView  import com.google.android.material.button.MaterialButton  import org.yuzu.yuzu_emu.databinding.PageSetupBinding +import org.yuzu.yuzu_emu.model.HomeViewModel +import org.yuzu.yuzu_emu.model.SetupCallback  import org.yuzu.yuzu_emu.model.SetupPage +import org.yuzu.yuzu_emu.model.StepState +import org.yuzu.yuzu_emu.utils.ViewUtils  class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) :      RecyclerView.Adapter<SetupAdapter.SetupPageViewHolder>() { @@ -26,7 +32,7 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)          holder.bind(pages[position])      inner class SetupPageViewHolder(val binding: PageSetupBinding) : -        RecyclerView.ViewHolder(binding.root) { +        RecyclerView.ViewHolder(binding.root), SetupCallback {          lateinit var page: SetupPage          init { @@ -35,6 +41,12 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)          fun bind(page: SetupPage) {              this.page = page + +            if (page.stepCompleted.invoke() == StepState.COMPLETE) { +                binding.buttonAction.visibility = View.INVISIBLE +                binding.textConfirmation.visibility = View.VISIBLE +            } +              binding.icon.setImageDrawable(                  ResourcesCompat.getDrawable(                      activity.resources, @@ -62,9 +74,15 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)                          MaterialButton.ICON_GRAVITY_END                      }                  setOnClickListener { -                    page.buttonAction.invoke() +                    page.buttonAction.invoke(this@SetupPageViewHolder)                  }              }          } + +        override fun onStepCompleted() { +            ViewUtils.hideView(binding.buttonAction, 200) +            ViewUtils.showView(binding.textConfirmation, 200) +            ViewModelProvider(activity)[HomeViewModel::class.java].setShouldPageForward(true) +        }      }  } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt index 6c4ddaf6b..d50c421a0 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SetupFragment.kt @@ -19,6 +19,7 @@ import androidx.core.content.ContextCompat  import androidx.core.view.ViewCompat  import androidx.core.view.WindowInsetsCompat  import androidx.core.view.isVisible +import androidx.core.view.updatePadding  import androidx.fragment.app.Fragment  import androidx.fragment.app.activityViewModels  import androidx.navigation.findNavController @@ -32,10 +33,13 @@ import org.yuzu.yuzu_emu.adapters.SetupAdapter  import org.yuzu.yuzu_emu.databinding.FragmentSetupBinding  import org.yuzu.yuzu_emu.features.settings.model.Settings  import org.yuzu.yuzu_emu.model.HomeViewModel +import org.yuzu.yuzu_emu.model.SetupCallback  import org.yuzu.yuzu_emu.model.SetupPage +import org.yuzu.yuzu_emu.model.StepState  import org.yuzu.yuzu_emu.ui.main.MainActivity  import org.yuzu.yuzu_emu.utils.DirectoryInitialization  import org.yuzu.yuzu_emu.utils.GameHelper +import org.yuzu.yuzu_emu.utils.ViewUtils  class SetupFragment : Fragment() {      private var _binding: FragmentSetupBinding? = null @@ -112,14 +116,22 @@ class SetupFragment : Fragment() {                          0,                          false,                          R.string.give_permission, -                        { permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) }, +                        { +                            notificationCallback = it +                            permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) +                        },                          true,                          R.string.notification_warning,                          R.string.notification_warning_description,                          0,                          { -                            NotificationManagerCompat.from(requireContext()) +                            if (NotificationManagerCompat.from(requireContext())                                  .areNotificationsEnabled() +                            ) { +                                StepState.COMPLETE +                            } else { +                                StepState.INCOMPLETE +                            }                          }                      )                  ) @@ -133,12 +145,22 @@ class SetupFragment : Fragment() {                      R.drawable.ic_add,                      true,                      R.string.select_keys, -                    { mainActivity.getProdKey.launch(arrayOf("*/*")) }, +                    { +                        keyCallback = it +                        getProdKey.launch(arrayOf("*/*")) +                    },                      true,                      R.string.install_prod_keys_warning,                      R.string.install_prod_keys_warning_description,                      R.string.install_prod_keys_warning_help, -                    { File(DirectoryInitialization.userDirectory + "/keys/prod.keys").exists() } +                    { +                        val file = File(DirectoryInitialization.userDirectory + "/keys/prod.keys") +                        if (file.exists()) { +                            StepState.COMPLETE +                        } else { +                            StepState.INCOMPLETE +                        } +                    }                  )              )              add( @@ -150,9 +172,8 @@ class SetupFragment : Fragment() {                      true,                      R.string.add_games,                      { -                        mainActivity.getGamesDirectory.launch( -                            Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data -                        ) +                        gamesDirCallback = it +                        getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data)                      },                      true,                      R.string.add_games_warning, @@ -163,7 +184,11 @@ class SetupFragment : Fragment() {                              PreferenceManager.getDefaultSharedPreferences(                                  YuzuApplication.appContext                              ) -                        preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty() +                        if (preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty()) { +                            StepState.COMPLETE +                        } else { +                            StepState.INCOMPLETE +                        }                      }                  )              ) @@ -181,6 +206,13 @@ class SetupFragment : Fragment() {              )          } +        homeViewModel.shouldPageForward.observe(viewLifecycleOwner) { +            if (it) { +                pageForward() +                homeViewModel.setShouldPageForward(false) +            } +        } +          binding.viewPager2.apply {              adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages)              offscreenPageLimit = 2 @@ -194,15 +226,15 @@ class SetupFragment : Fragment() {                  super.onPageSelected(position)                  if (position == 1 && previousPosition == 0) { -                    showView(binding.buttonNext) -                    showView(binding.buttonBack) +                    ViewUtils.showView(binding.buttonNext) +                    ViewUtils.showView(binding.buttonBack)                  } else if (position == 0 && previousPosition == 1) { -                    hideView(binding.buttonBack) -                    hideView(binding.buttonNext) +                    ViewUtils.hideView(binding.buttonBack) +                    ViewUtils.hideView(binding.buttonNext)                  } else if (position == pages.size - 1 && previousPosition == pages.size - 2) { -                    hideView(binding.buttonNext) +                    ViewUtils.hideView(binding.buttonNext)                  } else if (position == pages.size - 2 && previousPosition == pages.size - 1) { -                    showView(binding.buttonNext) +                    ViewUtils.showView(binding.buttonNext)                  }                  previousPosition = position @@ -215,7 +247,8 @@ class SetupFragment : Fragment() {              // Checks if the user has completed the task on the current page              if (currentPage.hasWarning) { -                if (currentPage.taskCompleted.invoke()) { +                val stepState = currentPage.stepCompleted.invoke() +                if (stepState != StepState.INCOMPLETE) {                      pageForward()                      return@setOnClickListener                  } @@ -264,9 +297,15 @@ class SetupFragment : Fragment() {          _binding = null      } +    private lateinit var notificationCallback: SetupCallback +      @RequiresApi(Build.VERSION_CODES.TIRAMISU)      private val permissionLauncher =          registerForActivityResult(ActivityResultContracts.RequestPermission()) { +            if (it) { +                notificationCallback.onStepCompleted() +            } +              if (!it &&                  !shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)              ) { @@ -277,6 +316,27 @@ class SetupFragment : Fragment() {              }          } +    private lateinit var keyCallback: SetupCallback + +    val getProdKey = +        registerForActivityResult(ActivityResultContracts.OpenDocument()) { result -> +            if (result != null) { +                if (mainActivity.processKey(result)) { +                    keyCallback.onStepCompleted() +                } +            } +        } + +    private lateinit var gamesDirCallback: SetupCallback + +    val getGamesDirectory = +        registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result -> +            if (result != null) { +                mainActivity.processGamesDir(result) +                gamesDirCallback.onStepCompleted() +            } +        } +      private fun finishSetup() {          PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()              .putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false) @@ -284,33 +344,6 @@ class SetupFragment : Fragment() {          mainActivity.finishSetup(binding.root.findNavController())      } -    private fun showView(view: View) { -        view.apply { -            alpha = 0f -            visibility = View.VISIBLE -            isClickable = true -        }.animate().apply { -            duration = 300 -            alpha(1f) -        }.start() -    } - -    private fun hideView(view: View) { -        if (view.visibility == View.INVISIBLE) { -            return -        } - -        view.apply { -            alpha = 1f -            isClickable = false -        }.animate().apply { -            duration = 300 -            alpha(0f) -        }.withEndAction { -            view.visibility = View.INVISIBLE -        } -    } -      fun pageForward() {          binding.viewPager2.currentItem = binding.viewPager2.currentItem + 1      } @@ -326,15 +359,29 @@ class SetupFragment : Fragment() {      private fun setInsets() =          ViewCompat.setOnApplyWindowInsetsListener(              binding.root -        ) { view: View, windowInsets: WindowInsetsCompat -> +        ) { _: View, windowInsets: WindowInsetsCompat ->              val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())              val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()) -            view.setPadding( -                barInsets.left + cutoutInsets.left, -                barInsets.top + cutoutInsets.top, -                barInsets.right + cutoutInsets.right, -                barInsets.bottom + cutoutInsets.bottom -            ) + +            val leftPadding = barInsets.left + cutoutInsets.left +            val topPadding = barInsets.top + cutoutInsets.top +            val rightPadding = barInsets.right + cutoutInsets.right +            val bottomPadding = barInsets.bottom + cutoutInsets.bottom + +            if (resources.getBoolean(R.bool.small_layout)) { +                binding.viewPager2 +                    .updatePadding(left = leftPadding, top = topPadding, right = rightPadding) +                binding.constraintButtons +                    .updatePadding(left = leftPadding, right = rightPadding, bottom = bottomPadding) +            } else { +                binding.viewPager2.updatePadding(top = topPadding, bottom = bottomPadding) +                binding.constraintButtons +                    .updatePadding( +                        left = leftPadding, +                        right = rightPadding, +                        bottom = bottomPadding +                    ) +            }              windowInsets          }  } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt index 263ee7144..e13d84c9c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt @@ -14,6 +14,9 @@ class HomeViewModel : ViewModel() {      private val _statusBarShadeVisible = MutableLiveData(true)      val statusBarShadeVisible: LiveData<Boolean> get() = _statusBarShadeVisible +    private val _shouldPageForward = MutableLiveData(false) +    val shouldPageForward: LiveData<Boolean> get() = _shouldPageForward +      var navigatedToSetup = false      init { @@ -33,4 +36,8 @@ class HomeViewModel : ViewModel() {          }          _statusBarShadeVisible.value = visible      } + +    fun setShouldPageForward(pageForward: Boolean) { +        _shouldPageForward.value = pageForward +    }  } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SetupPage.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SetupPage.kt index a0c878e1c..09a128ae6 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SetupPage.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SetupPage.kt @@ -10,10 +10,20 @@ data class SetupPage(      val buttonIconId: Int,      val leftAlignedIcon: Boolean,      val buttonTextId: Int, -    val buttonAction: () -> Unit, +    val buttonAction: (callback: SetupCallback) -> Unit,      val hasWarning: Boolean,      val warningTitleId: Int = 0,      val warningDescriptionId: Int = 0,      val warningHelpLinkId: Int = 0, -    val taskCompleted: () -> Boolean = { true } +    val stepCompleted: () -> StepState = { StepState.UNDEFINED }  ) + +interface SetupCallback { +    fun onStepCompleted() +} + +enum class StepState { +    COMPLETE, +    INCOMPLETE, +    UNDEFINED +} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index f7d7aed1e..f77d06262 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt @@ -266,73 +266,80 @@ class MainActivity : AppCompatActivity(), ThemeProvider {      val getGamesDirectory =          registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result -> -            if (result == null) { -                return@registerForActivityResult +            if (result != null) { +                processGamesDir(result)              } +        } -            contentResolver.takePersistableUriPermission( -                result, -                Intent.FLAG_GRANT_READ_URI_PERMISSION -            ) +    fun processGamesDir(result: Uri) { +        contentResolver.takePersistableUriPermission( +            result, +            Intent.FLAG_GRANT_READ_URI_PERMISSION +        ) -            // When a new directory is picked, we currently will reset the existing games -            // database. This effectively means that only one game directory is supported. -            PreferenceManager.getDefaultSharedPreferences(applicationContext).edit() -                .putString(GameHelper.KEY_GAME_PATH, result.toString()) -                .apply() +        // When a new directory is picked, we currently will reset the existing games +        // database. This effectively means that only one game directory is supported. +        PreferenceManager.getDefaultSharedPreferences(applicationContext).edit() +            .putString(GameHelper.KEY_GAME_PATH, result.toString()) +            .apply() -            Toast.makeText( -                applicationContext, -                R.string.games_dir_selected, -                Toast.LENGTH_LONG -            ).show() +        Toast.makeText( +            applicationContext, +            R.string.games_dir_selected, +            Toast.LENGTH_LONG +        ).show() -            gamesViewModel.reloadGames(true) -        } +        gamesViewModel.reloadGames(true) +    }      val getProdKey =          registerForActivityResult(ActivityResultContracts.OpenDocument()) { result -> -            if (result == null) { -                return@registerForActivityResult +            if (result != null) { +                processKey(result)              } +        } -            if (FileUtil.getExtension(result) != "keys") { -                MessageDialogFragment.newInstance( -                    R.string.reading_keys_failure, -                    R.string.install_prod_keys_failure_extension_description -                ).show(supportFragmentManager, MessageDialogFragment.TAG) -                return@registerForActivityResult -            } +    fun processKey(result: Uri): Boolean { +        if (FileUtil.getExtension(result) != "keys") { +            MessageDialogFragment.newInstance( +                R.string.reading_keys_failure, +                R.string.install_prod_keys_failure_extension_description +            ).show(supportFragmentManager, MessageDialogFragment.TAG) +            return false +        } -            contentResolver.takePersistableUriPermission( +        contentResolver.takePersistableUriPermission( +            result, +            Intent.FLAG_GRANT_READ_URI_PERMISSION +        ) + +        val dstPath = DirectoryInitialization.userDirectory + "/keys/" +        if (FileUtil.copyUriToInternalStorage( +                applicationContext,                  result, -                Intent.FLAG_GRANT_READ_URI_PERMISSION +                dstPath, +                "prod.keys"              ) - -            val dstPath = DirectoryInitialization.userDirectory + "/keys/" -            if (FileUtil.copyUriToInternalStorage( +        ) { +            if (NativeLibrary.reloadKeys()) { +                Toast.makeText(                      applicationContext, -                    result, -                    dstPath, -                    "prod.keys" -                ) -            ) { -                if (NativeLibrary.reloadKeys()) { -                    Toast.makeText( -                        applicationContext, -                        R.string.install_keys_success, -                        Toast.LENGTH_SHORT -                    ).show() -                    gamesViewModel.reloadGames(true) -                } else { -                    MessageDialogFragment.newInstance( -                        R.string.invalid_keys_error, -                        R.string.install_keys_failure_description, -                        R.string.dumping_keys_quickstart_link -                    ).show(supportFragmentManager, MessageDialogFragment.TAG) -                } +                    R.string.install_keys_success, +                    Toast.LENGTH_SHORT +                ).show() +                gamesViewModel.reloadGames(true) +                return true +            } else { +                MessageDialogFragment.newInstance( +                    R.string.invalid_keys_error, +                    R.string.install_keys_failure_description, +                    R.string.dumping_keys_quickstart_link +                ).show(supportFragmentManager, MessageDialogFragment.TAG) +                return false              }          } +        return false +    }      val getFirmware =          registerForActivityResult(ActivityResultContracts.OpenDocument()) { result -> diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ViewUtils.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ViewUtils.kt new file mode 100644 index 000000000..f9a3e4126 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ViewUtils.kt @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.utils + +import android.view.View + +object ViewUtils { +    fun showView(view: View, length: Long = 300) { +        view.apply { +            alpha = 0f +            visibility = View.VISIBLE +            isClickable = true +        }.animate().apply { +            duration = length +            alpha(1f) +        }.start() +    } + +    fun hideView(view: View, length: Long = 300) { +        if (view.visibility == View.INVISIBLE) { +            return +        } + +        view.apply { +            alpha = 1f +            isClickable = false +        }.animate().apply { +            duration = length +            alpha(0f) +        }.withEndAction { +            view.visibility = View.INVISIBLE +        }.start() +    } +} diff --git a/src/android/app/src/main/res/layout-w600dp/fragment_setup.xml b/src/android/app/src/main/res/layout-w600dp/fragment_setup.xml index cbe631d88..406df9eab 100644 --- a/src/android/app/src/main/res/layout-w600dp/fragment_setup.xml +++ b/src/android/app/src/main/res/layout-w600dp/fragment_setup.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout +<RelativeLayout      xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:app="http://schemas.android.com/apk/res-auto"      android:id="@+id/setup_root" @@ -8,33 +8,39 @@      <androidx.viewpager2.widget.ViewPager2          android:id="@+id/viewPager2" -        android:layout_width="0dp" -        android:layout_height="0dp" -        app:layout_constraintBottom_toBottomOf="parent" -        app:layout_constraintEnd_toEndOf="parent" -        app:layout_constraintStart_toStartOf="parent" -        app:layout_constraintTop_toTopOf="parent" /> +        android:layout_width="match_parent" +        android:layout_height="match_parent" +        android:layout_alignParentTop="true" +        android:layout_alignParentBottom="true" +        android:clipToPadding="false" /> -    <com.google.android.material.button.MaterialButton -        style="@style/Widget.Material3.Button.TextButton" -        android:id="@+id/button_next" -        android:layout_width="wrap_content" +    <androidx.constraintlayout.widget.ConstraintLayout +        android:id="@+id/constraint_buttons" +        android:layout_width="match_parent"          android:layout_height="wrap_content" -        android:layout_margin="16dp" -        android:text="@string/next" -        android:visibility="invisible" -        app:layout_constraintBottom_toBottomOf="parent" -        app:layout_constraintEnd_toEndOf="parent" /> +        android:layout_alignParentBottom="true" +        android:layout_margin="8dp"> -    <com.google.android.material.button.MaterialButton -        android:id="@+id/button_back" -        style="@style/Widget.Material3.Button.TextButton" -        android:layout_width="wrap_content" -        android:layout_height="wrap_content" -        android:layout_margin="16dp" -        android:text="@string/back" -        android:visibility="invisible" -        app:layout_constraintBottom_toBottomOf="parent" -        app:layout_constraintStart_toStartOf="parent" /> +        <com.google.android.material.button.MaterialButton +            android:id="@+id/button_next" +            style="@style/Widget.Material3.Button.TextButton" +            android:layout_width="wrap_content" +            android:layout_height="wrap_content" +            android:text="@string/next" +            android:visibility="invisible" +            app:layout_constraintBottom_toBottomOf="parent" +            app:layout_constraintEnd_toEndOf="parent" /> + +        <com.google.android.material.button.MaterialButton +            android:id="@+id/button_back" +            style="@style/Widget.Material3.Button.TextButton" +            android:layout_width="wrap_content" +            android:layout_height="wrap_content" +            android:text="@string/back" +            android:visibility="invisible" +            app:layout_constraintBottom_toBottomOf="parent" +            app:layout_constraintStart_toStartOf="parent" /> + +    </androidx.constraintlayout.widget.ConstraintLayout> -</androidx.constraintlayout.widget.ConstraintLayout> +</RelativeLayout> diff --git a/src/android/app/src/main/res/layout-w600dp/page_setup.xml b/src/android/app/src/main/res/layout-w600dp/page_setup.xml index e1c26b2f8..9e0ab8ecb 100644 --- a/src/android/app/src/main/res/layout-w600dp/page_setup.xml +++ b/src/android/app/src/main/res/layout-w600dp/page_setup.xml @@ -21,45 +21,76 @@      </LinearLayout> -    <LinearLayout +    <androidx.constraintlayout.widget.ConstraintLayout          android:layout_width="match_parent"          android:layout_height="match_parent" -        android:layout_weight="1" -        android:orientation="vertical" -        android:gravity="center"> +        android:layout_weight="1">          <com.google.android.material.textview.MaterialTextView -            style="@style/TextAppearance.Material3.DisplaySmall"              android:id="@+id/text_title" -            android:layout_width="match_parent" -            android:layout_height="wrap_content" -            android:textAlignment="center" +            style="@style/TextAppearance.Material3.DisplaySmall" +            android:layout_width="0dp" +            android:layout_height="0dp" +            android:gravity="center"              android:textColor="?attr/colorOnSurface"              android:textStyle="bold" +            app:layout_constraintBottom_toTopOf="@+id/text_description" +            app:layout_constraintEnd_toEndOf="parent" +            app:layout_constraintStart_toStartOf="parent" +            app:layout_constraintTop_toTopOf="parent" +            app:layout_constraintVertical_weight="2"              tools:text="@string/welcome" />          <com.google.android.material.textview.MaterialTextView -            style="@style/TextAppearance.Material3.TitleLarge"              android:id="@+id/text_description" -            android:layout_width="match_parent" -            android:layout_height="wrap_content" -            android:layout_marginTop="16dp" -            android:paddingHorizontal="32dp" -            android:textAlignment="center" -            android:textSize="26sp" -            app:lineHeight="40sp" +            style="@style/TextAppearance.Material3.TitleLarge" +            android:layout_width="0dp" +            android:layout_height="0dp" +            android:gravity="center" +            android:textSize="20sp" +            android:paddingHorizontal="16dp" +            app:layout_constraintBottom_toTopOf="@+id/button_action" +            app:layout_constraintEnd_toEndOf="parent" +            app:layout_constraintStart_toStartOf="parent" +            app:layout_constraintTop_toBottomOf="@+id/text_title" +            app:layout_constraintVertical_weight="2" +            app:lineHeight="30sp"              tools:text="@string/welcome_description" /> +        <com.google.android.material.textview.MaterialTextView +            android:id="@+id/text_confirmation" +            style="@style/TextAppearance.Material3.TitleLarge" +            android:layout_width="0dp" +            android:layout_height="0dp" +            android:paddingHorizontal="16dp" +            android:paddingBottom="20dp" +            android:gravity="center" +            android:textSize="30sp" +            android:visibility="invisible" +            android:text="@string/step_complete" +            android:textStyle="bold" +            app:layout_constraintBottom_toBottomOf="parent" +            app:layout_constraintEnd_toEndOf="parent" +            app:layout_constraintStart_toStartOf="parent" +            app:layout_constraintTop_toBottomOf="@+id/text_description" +            app:layout_constraintVertical_weight="1" +            app:lineHeight="30sp" /> +          <com.google.android.material.button.MaterialButton              android:id="@+id/button_action"              android:layout_width="wrap_content"              android:layout_height="56dp" -            android:layout_marginTop="32dp" +            android:layout_marginTop="16dp" +            android:layout_marginBottom="48dp"              android:textSize="20sp" -            app:iconSize="24sp"              app:iconGravity="end" +            app:iconSize="24sp" +            app:layout_constraintBottom_toBottomOf="parent" +            app:layout_constraintEnd_toEndOf="parent" +            app:layout_constraintStart_toStartOf="parent" +            app:layout_constraintTop_toBottomOf="@+id/text_description"              tools:text="Get started" /> -    </LinearLayout> +    </androidx.constraintlayout.widget.ConstraintLayout>  </LinearLayout> diff --git a/src/android/app/src/main/res/layout/fragment_setup.xml b/src/android/app/src/main/res/layout/fragment_setup.xml index d7bafaea2..9499f6463 100644 --- a/src/android/app/src/main/res/layout/fragment_setup.xml +++ b/src/android/app/src/main/res/layout/fragment_setup.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout +<RelativeLayout      xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:app="http://schemas.android.com/apk/res-auto"      android:id="@+id/setup_root" @@ -8,35 +8,39 @@      <androidx.viewpager2.widget.ViewPager2          android:id="@+id/viewPager2" -        android:layout_width="0dp" -        android:layout_height="0dp" -        android:clipToPadding="false" -        android:layout_marginBottom="16dp" -        app:layout_constraintBottom_toTopOf="@+id/button_next" -        app:layout_constraintEnd_toEndOf="parent" -        app:layout_constraintStart_toStartOf="parent" -        app:layout_constraintTop_toTopOf="parent" /> - -    <com.google.android.material.button.MaterialButton -        style="@style/Widget.Material3.Button.TextButton" -        android:id="@+id/button_next" -        android:layout_width="wrap_content" +        android:layout_width="match_parent"          android:layout_height="wrap_content" -        android:layout_margin="12dp" -        android:text="@string/next" -        android:visibility="invisible" -        app:layout_constraintBottom_toBottomOf="parent" -        app:layout_constraintEnd_toEndOf="parent" /> +        android:layout_above="@+id/constraint_buttons" +        android:layout_alignParentTop="true" +        android:clipToPadding="false" /> -    <com.google.android.material.button.MaterialButton -        style="@style/Widget.Material3.Button.TextButton" -        android:id="@+id/button_back" -        android:layout_width="wrap_content" +    <androidx.constraintlayout.widget.ConstraintLayout +        android:id="@+id/constraint_buttons" +        android:layout_width="match_parent"          android:layout_height="wrap_content" -        android:layout_margin="12dp" -        android:text="@string/back" -        android:visibility="invisible" -        app:layout_constraintBottom_toBottomOf="parent" -        app:layout_constraintStart_toStartOf="parent" /> +        android:layout_margin="8dp" +        android:layout_alignParentBottom="true"> + +        <com.google.android.material.button.MaterialButton +            android:id="@+id/button_next" +            style="@style/Widget.Material3.Button.TextButton" +            android:layout_width="wrap_content" +            android:layout_height="wrap_content" +            android:text="@string/next" +            android:visibility="invisible" +            app:layout_constraintBottom_toBottomOf="parent" +            app:layout_constraintEnd_toEndOf="parent" /> + +        <com.google.android.material.button.MaterialButton +            android:id="@+id/button_back" +            style="@style/Widget.Material3.Button.TextButton" +            android:layout_width="wrap_content" +            android:layout_height="wrap_content" +            android:text="@string/back" +            android:visibility="invisible" +            app:layout_constraintBottom_toBottomOf="parent" +            app:layout_constraintStart_toStartOf="parent" /> + +    </androidx.constraintlayout.widget.ConstraintLayout> -</androidx.constraintlayout.widget.ConstraintLayout> +</RelativeLayout> diff --git a/src/android/app/src/main/res/layout/page_setup.xml b/src/android/app/src/main/res/layout/page_setup.xml index 1436ef308..535abcf02 100644 --- a/src/android/app/src/main/res/layout/page_setup.xml +++ b/src/android/app/src/main/res/layout/page_setup.xml @@ -21,11 +21,12 @@          app:layout_constraintVertical_chainStyle="spread"          app:layout_constraintWidth_max="220dp"          app:layout_constraintWidth_min="110dp" -        app:layout_constraintVertical_weight="3" /> +        app:layout_constraintVertical_weight="3" +        tools:src="@drawable/ic_notification" />      <com.google.android.material.textview.MaterialTextView          android:id="@+id/text_title" -        style="@style/TextAppearance.Material3.DisplayMedium" +        style="@style/TextAppearance.Material3.DisplaySmall"          android:layout_width="0dp"          android:layout_height="0dp"          android:textAlignment="center" @@ -44,23 +45,42 @@          android:layout_width="0dp"          android:layout_height="0dp"          android:textAlignment="center" -        android:textSize="26sp" +        android:textSize="20sp"          android:paddingHorizontal="16dp"          app:layout_constraintBottom_toTopOf="@+id/button_action"          app:layout_constraintEnd_toEndOf="parent"          app:layout_constraintStart_toStartOf="parent"          app:layout_constraintTop_toBottomOf="@+id/text_title"          app:layout_constraintVertical_weight="2" -        app:lineHeight="40sp" +        app:lineHeight="30sp"          tools:text="@string/welcome_description" /> +    <com.google.android.material.textview.MaterialTextView +        android:id="@+id/text_confirmation" +        style="@style/TextAppearance.Material3.TitleLarge" +        android:layout_width="wrap_content" +        android:layout_height="0dp" +        android:paddingHorizontal="16dp" +        android:paddingTop="24dp" +        android:textAlignment="center" +        android:textSize="30sp" +        android:visibility="invisible" +        android:text="@string/step_complete" +        android:textStyle="bold" +        app:layout_constraintBottom_toBottomOf="parent" +        app:layout_constraintEnd_toEndOf="parent" +        app:layout_constraintStart_toStartOf="parent" +        app:layout_constraintTop_toBottomOf="@+id/text_description" +        app:layout_constraintVertical_weight="1" +        app:lineHeight="30sp" /> +      <com.google.android.material.button.MaterialButton          android:id="@+id/button_action"          android:layout_width="wrap_content"          android:layout_height="56dp" -        android:textSize="20sp"          android:layout_marginTop="16dp"          android:layout_marginBottom="48dp" +        android:textSize="20sp"          app:iconGravity="end"          app:iconSize="24sp"          app:layout_constraintBottom_toBottomOf="parent" diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 82359f358..de1b2909b 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -29,6 +29,7 @@      <string name="back">Back</string>      <string name="add_games">Add Games</string>      <string name="add_games_description">Select your games folder</string> +    <string name="step_complete">Complete!</string>      <!-- Home strings -->      <string name="home_games">Games</string> | 
