diff options
Diffstat (limited to '')
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 | |||
| 5 | 5 | ||
| 6 | import android.text.Html | 6 | import android.text.Html |
| 7 | import android.view.LayoutInflater | 7 | import android.view.LayoutInflater |
| 8 | import android.view.View | ||
| 8 | import android.view.ViewGroup | 9 | import android.view.ViewGroup |
| 9 | import androidx.appcompat.app.AppCompatActivity | 10 | import androidx.appcompat.app.AppCompatActivity |
| 10 | import androidx.core.content.res.ResourcesCompat | 11 | import androidx.core.content.res.ResourcesCompat |
| 12 | import androidx.lifecycle.ViewModelProvider | ||
| 11 | import androidx.recyclerview.widget.RecyclerView | 13 | import androidx.recyclerview.widget.RecyclerView |
| 12 | import com.google.android.material.button.MaterialButton | 14 | import com.google.android.material.button.MaterialButton |
| 13 | import org.yuzu.yuzu_emu.databinding.PageSetupBinding | 15 | import org.yuzu.yuzu_emu.databinding.PageSetupBinding |
| 16 | import org.yuzu.yuzu_emu.model.HomeViewModel | ||
| 17 | import org.yuzu.yuzu_emu.model.SetupCallback | ||
| 14 | import org.yuzu.yuzu_emu.model.SetupPage | 18 | import org.yuzu.yuzu_emu.model.SetupPage |
| 19 | import org.yuzu.yuzu_emu.model.StepState | ||
| 20 | import org.yuzu.yuzu_emu.utils.ViewUtils | ||
| 15 | 21 | ||
| 16 | class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) : | 22 | class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) : |
| 17 | RecyclerView.Adapter<SetupAdapter.SetupPageViewHolder>() { | 23 | RecyclerView.Adapter<SetupAdapter.SetupPageViewHolder>() { |
| @@ -26,7 +32,7 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) | |||
| 26 | holder.bind(pages[position]) | 32 | holder.bind(pages[position]) |
| 27 | 33 | ||
| 28 | inner class SetupPageViewHolder(val binding: PageSetupBinding) : | 34 | inner class SetupPageViewHolder(val binding: PageSetupBinding) : |
| 29 | RecyclerView.ViewHolder(binding.root) { | 35 | RecyclerView.ViewHolder(binding.root), SetupCallback { |
| 30 | lateinit var page: SetupPage | 36 | lateinit var page: SetupPage |
| 31 | 37 | ||
| 32 | init { | 38 | init { |
| @@ -35,6 +41,12 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) | |||
| 35 | 41 | ||
| 36 | fun bind(page: SetupPage) { | 42 | fun bind(page: SetupPage) { |
| 37 | this.page = page | 43 | this.page = page |
| 44 | |||
| 45 | if (page.stepCompleted.invoke() == StepState.COMPLETE) { | ||
| 46 | binding.buttonAction.visibility = View.INVISIBLE | ||
| 47 | binding.textConfirmation.visibility = View.VISIBLE | ||
| 48 | } | ||
| 49 | |||
| 38 | binding.icon.setImageDrawable( | 50 | binding.icon.setImageDrawable( |
| 39 | ResourcesCompat.getDrawable( | 51 | ResourcesCompat.getDrawable( |
| 40 | activity.resources, | 52 | activity.resources, |
| @@ -62,9 +74,15 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) | |||
| 62 | MaterialButton.ICON_GRAVITY_END | 74 | MaterialButton.ICON_GRAVITY_END |
| 63 | } | 75 | } |
| 64 | setOnClickListener { | 76 | setOnClickListener { |
| 65 | page.buttonAction.invoke() | 77 | page.buttonAction.invoke(this@SetupPageViewHolder) |
| 66 | } | 78 | } |
| 67 | } | 79 | } |
| 68 | } | 80 | } |
| 81 | |||
| 82 | override fun onStepCompleted() { | ||
| 83 | ViewUtils.hideView(binding.buttonAction, 200) | ||
| 84 | ViewUtils.showView(binding.textConfirmation, 200) | ||
| 85 | ViewModelProvider(activity)[HomeViewModel::class.java].setShouldPageForward(true) | ||
| 86 | } | ||
| 69 | } | 87 | } |
| 70 | } | 88 | } |
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 | |||
| 19 | import androidx.core.view.ViewCompat | 19 | import androidx.core.view.ViewCompat |
| 20 | import androidx.core.view.WindowInsetsCompat | 20 | import androidx.core.view.WindowInsetsCompat |
| 21 | import androidx.core.view.isVisible | 21 | import androidx.core.view.isVisible |
| 22 | import androidx.core.view.updatePadding | ||
| 22 | import androidx.fragment.app.Fragment | 23 | import androidx.fragment.app.Fragment |
| 23 | import androidx.fragment.app.activityViewModels | 24 | import androidx.fragment.app.activityViewModels |
| 24 | import androidx.navigation.findNavController | 25 | import androidx.navigation.findNavController |
| @@ -32,10 +33,13 @@ import org.yuzu.yuzu_emu.adapters.SetupAdapter | |||
| 32 | import org.yuzu.yuzu_emu.databinding.FragmentSetupBinding | 33 | import org.yuzu.yuzu_emu.databinding.FragmentSetupBinding |
| 33 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 34 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 34 | import org.yuzu.yuzu_emu.model.HomeViewModel | 35 | import org.yuzu.yuzu_emu.model.HomeViewModel |
| 36 | import org.yuzu.yuzu_emu.model.SetupCallback | ||
| 35 | import org.yuzu.yuzu_emu.model.SetupPage | 37 | import org.yuzu.yuzu_emu.model.SetupPage |
| 38 | import org.yuzu.yuzu_emu.model.StepState | ||
| 36 | import org.yuzu.yuzu_emu.ui.main.MainActivity | 39 | import org.yuzu.yuzu_emu.ui.main.MainActivity |
| 37 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization | 40 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization |
| 38 | import org.yuzu.yuzu_emu.utils.GameHelper | 41 | import org.yuzu.yuzu_emu.utils.GameHelper |
| 42 | import org.yuzu.yuzu_emu.utils.ViewUtils | ||
| 39 | 43 | ||
| 40 | class SetupFragment : Fragment() { | 44 | class SetupFragment : Fragment() { |
| 41 | private var _binding: FragmentSetupBinding? = null | 45 | private var _binding: FragmentSetupBinding? = null |
| @@ -112,14 +116,22 @@ class SetupFragment : Fragment() { | |||
| 112 | 0, | 116 | 0, |
| 113 | false, | 117 | false, |
| 114 | R.string.give_permission, | 118 | R.string.give_permission, |
| 115 | { permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) }, | 119 | { |
| 120 | notificationCallback = it | ||
| 121 | permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) | ||
| 122 | }, | ||
| 116 | true, | 123 | true, |
| 117 | R.string.notification_warning, | 124 | R.string.notification_warning, |
| 118 | R.string.notification_warning_description, | 125 | R.string.notification_warning_description, |
| 119 | 0, | 126 | 0, |
| 120 | { | 127 | { |
| 121 | NotificationManagerCompat.from(requireContext()) | 128 | if (NotificationManagerCompat.from(requireContext()) |
| 122 | .areNotificationsEnabled() | 129 | .areNotificationsEnabled() |
| 130 | ) { | ||
| 131 | StepState.COMPLETE | ||
| 132 | } else { | ||
| 133 | StepState.INCOMPLETE | ||
| 134 | } | ||
| 123 | } | 135 | } |
| 124 | ) | 136 | ) |
| 125 | ) | 137 | ) |
| @@ -133,12 +145,22 @@ class SetupFragment : Fragment() { | |||
| 133 | R.drawable.ic_add, | 145 | R.drawable.ic_add, |
| 134 | true, | 146 | true, |
| 135 | R.string.select_keys, | 147 | R.string.select_keys, |
| 136 | { mainActivity.getProdKey.launch(arrayOf("*/*")) }, | 148 | { |
| 149 | keyCallback = it | ||
| 150 | getProdKey.launch(arrayOf("*/*")) | ||
| 151 | }, | ||
| 137 | true, | 152 | true, |
| 138 | R.string.install_prod_keys_warning, | 153 | R.string.install_prod_keys_warning, |
| 139 | R.string.install_prod_keys_warning_description, | 154 | R.string.install_prod_keys_warning_description, |
| 140 | R.string.install_prod_keys_warning_help, | 155 | R.string.install_prod_keys_warning_help, |
| 141 | { File(DirectoryInitialization.userDirectory + "/keys/prod.keys").exists() } | 156 | { |
| 157 | val file = File(DirectoryInitialization.userDirectory + "/keys/prod.keys") | ||
| 158 | if (file.exists()) { | ||
| 159 | StepState.COMPLETE | ||
| 160 | } else { | ||
| 161 | StepState.INCOMPLETE | ||
| 162 | } | ||
| 163 | } | ||
| 142 | ) | 164 | ) |
| 143 | ) | 165 | ) |
| 144 | add( | 166 | add( |
| @@ -150,9 +172,8 @@ class SetupFragment : Fragment() { | |||
| 150 | true, | 172 | true, |
| 151 | R.string.add_games, | 173 | R.string.add_games, |
| 152 | { | 174 | { |
| 153 | mainActivity.getGamesDirectory.launch( | 175 | gamesDirCallback = it |
| 154 | Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data | 176 | getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data) |
| 155 | ) | ||
| 156 | }, | 177 | }, |
| 157 | true, | 178 | true, |
| 158 | R.string.add_games_warning, | 179 | R.string.add_games_warning, |
| @@ -163,7 +184,11 @@ class SetupFragment : Fragment() { | |||
| 163 | PreferenceManager.getDefaultSharedPreferences( | 184 | PreferenceManager.getDefaultSharedPreferences( |
| 164 | YuzuApplication.appContext | 185 | YuzuApplication.appContext |
| 165 | ) | 186 | ) |
| 166 | preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty() | 187 | if (preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty()) { |
| 188 | StepState.COMPLETE | ||
| 189 | } else { | ||
| 190 | StepState.INCOMPLETE | ||
| 191 | } | ||
| 167 | } | 192 | } |
| 168 | ) | 193 | ) |
| 169 | ) | 194 | ) |
| @@ -181,6 +206,13 @@ class SetupFragment : Fragment() { | |||
| 181 | ) | 206 | ) |
| 182 | } | 207 | } |
| 183 | 208 | ||
| 209 | homeViewModel.shouldPageForward.observe(viewLifecycleOwner) { | ||
| 210 | if (it) { | ||
| 211 | pageForward() | ||
| 212 | homeViewModel.setShouldPageForward(false) | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 184 | binding.viewPager2.apply { | 216 | binding.viewPager2.apply { |
| 185 | adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages) | 217 | adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages) |
| 186 | offscreenPageLimit = 2 | 218 | offscreenPageLimit = 2 |
| @@ -194,15 +226,15 @@ class SetupFragment : Fragment() { | |||
| 194 | super.onPageSelected(position) | 226 | super.onPageSelected(position) |
| 195 | 227 | ||
| 196 | if (position == 1 && previousPosition == 0) { | 228 | if (position == 1 && previousPosition == 0) { |
| 197 | showView(binding.buttonNext) | 229 | ViewUtils.showView(binding.buttonNext) |
| 198 | showView(binding.buttonBack) | 230 | ViewUtils.showView(binding.buttonBack) |
| 199 | } else if (position == 0 && previousPosition == 1) { | 231 | } else if (position == 0 && previousPosition == 1) { |
| 200 | hideView(binding.buttonBack) | 232 | ViewUtils.hideView(binding.buttonBack) |
| 201 | hideView(binding.buttonNext) | 233 | ViewUtils.hideView(binding.buttonNext) |
| 202 | } else if (position == pages.size - 1 && previousPosition == pages.size - 2) { | 234 | } else if (position == pages.size - 1 && previousPosition == pages.size - 2) { |
| 203 | hideView(binding.buttonNext) | 235 | ViewUtils.hideView(binding.buttonNext) |
| 204 | } else if (position == pages.size - 2 && previousPosition == pages.size - 1) { | 236 | } else if (position == pages.size - 2 && previousPosition == pages.size - 1) { |
| 205 | showView(binding.buttonNext) | 237 | ViewUtils.showView(binding.buttonNext) |
| 206 | } | 238 | } |
| 207 | 239 | ||
| 208 | previousPosition = position | 240 | previousPosition = position |
| @@ -215,7 +247,8 @@ class SetupFragment : Fragment() { | |||
| 215 | 247 | ||
| 216 | // Checks if the user has completed the task on the current page | 248 | // Checks if the user has completed the task on the current page |
| 217 | if (currentPage.hasWarning) { | 249 | if (currentPage.hasWarning) { |
| 218 | if (currentPage.taskCompleted.invoke()) { | 250 | val stepState = currentPage.stepCompleted.invoke() |
| 251 | if (stepState != StepState.INCOMPLETE) { | ||
| 219 | pageForward() | 252 | pageForward() |
| 220 | return@setOnClickListener | 253 | return@setOnClickListener |
| 221 | } | 254 | } |
| @@ -264,9 +297,15 @@ class SetupFragment : Fragment() { | |||
| 264 | _binding = null | 297 | _binding = null |
| 265 | } | 298 | } |
| 266 | 299 | ||
| 300 | private lateinit var notificationCallback: SetupCallback | ||
| 301 | |||
| 267 | @RequiresApi(Build.VERSION_CODES.TIRAMISU) | 302 | @RequiresApi(Build.VERSION_CODES.TIRAMISU) |
| 268 | private val permissionLauncher = | 303 | private val permissionLauncher = |
| 269 | registerForActivityResult(ActivityResultContracts.RequestPermission()) { | 304 | registerForActivityResult(ActivityResultContracts.RequestPermission()) { |
| 305 | if (it) { | ||
| 306 | notificationCallback.onStepCompleted() | ||
| 307 | } | ||
| 308 | |||
| 270 | if (!it && | 309 | if (!it && |
| 271 | !shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS) | 310 | !shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS) |
| 272 | ) { | 311 | ) { |
| @@ -277,6 +316,27 @@ class SetupFragment : Fragment() { | |||
| 277 | } | 316 | } |
| 278 | } | 317 | } |
| 279 | 318 | ||
| 319 | private lateinit var keyCallback: SetupCallback | ||
| 320 | |||
| 321 | val getProdKey = | ||
| 322 | registerForActivityResult(ActivityResultContracts.OpenDocument()) { result -> | ||
| 323 | if (result != null) { | ||
| 324 | if (mainActivity.processKey(result)) { | ||
| 325 | keyCallback.onStepCompleted() | ||
| 326 | } | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | private lateinit var gamesDirCallback: SetupCallback | ||
| 331 | |||
| 332 | val getGamesDirectory = | ||
| 333 | registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result -> | ||
| 334 | if (result != null) { | ||
| 335 | mainActivity.processGamesDir(result) | ||
| 336 | gamesDirCallback.onStepCompleted() | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 280 | private fun finishSetup() { | 340 | private fun finishSetup() { |
| 281 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit() | 341 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit() |
| 282 | .putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false) | 342 | .putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false) |
| @@ -284,33 +344,6 @@ class SetupFragment : Fragment() { | |||
| 284 | mainActivity.finishSetup(binding.root.findNavController()) | 344 | mainActivity.finishSetup(binding.root.findNavController()) |
| 285 | } | 345 | } |
| 286 | 346 | ||
| 287 | private fun showView(view: View) { | ||
| 288 | view.apply { | ||
| 289 | alpha = 0f | ||
| 290 | visibility = View.VISIBLE | ||
| 291 | isClickable = true | ||
| 292 | }.animate().apply { | ||
| 293 | duration = 300 | ||
| 294 | alpha(1f) | ||
| 295 | }.start() | ||
| 296 | } | ||
| 297 | |||
| 298 | private fun hideView(view: View) { | ||
| 299 | if (view.visibility == View.INVISIBLE) { | ||
| 300 | return | ||
| 301 | } | ||
| 302 | |||
| 303 | view.apply { | ||
| 304 | alpha = 1f | ||
| 305 | isClickable = false | ||
| 306 | }.animate().apply { | ||
| 307 | duration = 300 | ||
| 308 | alpha(0f) | ||
| 309 | }.withEndAction { | ||
| 310 | view.visibility = View.INVISIBLE | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | fun pageForward() { | 347 | fun pageForward() { |
| 315 | binding.viewPager2.currentItem = binding.viewPager2.currentItem + 1 | 348 | binding.viewPager2.currentItem = binding.viewPager2.currentItem + 1 |
| 316 | } | 349 | } |
| @@ -326,15 +359,29 @@ class SetupFragment : Fragment() { | |||
| 326 | private fun setInsets() = | 359 | private fun setInsets() = |
| 327 | ViewCompat.setOnApplyWindowInsetsListener( | 360 | ViewCompat.setOnApplyWindowInsetsListener( |
| 328 | binding.root | 361 | binding.root |
| 329 | ) { view: View, windowInsets: WindowInsetsCompat -> | 362 | ) { _: View, windowInsets: WindowInsetsCompat -> |
| 330 | val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) | 363 | val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) |
| 331 | val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()) | 364 | val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()) |
| 332 | view.setPadding( | 365 | |
| 333 | barInsets.left + cutoutInsets.left, | 366 | val leftPadding = barInsets.left + cutoutInsets.left |
| 334 | barInsets.top + cutoutInsets.top, | 367 | val topPadding = barInsets.top + cutoutInsets.top |
| 335 | barInsets.right + cutoutInsets.right, | 368 | val rightPadding = barInsets.right + cutoutInsets.right |
| 336 | barInsets.bottom + cutoutInsets.bottom | 369 | val bottomPadding = barInsets.bottom + cutoutInsets.bottom |
| 337 | ) | 370 | |
| 371 | if (resources.getBoolean(R.bool.small_layout)) { | ||
| 372 | binding.viewPager2 | ||
| 373 | .updatePadding(left = leftPadding, top = topPadding, right = rightPadding) | ||
| 374 | binding.constraintButtons | ||
| 375 | .updatePadding(left = leftPadding, right = rightPadding, bottom = bottomPadding) | ||
| 376 | } else { | ||
| 377 | binding.viewPager2.updatePadding(top = topPadding, bottom = bottomPadding) | ||
| 378 | binding.constraintButtons | ||
| 379 | .updatePadding( | ||
| 380 | left = leftPadding, | ||
| 381 | right = rightPadding, | ||
| 382 | bottom = bottomPadding | ||
| 383 | ) | ||
| 384 | } | ||
| 338 | windowInsets | 385 | windowInsets |
| 339 | } | 386 | } |
| 340 | } | 387 | } |
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() { | |||
| 14 | private val _statusBarShadeVisible = MutableLiveData(true) | 14 | private val _statusBarShadeVisible = MutableLiveData(true) |
| 15 | val statusBarShadeVisible: LiveData<Boolean> get() = _statusBarShadeVisible | 15 | val statusBarShadeVisible: LiveData<Boolean> get() = _statusBarShadeVisible |
| 16 | 16 | ||
| 17 | private val _shouldPageForward = MutableLiveData(false) | ||
| 18 | val shouldPageForward: LiveData<Boolean> get() = _shouldPageForward | ||
| 19 | |||
| 17 | var navigatedToSetup = false | 20 | var navigatedToSetup = false |
| 18 | 21 | ||
| 19 | init { | 22 | init { |
| @@ -33,4 +36,8 @@ class HomeViewModel : ViewModel() { | |||
| 33 | } | 36 | } |
| 34 | _statusBarShadeVisible.value = visible | 37 | _statusBarShadeVisible.value = visible |
| 35 | } | 38 | } |
| 39 | |||
| 40 | fun setShouldPageForward(pageForward: Boolean) { | ||
| 41 | _shouldPageForward.value = pageForward | ||
| 42 | } | ||
| 36 | } | 43 | } |
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( | |||
| 10 | val buttonIconId: Int, | 10 | val buttonIconId: Int, |
| 11 | val leftAlignedIcon: Boolean, | 11 | val leftAlignedIcon: Boolean, |
| 12 | val buttonTextId: Int, | 12 | val buttonTextId: Int, |
| 13 | val buttonAction: () -> Unit, | 13 | val buttonAction: (callback: SetupCallback) -> Unit, |
| 14 | val hasWarning: Boolean, | 14 | val hasWarning: Boolean, |
| 15 | val warningTitleId: Int = 0, | 15 | val warningTitleId: Int = 0, |
| 16 | val warningDescriptionId: Int = 0, | 16 | val warningDescriptionId: Int = 0, |
| 17 | val warningHelpLinkId: Int = 0, | 17 | val warningHelpLinkId: Int = 0, |
| 18 | val taskCompleted: () -> Boolean = { true } | 18 | val stepCompleted: () -> StepState = { StepState.UNDEFINED } |
| 19 | ) | 19 | ) |
| 20 | |||
| 21 | interface SetupCallback { | ||
| 22 | fun onStepCompleted() | ||
| 23 | } | ||
| 24 | |||
| 25 | enum class StepState { | ||
| 26 | COMPLETE, | ||
| 27 | INCOMPLETE, | ||
| 28 | UNDEFINED | ||
| 29 | } | ||
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 { | |||
| 266 | 266 | ||
| 267 | val getGamesDirectory = | 267 | val getGamesDirectory = |
| 268 | registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result -> | 268 | registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result -> |
| 269 | if (result == null) { | 269 | if (result != null) { |
| 270 | return@registerForActivityResult | 270 | processGamesDir(result) |
| 271 | } | 271 | } |
| 272 | } | ||
| 272 | 273 | ||
| 273 | contentResolver.takePersistableUriPermission( | 274 | fun processGamesDir(result: Uri) { |
| 274 | result, | 275 | contentResolver.takePersistableUriPermission( |
| 275 | Intent.FLAG_GRANT_READ_URI_PERMISSION | 276 | result, |
| 276 | ) | 277 | Intent.FLAG_GRANT_READ_URI_PERMISSION |
| 278 | ) | ||
| 277 | 279 | ||
| 278 | // When a new directory is picked, we currently will reset the existing games | 280 | // When a new directory is picked, we currently will reset the existing games |
| 279 | // database. This effectively means that only one game directory is supported. | 281 | // database. This effectively means that only one game directory is supported. |
| 280 | PreferenceManager.getDefaultSharedPreferences(applicationContext).edit() | 282 | PreferenceManager.getDefaultSharedPreferences(applicationContext).edit() |
| 281 | .putString(GameHelper.KEY_GAME_PATH, result.toString()) | 283 | .putString(GameHelper.KEY_GAME_PATH, result.toString()) |
| 282 | .apply() | 284 | .apply() |
| 283 | 285 | ||
| 284 | Toast.makeText( | 286 | Toast.makeText( |
| 285 | applicationContext, | 287 | applicationContext, |
| 286 | R.string.games_dir_selected, | 288 | R.string.games_dir_selected, |
| 287 | Toast.LENGTH_LONG | 289 | Toast.LENGTH_LONG |
| 288 | ).show() | 290 | ).show() |
| 289 | 291 | ||
| 290 | gamesViewModel.reloadGames(true) | 292 | gamesViewModel.reloadGames(true) |
| 291 | } | 293 | } |
| 292 | 294 | ||
| 293 | val getProdKey = | 295 | val getProdKey = |
| 294 | registerForActivityResult(ActivityResultContracts.OpenDocument()) { result -> | 296 | registerForActivityResult(ActivityResultContracts.OpenDocument()) { result -> |
| 295 | if (result == null) { | 297 | if (result != null) { |
| 296 | return@registerForActivityResult | 298 | processKey(result) |
| 297 | } | 299 | } |
| 300 | } | ||
| 298 | 301 | ||
| 299 | if (FileUtil.getExtension(result) != "keys") { | 302 | fun processKey(result: Uri): Boolean { |
| 300 | MessageDialogFragment.newInstance( | 303 | if (FileUtil.getExtension(result) != "keys") { |
| 301 | R.string.reading_keys_failure, | 304 | MessageDialogFragment.newInstance( |
| 302 | R.string.install_prod_keys_failure_extension_description | 305 | R.string.reading_keys_failure, |
| 303 | ).show(supportFragmentManager, MessageDialogFragment.TAG) | 306 | R.string.install_prod_keys_failure_extension_description |
| 304 | return@registerForActivityResult | 307 | ).show(supportFragmentManager, MessageDialogFragment.TAG) |
| 305 | } | 308 | return false |
| 309 | } | ||
| 306 | 310 | ||
| 307 | contentResolver.takePersistableUriPermission( | 311 | contentResolver.takePersistableUriPermission( |
| 312 | result, | ||
| 313 | Intent.FLAG_GRANT_READ_URI_PERMISSION | ||
| 314 | ) | ||
| 315 | |||
| 316 | val dstPath = DirectoryInitialization.userDirectory + "/keys/" | ||
| 317 | if (FileUtil.copyUriToInternalStorage( | ||
| 318 | applicationContext, | ||
| 308 | result, | 319 | result, |
| 309 | Intent.FLAG_GRANT_READ_URI_PERMISSION | 320 | dstPath, |
| 321 | "prod.keys" | ||
| 310 | ) | 322 | ) |
| 311 | 323 | ) { | |
| 312 | val dstPath = DirectoryInitialization.userDirectory + "/keys/" | 324 | if (NativeLibrary.reloadKeys()) { |
| 313 | if (FileUtil.copyUriToInternalStorage( | 325 | Toast.makeText( |
| 314 | applicationContext, | 326 | applicationContext, |
| 315 | result, | 327 | R.string.install_keys_success, |
| 316 | dstPath, | 328 | Toast.LENGTH_SHORT |
| 317 | "prod.keys" | 329 | ).show() |
| 318 | ) | 330 | gamesViewModel.reloadGames(true) |
| 319 | ) { | 331 | return true |
| 320 | if (NativeLibrary.reloadKeys()) { | 332 | } else { |
| 321 | Toast.makeText( | 333 | MessageDialogFragment.newInstance( |
| 322 | applicationContext, | 334 | R.string.invalid_keys_error, |
| 323 | R.string.install_keys_success, | 335 | R.string.install_keys_failure_description, |
| 324 | Toast.LENGTH_SHORT | 336 | R.string.dumping_keys_quickstart_link |
| 325 | ).show() | 337 | ).show(supportFragmentManager, MessageDialogFragment.TAG) |
| 326 | gamesViewModel.reloadGames(true) | 338 | return false |
| 327 | } else { | ||
| 328 | MessageDialogFragment.newInstance( | ||
| 329 | R.string.invalid_keys_error, | ||
| 330 | R.string.install_keys_failure_description, | ||
| 331 | R.string.dumping_keys_quickstart_link | ||
| 332 | ).show(supportFragmentManager, MessageDialogFragment.TAG) | ||
| 333 | } | ||
| 334 | } | 339 | } |
| 335 | } | 340 | } |
| 341 | return false | ||
| 342 | } | ||
| 336 | 343 | ||
| 337 | val getFirmware = | 344 | val getFirmware = |
| 338 | registerForActivityResult(ActivityResultContracts.OpenDocument()) { result -> | 345 | 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 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.utils | ||
| 5 | |||
| 6 | import android.view.View | ||
| 7 | |||
| 8 | object ViewUtils { | ||
| 9 | fun showView(view: View, length: Long = 300) { | ||
| 10 | view.apply { | ||
| 11 | alpha = 0f | ||
| 12 | visibility = View.VISIBLE | ||
| 13 | isClickable = true | ||
| 14 | }.animate().apply { | ||
| 15 | duration = length | ||
| 16 | alpha(1f) | ||
| 17 | }.start() | ||
| 18 | } | ||
| 19 | |||
| 20 | fun hideView(view: View, length: Long = 300) { | ||
| 21 | if (view.visibility == View.INVISIBLE) { | ||
| 22 | return | ||
| 23 | } | ||
| 24 | |||
| 25 | view.apply { | ||
| 26 | alpha = 1f | ||
| 27 | isClickable = false | ||
| 28 | }.animate().apply { | ||
| 29 | duration = length | ||
| 30 | alpha(0f) | ||
| 31 | }.withEndAction { | ||
| 32 | view.visibility = View.INVISIBLE | ||
| 33 | }.start() | ||
| 34 | } | ||
| 35 | } | ||
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 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <androidx.constraintlayout.widget.ConstraintLayout | 2 | <RelativeLayout |
| 3 | xmlns:android="http://schemas.android.com/apk/res/android" | 3 | xmlns:android="http://schemas.android.com/apk/res/android" |
| 4 | xmlns:app="http://schemas.android.com/apk/res-auto" | 4 | xmlns:app="http://schemas.android.com/apk/res-auto" |
| 5 | android:id="@+id/setup_root" | 5 | android:id="@+id/setup_root" |
| @@ -8,33 +8,39 @@ | |||
| 8 | 8 | ||
| 9 | <androidx.viewpager2.widget.ViewPager2 | 9 | <androidx.viewpager2.widget.ViewPager2 |
| 10 | android:id="@+id/viewPager2" | 10 | android:id="@+id/viewPager2" |
| 11 | android:layout_width="0dp" | 11 | android:layout_width="match_parent" |
| 12 | android:layout_height="0dp" | 12 | android:layout_height="match_parent" |
| 13 | app:layout_constraintBottom_toBottomOf="parent" | 13 | android:layout_alignParentTop="true" |
| 14 | app:layout_constraintEnd_toEndOf="parent" | 14 | android:layout_alignParentBottom="true" |
| 15 | app:layout_constraintStart_toStartOf="parent" | 15 | android:clipToPadding="false" /> |
| 16 | app:layout_constraintTop_toTopOf="parent" /> | ||
| 17 | 16 | ||
| 18 | <com.google.android.material.button.MaterialButton | 17 | <androidx.constraintlayout.widget.ConstraintLayout |
| 19 | style="@style/Widget.Material3.Button.TextButton" | 18 | android:id="@+id/constraint_buttons" |
| 20 | android:id="@+id/button_next" | 19 | android:layout_width="match_parent" |
| 21 | android:layout_width="wrap_content" | ||
| 22 | android:layout_height="wrap_content" | 20 | android:layout_height="wrap_content" |
| 23 | android:layout_margin="16dp" | 21 | android:layout_alignParentBottom="true" |
| 24 | android:text="@string/next" | 22 | android:layout_margin="8dp"> |
| 25 | android:visibility="invisible" | ||
| 26 | app:layout_constraintBottom_toBottomOf="parent" | ||
| 27 | app:layout_constraintEnd_toEndOf="parent" /> | ||
| 28 | 23 | ||
| 29 | <com.google.android.material.button.MaterialButton | 24 | <com.google.android.material.button.MaterialButton |
| 30 | android:id="@+id/button_back" | 25 | android:id="@+id/button_next" |
| 31 | style="@style/Widget.Material3.Button.TextButton" | 26 | style="@style/Widget.Material3.Button.TextButton" |
| 32 | android:layout_width="wrap_content" | 27 | android:layout_width="wrap_content" |
| 33 | android:layout_height="wrap_content" | 28 | android:layout_height="wrap_content" |
| 34 | android:layout_margin="16dp" | 29 | android:text="@string/next" |
| 35 | android:text="@string/back" | 30 | android:visibility="invisible" |
| 36 | android:visibility="invisible" | 31 | app:layout_constraintBottom_toBottomOf="parent" |
| 37 | app:layout_constraintBottom_toBottomOf="parent" | 32 | app:layout_constraintEnd_toEndOf="parent" /> |
| 38 | app:layout_constraintStart_toStartOf="parent" /> | 33 | |
| 34 | <com.google.android.material.button.MaterialButton | ||
| 35 | android:id="@+id/button_back" | ||
| 36 | style="@style/Widget.Material3.Button.TextButton" | ||
| 37 | android:layout_width="wrap_content" | ||
| 38 | android:layout_height="wrap_content" | ||
| 39 | android:text="@string/back" | ||
| 40 | android:visibility="invisible" | ||
| 41 | app:layout_constraintBottom_toBottomOf="parent" | ||
| 42 | app:layout_constraintStart_toStartOf="parent" /> | ||
| 43 | |||
| 44 | </androidx.constraintlayout.widget.ConstraintLayout> | ||
| 39 | 45 | ||
| 40 | </androidx.constraintlayout.widget.ConstraintLayout> | 46 | </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 @@ | |||
| 21 | 21 | ||
| 22 | </LinearLayout> | 22 | </LinearLayout> |
| 23 | 23 | ||
| 24 | <LinearLayout | 24 | <androidx.constraintlayout.widget.ConstraintLayout |
| 25 | android:layout_width="match_parent" | 25 | android:layout_width="match_parent" |
| 26 | android:layout_height="match_parent" | 26 | android:layout_height="match_parent" |
| 27 | android:layout_weight="1" | 27 | android:layout_weight="1"> |
| 28 | android:orientation="vertical" | ||
| 29 | android:gravity="center"> | ||
| 30 | 28 | ||
| 31 | <com.google.android.material.textview.MaterialTextView | 29 | <com.google.android.material.textview.MaterialTextView |
| 32 | style="@style/TextAppearance.Material3.DisplaySmall" | ||
| 33 | android:id="@+id/text_title" | 30 | android:id="@+id/text_title" |
| 34 | android:layout_width="match_parent" | 31 | style="@style/TextAppearance.Material3.DisplaySmall" |
| 35 | android:layout_height="wrap_content" | 32 | android:layout_width="0dp" |
| 36 | android:textAlignment="center" | 33 | android:layout_height="0dp" |
| 34 | android:gravity="center" | ||
| 37 | android:textColor="?attr/colorOnSurface" | 35 | android:textColor="?attr/colorOnSurface" |
| 38 | android:textStyle="bold" | 36 | android:textStyle="bold" |
| 37 | app:layout_constraintBottom_toTopOf="@+id/text_description" | ||
| 38 | app:layout_constraintEnd_toEndOf="parent" | ||
| 39 | app:layout_constraintStart_toStartOf="parent" | ||
| 40 | app:layout_constraintTop_toTopOf="parent" | ||
| 41 | app:layout_constraintVertical_weight="2" | ||
| 39 | tools:text="@string/welcome" /> | 42 | tools:text="@string/welcome" /> |
| 40 | 43 | ||
| 41 | <com.google.android.material.textview.MaterialTextView | 44 | <com.google.android.material.textview.MaterialTextView |
| 42 | style="@style/TextAppearance.Material3.TitleLarge" | ||
| 43 | android:id="@+id/text_description" | 45 | android:id="@+id/text_description" |
| 44 | android:layout_width="match_parent" | 46 | style="@style/TextAppearance.Material3.TitleLarge" |
| 45 | android:layout_height="wrap_content" | 47 | android:layout_width="0dp" |
| 46 | android:layout_marginTop="16dp" | 48 | android:layout_height="0dp" |
| 47 | android:paddingHorizontal="32dp" | 49 | android:gravity="center" |
| 48 | android:textAlignment="center" | 50 | android:textSize="20sp" |
| 49 | android:textSize="26sp" | 51 | android:paddingHorizontal="16dp" |
| 50 | app:lineHeight="40sp" | 52 | app:layout_constraintBottom_toTopOf="@+id/button_action" |
| 53 | app:layout_constraintEnd_toEndOf="parent" | ||
| 54 | app:layout_constraintStart_toStartOf="parent" | ||
| 55 | app:layout_constraintTop_toBottomOf="@+id/text_title" | ||
| 56 | app:layout_constraintVertical_weight="2" | ||
| 57 | app:lineHeight="30sp" | ||
| 51 | tools:text="@string/welcome_description" /> | 58 | tools:text="@string/welcome_description" /> |
| 52 | 59 | ||
| 60 | <com.google.android.material.textview.MaterialTextView | ||
| 61 | android:id="@+id/text_confirmation" | ||
| 62 | style="@style/TextAppearance.Material3.TitleLarge" | ||
| 63 | android:layout_width="0dp" | ||
| 64 | android:layout_height="0dp" | ||
| 65 | android:paddingHorizontal="16dp" | ||
| 66 | android:paddingBottom="20dp" | ||
| 67 | android:gravity="center" | ||
| 68 | android:textSize="30sp" | ||
| 69 | android:visibility="invisible" | ||
| 70 | android:text="@string/step_complete" | ||
| 71 | android:textStyle="bold" | ||
| 72 | app:layout_constraintBottom_toBottomOf="parent" | ||
| 73 | app:layout_constraintEnd_toEndOf="parent" | ||
| 74 | app:layout_constraintStart_toStartOf="parent" | ||
| 75 | app:layout_constraintTop_toBottomOf="@+id/text_description" | ||
| 76 | app:layout_constraintVertical_weight="1" | ||
| 77 | app:lineHeight="30sp" /> | ||
| 78 | |||
| 53 | <com.google.android.material.button.MaterialButton | 79 | <com.google.android.material.button.MaterialButton |
| 54 | android:id="@+id/button_action" | 80 | android:id="@+id/button_action" |
| 55 | android:layout_width="wrap_content" | 81 | android:layout_width="wrap_content" |
| 56 | android:layout_height="56dp" | 82 | android:layout_height="56dp" |
| 57 | android:layout_marginTop="32dp" | 83 | android:layout_marginTop="16dp" |
| 84 | android:layout_marginBottom="48dp" | ||
| 58 | android:textSize="20sp" | 85 | android:textSize="20sp" |
| 59 | app:iconSize="24sp" | ||
| 60 | app:iconGravity="end" | 86 | app:iconGravity="end" |
| 87 | app:iconSize="24sp" | ||
| 88 | app:layout_constraintBottom_toBottomOf="parent" | ||
| 89 | app:layout_constraintEnd_toEndOf="parent" | ||
| 90 | app:layout_constraintStart_toStartOf="parent" | ||
| 91 | app:layout_constraintTop_toBottomOf="@+id/text_description" | ||
| 61 | tools:text="Get started" /> | 92 | tools:text="Get started" /> |
| 62 | 93 | ||
| 63 | </LinearLayout> | 94 | </androidx.constraintlayout.widget.ConstraintLayout> |
| 64 | 95 | ||
| 65 | </LinearLayout> | 96 | </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 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <androidx.constraintlayout.widget.ConstraintLayout | 2 | <RelativeLayout |
| 3 | xmlns:android="http://schemas.android.com/apk/res/android" | 3 | xmlns:android="http://schemas.android.com/apk/res/android" |
| 4 | xmlns:app="http://schemas.android.com/apk/res-auto" | 4 | xmlns:app="http://schemas.android.com/apk/res-auto" |
| 5 | android:id="@+id/setup_root" | 5 | android:id="@+id/setup_root" |
| @@ -8,35 +8,39 @@ | |||
| 8 | 8 | ||
| 9 | <androidx.viewpager2.widget.ViewPager2 | 9 | <androidx.viewpager2.widget.ViewPager2 |
| 10 | android:id="@+id/viewPager2" | 10 | android:id="@+id/viewPager2" |
| 11 | android:layout_width="0dp" | 11 | android:layout_width="match_parent" |
| 12 | android:layout_height="0dp" | ||
| 13 | android:clipToPadding="false" | ||
| 14 | android:layout_marginBottom="16dp" | ||
| 15 | app:layout_constraintBottom_toTopOf="@+id/button_next" | ||
| 16 | app:layout_constraintEnd_toEndOf="parent" | ||
| 17 | app:layout_constraintStart_toStartOf="parent" | ||
| 18 | app:layout_constraintTop_toTopOf="parent" /> | ||
| 19 | |||
| 20 | <com.google.android.material.button.MaterialButton | ||
| 21 | style="@style/Widget.Material3.Button.TextButton" | ||
| 22 | android:id="@+id/button_next" | ||
| 23 | android:layout_width="wrap_content" | ||
| 24 | android:layout_height="wrap_content" | 12 | android:layout_height="wrap_content" |
| 25 | android:layout_margin="12dp" | 13 | android:layout_above="@+id/constraint_buttons" |
| 26 | android:text="@string/next" | 14 | android:layout_alignParentTop="true" |
| 27 | android:visibility="invisible" | 15 | android:clipToPadding="false" /> |
| 28 | app:layout_constraintBottom_toBottomOf="parent" | ||
| 29 | app:layout_constraintEnd_toEndOf="parent" /> | ||
| 30 | 16 | ||
| 31 | <com.google.android.material.button.MaterialButton | 17 | <androidx.constraintlayout.widget.ConstraintLayout |
| 32 | style="@style/Widget.Material3.Button.TextButton" | 18 | android:id="@+id/constraint_buttons" |
| 33 | android:id="@+id/button_back" | 19 | android:layout_width="match_parent" |
| 34 | android:layout_width="wrap_content" | ||
| 35 | android:layout_height="wrap_content" | 20 | android:layout_height="wrap_content" |
| 36 | android:layout_margin="12dp" | 21 | android:layout_margin="8dp" |
| 37 | android:text="@string/back" | 22 | android:layout_alignParentBottom="true"> |
| 38 | android:visibility="invisible" | 23 | |
| 39 | app:layout_constraintBottom_toBottomOf="parent" | 24 | <com.google.android.material.button.MaterialButton |
| 40 | app:layout_constraintStart_toStartOf="parent" /> | 25 | android:id="@+id/button_next" |
| 26 | style="@style/Widget.Material3.Button.TextButton" | ||
| 27 | android:layout_width="wrap_content" | ||
| 28 | android:layout_height="wrap_content" | ||
| 29 | android:text="@string/next" | ||
| 30 | android:visibility="invisible" | ||
| 31 | app:layout_constraintBottom_toBottomOf="parent" | ||
| 32 | app:layout_constraintEnd_toEndOf="parent" /> | ||
| 33 | |||
| 34 | <com.google.android.material.button.MaterialButton | ||
| 35 | android:id="@+id/button_back" | ||
| 36 | style="@style/Widget.Material3.Button.TextButton" | ||
| 37 | android:layout_width="wrap_content" | ||
| 38 | android:layout_height="wrap_content" | ||
| 39 | android:text="@string/back" | ||
| 40 | android:visibility="invisible" | ||
| 41 | app:layout_constraintBottom_toBottomOf="parent" | ||
| 42 | app:layout_constraintStart_toStartOf="parent" /> | ||
| 43 | |||
| 44 | </androidx.constraintlayout.widget.ConstraintLayout> | ||
| 41 | 45 | ||
| 42 | </androidx.constraintlayout.widget.ConstraintLayout> | 46 | </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 @@ | |||
| 21 | app:layout_constraintVertical_chainStyle="spread" | 21 | app:layout_constraintVertical_chainStyle="spread" |
| 22 | app:layout_constraintWidth_max="220dp" | 22 | app:layout_constraintWidth_max="220dp" |
| 23 | app:layout_constraintWidth_min="110dp" | 23 | app:layout_constraintWidth_min="110dp" |
| 24 | app:layout_constraintVertical_weight="3" /> | 24 | app:layout_constraintVertical_weight="3" |
| 25 | tools:src="@drawable/ic_notification" /> | ||
| 25 | 26 | ||
| 26 | <com.google.android.material.textview.MaterialTextView | 27 | <com.google.android.material.textview.MaterialTextView |
| 27 | android:id="@+id/text_title" | 28 | android:id="@+id/text_title" |
| 28 | style="@style/TextAppearance.Material3.DisplayMedium" | 29 | style="@style/TextAppearance.Material3.DisplaySmall" |
| 29 | android:layout_width="0dp" | 30 | android:layout_width="0dp" |
| 30 | android:layout_height="0dp" | 31 | android:layout_height="0dp" |
| 31 | android:textAlignment="center" | 32 | android:textAlignment="center" |
| @@ -44,23 +45,42 @@ | |||
| 44 | android:layout_width="0dp" | 45 | android:layout_width="0dp" |
| 45 | android:layout_height="0dp" | 46 | android:layout_height="0dp" |
| 46 | android:textAlignment="center" | 47 | android:textAlignment="center" |
| 47 | android:textSize="26sp" | 48 | android:textSize="20sp" |
| 48 | android:paddingHorizontal="16dp" | 49 | android:paddingHorizontal="16dp" |
| 49 | app:layout_constraintBottom_toTopOf="@+id/button_action" | 50 | app:layout_constraintBottom_toTopOf="@+id/button_action" |
| 50 | app:layout_constraintEnd_toEndOf="parent" | 51 | app:layout_constraintEnd_toEndOf="parent" |
| 51 | app:layout_constraintStart_toStartOf="parent" | 52 | app:layout_constraintStart_toStartOf="parent" |
| 52 | app:layout_constraintTop_toBottomOf="@+id/text_title" | 53 | app:layout_constraintTop_toBottomOf="@+id/text_title" |
| 53 | app:layout_constraintVertical_weight="2" | 54 | app:layout_constraintVertical_weight="2" |
| 54 | app:lineHeight="40sp" | 55 | app:lineHeight="30sp" |
| 55 | tools:text="@string/welcome_description" /> | 56 | tools:text="@string/welcome_description" /> |
| 56 | 57 | ||
| 58 | <com.google.android.material.textview.MaterialTextView | ||
| 59 | android:id="@+id/text_confirmation" | ||
| 60 | style="@style/TextAppearance.Material3.TitleLarge" | ||
| 61 | android:layout_width="wrap_content" | ||
| 62 | android:layout_height="0dp" | ||
| 63 | android:paddingHorizontal="16dp" | ||
| 64 | android:paddingTop="24dp" | ||
| 65 | android:textAlignment="center" | ||
| 66 | android:textSize="30sp" | ||
| 67 | android:visibility="invisible" | ||
| 68 | android:text="@string/step_complete" | ||
| 69 | android:textStyle="bold" | ||
| 70 | app:layout_constraintBottom_toBottomOf="parent" | ||
| 71 | app:layout_constraintEnd_toEndOf="parent" | ||
| 72 | app:layout_constraintStart_toStartOf="parent" | ||
| 73 | app:layout_constraintTop_toBottomOf="@+id/text_description" | ||
| 74 | app:layout_constraintVertical_weight="1" | ||
| 75 | app:lineHeight="30sp" /> | ||
| 76 | |||
| 57 | <com.google.android.material.button.MaterialButton | 77 | <com.google.android.material.button.MaterialButton |
| 58 | android:id="@+id/button_action" | 78 | android:id="@+id/button_action" |
| 59 | android:layout_width="wrap_content" | 79 | android:layout_width="wrap_content" |
| 60 | android:layout_height="56dp" | 80 | android:layout_height="56dp" |
| 61 | android:textSize="20sp" | ||
| 62 | android:layout_marginTop="16dp" | 81 | android:layout_marginTop="16dp" |
| 63 | android:layout_marginBottom="48dp" | 82 | android:layout_marginBottom="48dp" |
| 83 | android:textSize="20sp" | ||
| 64 | app:iconGravity="end" | 84 | app:iconGravity="end" |
| 65 | app:iconSize="24sp" | 85 | app:iconSize="24sp" |
| 66 | app:layout_constraintBottom_toBottomOf="parent" | 86 | 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 @@ | |||
| 29 | <string name="back">Back</string> | 29 | <string name="back">Back</string> |
| 30 | <string name="add_games">Add Games</string> | 30 | <string name="add_games">Add Games</string> |
| 31 | <string name="add_games_description">Select your games folder</string> | 31 | <string name="add_games_description">Select your games folder</string> |
| 32 | <string name="step_complete">Complete!</string> | ||
| 32 | 33 | ||
| 33 | <!-- Home strings --> | 34 | <!-- Home strings --> |
| 34 | <string name="home_games">Games</string> | 35 | <string name="home_games">Games</string> |