Compare commits

...
Sign in to create a new pull request.

12 commits

Author SHA1 Message Date
lynxnb
b443287007 WIP 2022-02-28 21:58:39 +01:00
lynxnb
8360cdf82e Add misc.xml to gitignore 2022-02-28 21:52:01 +01:00
lynxnb
25ddc846bb Introduce new AppDialog base components 2022-02-28 21:52:00 +01:00
lynxnb
67881d2215 Misc improvements to GenericAdapter
- Allow removing one item from the list
- Keep track of one selected position. This is useful for single choice lists using radio buttons
- Max number of displayed entries. An expand button will be displayed at the bottom when going past the limit, and the entries to display when collapsed is configurable
2022-02-23 18:20:08 +01:00
lynxnb
c5797fdff6 Create a unified style for section titles 2022-02-23 16:44:11 +01:00
lynxnb
8d56fa3194 Allow content to be drawn behind the navigation bars 2022-02-23 16:44:11 +01:00
lynxnb
be38c8b7a2 Make BottomSheetDialog go fullscreen when fully expanded 2022-02-23 16:44:11 +01:00
lynxnb
e00db910f1 Add a drag indicator element at the top of LicenceDialog
A new `DragIndicatorView` had been introduced, which draws a drag indicator drawable. Users of this view should add the callback member as a behavior callback for proper hiding of the indicator when the dialog is fully expanded.
2022-02-23 16:44:10 +01:00
lynxnb
bf331abcdc Improve design consistency across the app
Game images, buttons and dialogs now have a consistent corner radius, across all game list layouts.
2022-02-06 17:30:13 +01:00
lynxnb
b22ad8035c Partially revert 'Make all Dialogs use @color/backgroundColor as the background color'
This partially reverts commit 36a1f2a2ec.
2022-02-06 17:30:13 +01:00
lynxnb
74d75505e9 AppListItem misc tweaks
* Restore text marquee on all layouts
* Text size and color tweaks
* List layout image has round corners
* Clean up unneeded attributes
2022-02-06 17:30:12 +01:00
lynxnb
6ee5e7e629 Use NestedScrollView for licence dialogs and minor layout tweaks 2022-02-06 17:30:12 +01:00
57 changed files with 1646 additions and 246 deletions

1
.gitignore vendored
View file

@ -45,6 +45,7 @@ captures/
.idea/dictionaries .idea/dictionaries
.idea/libraries .idea/libraries
.idea/jarRepositories.xml .idea/jarRepositories.xml
.idea/misc.xml
# Android Studio 3 in .gitignore file. # Android Studio 3 in .gitignore file.
.idea/caches .idea/caches
.idea/modules.xml .idea/modules.xml

79
.idea/misc.xml generated
View file

@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="../../../../../layout/custom_preview.xml" value="0.16875" />
<entry key="app/src/main/res/drawable/logo_skyline.xml" value="0.152" />
<entry key="app/src/main/res/layout/app_dialog.xml" value="0.22335526315789472" />
<entry key="app/src/main/res/layout/button_dialog.xml" value="0.33" />
<entry key="app/src/main/res/layout/controller_activity.xml" value="0.22335526315789472" />
<entry key="app/src/main/res/layout/controller_header.xml" value="0.22335526315789472" />
<entry key="app/src/main/res/layout/header_rom_filter.xml" value="0.22335526315789472" />
<entry key="app/src/main/res/layout/license_dialog.xml" value="0.1" />
<entry key="app/src/main/res/layout/main_activity.xml" value="0.2028688524590164" />
<entry key="app/src/main/res/layout/on_screen_edit_activity.xml" value="0.67" />
<entry key="app/src/main/res/layout/on_screen_edit_mini_fab.xml" value="0.22335526315789472" />
<entry key="app/src/main/res/layout/settings_activity.xml" value="0.22302631578947368" />
<entry key="app/src/main/res/menu/toolbar_log.xml" value="0.11019736842105263" />
</map>
</option>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="JavadocGenerationManager">
<option name="OUTPUT_DIRECTORY" value="$PROJECT_DIR$/../LightSwitchEXTRA/JDoc" />
<option name="OPTION_SCOPE" value="private" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
<option name="myDefaultNotNull" value="androidx.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="15">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
<item index="10" class="java.lang.String" itemvalue="android.annotation.Nullable" />
<item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
<item index="12" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" />
<item index="13" class="java.lang.String" itemvalue="io.reactivex.annotations.Nullable" />
<item index="14" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="15">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
<item index="9" class="java.lang.String" itemvalue="android.annotation.NonNull" />
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
<item index="11" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" />
<item index="12" class="java.lang.String" itemvalue="io.reactivex.annotations.NonNull" />
<item index="13" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.NonNull" />
<item index="14" class="java.lang.String" itemvalue="lombok.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View file

@ -2,6 +2,7 @@ plugins {
id 'com.android.application' id 'com.android.application'
id 'kotlin-android' id 'kotlin-android'
id 'kotlin-kapt' id 'kotlin-kapt'
id 'kotlinx-serialization'
id 'dagger.hilt.android.plugin' id 'dagger.hilt.android.plugin'
} }
@ -92,6 +93,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'androidx.preference:preference-ktx:1.1.1' implementation 'androidx.preference:preference-ktx:1.1.1'
implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation 'com.google.android.material:material:1.4.0' implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.documentfile:documentfile:1.0.1' implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
@ -104,9 +106,12 @@ dependencies {
/* JetBrains */ /* JetBrains */
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
/* Other Java */ /* Other Java */
implementation 'info.debatty:java-string-similarity:2.0.0' implementation 'info.debatty:java-string-similarity:2.0.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
} }
kapt { kapt {

View file

@ -4,3 +4,31 @@
# Retain all classes within Skyline for traces + JNI access + Serializable classes # Retain all classes within Skyline for traces + JNI access + Serializable classes
-keep class emu.skyline.** { *; } -keep class emu.skyline.** { *; }
# Kotlinx Serialization rules
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
static <1>$Companion Companion;
}
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <2>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}
# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
public static ** INSTANCE;
}
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault

View file

@ -5,23 +5,32 @@
package emu.skyline package emu.skyline
import android.content.ComponentName import android.graphics.Rect
import android.content.Intent
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.graphics.drawable.Icon
import android.os.Bundle import android.os.Bundle
import android.view.KeyEvent import android.view.KeyEvent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat import androidx.annotation.StringRes
import androidx.core.graphics.drawable.toBitmap import androidx.recyclerview.widget.*
import androidx.viewbinding.ViewBinding
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.snackbar.Snackbar
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import emu.skyline.adapter.GenericAdapter
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.appdialog.*
import emu.skyline.data.AppItem import emu.skyline.data.AppItem
import emu.skyline.databinding.AppDialogBinding import emu.skyline.databinding.AppDialogBinding
import emu.skyline.loader.LoaderResult import emu.skyline.network.TitleMetaData
import emu.skyline.network.TitleMetaService
import kotlinx.serialization.json.Json
import okhttp3.MediaType
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
/** /**
* This dialog is used to show extra game metadata and provide extra options such as pinning the game to the home screen * This dialog is used to show extra game metadata and provide extra options such as pinning the game to the home screen
@ -43,6 +52,12 @@ class AppDialog : BottomSheetDialogFragment() {
private lateinit var binding : AppDialogBinding private lateinit var binding : AppDialogBinding
private val baseAdapter = ConcatAdapter()
private val gameInfoAdapter = GenericAdapter()
private val updatesAdapter = GenericAdapter()
private val dlcsAdapter = GenericAdapter()
private val tlmdAdapter = GenericAdapter()
private val item by lazy { requireArguments().getSerializable("item") as AppItem } private val item by lazy { requireArguments().getSerializable("item") as AppItem }
/** /**
@ -56,9 +71,6 @@ class AppDialog : BottomSheetDialogFragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
val behavior = BottomSheetBehavior.from(requireView().parent as View)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
dialog?.setOnKeyListener { _, keyCode, event -> dialog?.setOnKeyListener { _, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_BUTTON_B && event.action == KeyEvent.ACTION_UP) { if (keyCode == KeyEvent.KEYCODE_BUTTON_B && event.action == KeyEvent.ACTION_UP) {
dialog?.onBackPressed() dialog?.onBackPressed()
@ -70,35 +82,122 @@ class AppDialog : BottomSheetDialogFragment() {
override fun onViewCreated(view : View, savedInstanceState : Bundle?) { override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
view.setBackgroundColor(requireContext().getColor(R.color.backgroundColor))
val missingIcon = ContextCompat.getDrawable(requireActivity(), R.drawable.default_icon)!!.toBitmap(256, 256) baseAdapter.apply {
addAdapter(gameInfoAdapter)
binding.gameIcon.setImageBitmap(item.icon ?: missingIcon) addAdapter(updatesAdapter)
binding.gameTitle.text = item.title addAdapter(dlcsAdapter)
binding.gameSubtitle.text = item.subTitle ?: item.loaderResultString(requireContext()) addAdapter(tlmdAdapter)
binding.gamePlay.isEnabled = item.loaderResult == LoaderResult.Success
binding.gamePlay.setOnClickListener {
startActivity(Intent(activity, EmulationActivity::class.java).apply { data = item.uri })
} }
val shortcutManager = requireActivity().getSystemService(ShortcutManager::class.java) val retrofit = Retrofit.Builder()
binding.gamePin.isEnabled = shortcutManager.isRequestPinShortcutSupported .baseUrl("https://raw.githubusercontent.com/skyline-emu/title-meta/")
.addConverterFactory(Json.asConverterFactory(MediaType.get("application/json")))
.build()
binding.gamePin.setOnClickListener { val service : TitleMetaService = retrofit.create(TitleMetaService::class.java)
val info = ShortcutInfo.Builder(context, item.title)
info.setShortLabel(item.title)
info.setActivity(ComponentName(requireContext(), EmulationActivity::class.java))
info.setIcon(Icon.createWithAdaptiveBitmap(item.icon ?: missingIcon))
val intent = Intent(context, EmulationActivity::class.java) service.getData(item.title).enqueue(object : Callback<TitleMetaData> {
intent.data = item.uri override fun onResponse(call : Call<TitleMetaData>, response : Response<TitleMetaData>) {
intent.action = Intent.ACTION_VIEW //response.body()?.let { populateAdaptersAfterData(it) }
TODO("NOT")
}
info.setIntent(intent) override fun onFailure(call : Call<TitleMetaData>, t : Throwable) {
TODO("Not yet implemented")
}
})
shortcutManager.requestPinShortcut(info.build(), null) populateAdaptersBeforeData()
binding.content.apply {
addItemDecoration(SpacingItemDecoration(resources.getDimensionPixelSize(R.dimen.section_spacing)))
adapter = baseAdapter
} }
} }
private fun populateAdaptersBeforeData() {
populateGameInfoAdapter(null)
//populateUpdatesAdapter()
//populateDlcsAdapter()
}
private fun populateAdaptersAfterData(data : TitleMetaData) {
populateGameInfoAdapter(data)
populateTlmdAdapter(data)
}
private fun populateGameInfoAdapter(data : TitleMetaData?) {
val entries : MutableList<GenericListItem<out ViewBinding>> = ArrayList()
entries.apply {
add(DragIndicatorViewItem(BottomSheetBehavior.from(requireView().parent as View)))
add(GameInfoViewItem(requireActivity(), item, data?.version, data?.rating))
}
gameInfoAdapter.setItems(entries)
}
private fun populateUpdatesAdapter() {
val entries : MutableList<GenericListItem<out ViewBinding>> = ArrayList()
entries.apply {
add(SectionHeaderViewItem(requireContext().getString(R.string.updates)))
add(UpdatesViewItem("TODO base_version"))
}
updatesAdapter.apply {
selectedPosition = 0 + 1
setItems(entries)
}
}
private fun populateDlcsAdapter() {
val entries : MutableList<GenericListItem<out ViewBinding>> = ArrayList()
entries.apply {
add(SectionHeaderViewItem(requireContext().getString(R.string.dlcs)))
}
dlcsAdapter.setItems(entries)
}
private fun populateTlmdAdapter(data : TitleMetaData) {
val entries : MutableList<GenericListItem<out ViewBinding>> = ArrayList()
entries.apply {
data.issues?.let { issues ->
add(SectionHeaderViewItem(requireContext().getString(R.string.issues)) { _, _ ->
Snackbar.make(this@AppDialog.requireView(), data.discussion, Snackbar.LENGTH_SHORT).show()
})
issues.forEach { issue ->
add(IssuesViewItem(issue.title, issue.description))
}
}
data.notes?.let { notes ->
add(SectionHeaderViewItem(requireContext().getString(R.string.notes)))
notes.forEach { note ->
add(NotesViewItem(note))
}
}
data.cheats?.let { cheats ->
add(SectionHeaderViewItem(requireContext().getString(R.string.cheats)))
cheats.forEach { (key, cheat) ->
add(CheatsViewItem(cheat.title, cheat.author, cheat.description, cheat.code, false))
}
}
}
tlmdAdapter.setItems(entries)
}
private inner class SpacingItemDecoration(private val padding : Int) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect : Rect, view : View, parent : RecyclerView, state : RecyclerView.State) {
super.getItemOffsets(outRect, view, parent, state)
outRect.set(0, 0, 0, padding)
}
}
private fun getResString(@StringRes resId : Int) = requireContext().getString(resId)
} }

View file

@ -19,6 +19,7 @@ import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.content.res.use import androidx.core.content.res.use
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.WindowCompat
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.size import androidx.core.view.size
@ -101,6 +102,7 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(binding.root) setContentView(binding.root)
WindowCompat.setDecorFitsSystemWindows(window, false)
PreferenceManager.setDefaultValues(this, R.xml.preferences, false) PreferenceManager.setDefaultValues(this, R.xml.preferences, false)

View file

@ -9,6 +9,7 @@ import android.os.Bundle
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import emu.skyline.databinding.SettingsActivityBinding import emu.skyline.databinding.SettingsActivityBinding
@ -29,6 +30,7 @@ class SettingsActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(binding.root) setContentView(binding.root)
WindowCompat.setDecorFitsSystemWindows(window, false)
setSupportActionBar(binding.titlebar.toolbar) setSupportActionBar(binding.titlebar.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)

View file

@ -87,6 +87,9 @@ class AppViewItem(var layoutType : LayoutType, private val item : AppItem, priva
override fun bind(binding : LayoutBinding<*>, position : Int) { override fun bind(binding : LayoutBinding<*>, position : Int) {
binding.textTitle.text = item.title binding.textTitle.text = item.title
binding.textSubtitle.text = item.subTitle ?: item.loaderResultString(binding.root.context) binding.textSubtitle.text = item.subTitle ?: item.loaderResultString(binding.root.context)
// Make the title text view selected for marquee to work
binding.textTitle.isSelected = true
binding.textSubtitle.isSelected = true
binding.icon.setImageBitmap(item.icon ?: missingIcon) binding.icon.setImageBitmap(item.icon ?: missingIcon)

View file

@ -36,6 +36,7 @@ class GenericAdapter : RecyclerView.Adapter<GenericViewHolder<ViewBinding>>(), F
val currentItems : List<GenericListItem<in ViewBinding>> get() = asyncListDiffer.currentList val currentItems : List<GenericListItem<in ViewBinding>> get() = asyncListDiffer.currentList
var currentSearchTerm = "" var currentSearchTerm = ""
var selectedPosition : Int? = null
private val viewTypesMapping = mutableMapOf<ViewBindingFactory, Int>() private val viewTypesMapping = mutableMapOf<ViewBindingFactory, Int>()
@ -68,6 +69,11 @@ class GenericAdapter : RecyclerView.Adapter<GenericViewHolder<ViewBinding>>(), F
filter.filter(currentSearchTerm) filter.filter(currentSearchTerm)
} }
fun removeItemAt(position : Int) {
allItems.removeAt(position)
filter.filter(currentSearchTerm)
}
fun setOnFilterPublishedListener(listener : OnFilterPublishedListener) { fun setOnFilterPublishedListener(listener : OnFilterPublishedListener) {
onFilterPublishedListener = listener onFilterPublishedListener = listener
} }

View file

@ -0,0 +1,99 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.adapter.appdialog
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.ViewBindingFactory
import emu.skyline.adapter.inflater
import emu.skyline.databinding.AppDialogCheatsItemBinding
object AppDialogCheatsItemBindingFactory : ViewBindingFactory {
override fun createBinding(parent : ViewGroup) = AppDialogCheatsItemBinding.inflate(parent.inflater(), parent, false)
}
class CheatsViewItem(
private val title : String,
private val author : String?,
private val description : String?,
private val code : String,
var isEnabled : Boolean,
private val onClick : ((item : CheatsViewItem, position : Int) -> Unit)? = null
) : GenericListItem<AppDialogCheatsItemBinding>() {
companion object {
const val MAX_LINES = 2
}
private var isExpandable : Boolean? = null
private var isExpanded = false
override fun getViewBindingFactory() = AppDialogCheatsItemBindingFactory
override fun bind(binding : AppDialogCheatsItemBinding, position : Int) {
binding.title.text = title
author?.let {
binding.author.text = author
binding.author.visibility = View.VISIBLE
} ?: run { binding.author.visibility = View.GONE }
description?.let {
binding.description.text = it
binding.description.visibility = View.VISIBLE
} ?: run { binding.description.visibility = View.GONE }
binding.code.text = code
binding.checkbox.isChecked = isEnabled
handleExpand(binding, position)
binding.checkbox.setOnCheckedChangeListener { _, isChecked : Boolean ->
isEnabled = isChecked
onClick?.invoke(this, position)
}
}
private fun handleExpand(binding : AppDialogCheatsItemBinding, position : Int) {
val setupExpandButton = {
if (isExpandable == true) {
binding.expandButton.visibility = View.VISIBLE
binding.root.setOnClickListener {
isExpanded = !isExpanded
adapter?.notifyItemChanged(position)
}
} else {
binding.expandButton.visibility = View.GONE
}
}
isExpandable ?: binding.root.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw() : Boolean {
isExpandable = binding.title.layout.getEllipsisCount(0) > 0 ||
binding.author.layout.getEllipsisCount(0) > 0 ||
binding.description.layout.getEllipsisCount(MAX_LINES - 1) > 0 ||
code.isNotEmpty()
setupExpandButton.invoke()
binding.root.viewTreeObserver.removeOnPreDrawListener(this)
return true
}
})
if (isExpanded) {
binding.expandButton.rotation = 180F
binding.title.isSingleLine = false
binding.author.isSingleLine = false
binding.description.maxLines = Int.MAX_VALUE
binding.code.visibility = View.VISIBLE
} else {
binding.expandButton.rotation = 0F
binding.title.isSingleLine = true
binding.author.isSingleLine = true
binding.description.maxLines = MAX_LINES
binding.code.visibility = View.GONE
}
setupExpandButton.invoke()
}
}

View file

@ -0,0 +1,36 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.adapter.appdialog
import android.view.View
import android.view.ViewGroup
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.ViewBindingFactory
import emu.skyline.adapter.inflater
import emu.skyline.databinding.AppDialogDlcsItemBinding
object AppDialogDlcsItemBindingFactory : ViewBindingFactory {
override fun createBinding(parent : ViewGroup) = AppDialogDlcsItemBinding.inflate(parent.inflater(), parent, false)
}
class DlcsViewItem(
private val title : String,
var isEnabled : Boolean,
private val onClick : ((item : DlcsViewItem, position : Int) -> Unit)? = null
) : GenericListItem<AppDialogDlcsItemBinding>() {
override fun getViewBindingFactory() = AppDialogDlcsItemBindingFactory
override fun bind(binding : AppDialogDlcsItemBinding, position : Int) {
binding.checkbox.text = title
binding.checkbox.isChecked = isEnabled
binding.checkbox.isSelected = true
binding.checkbox.setOnCheckedChangeListener { _ : View, isChecked : Boolean ->
isEnabled = isChecked
onClick?.invoke(this, position)
}
}
}

View file

@ -0,0 +1,26 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.adapter.appdialog
import android.view.View
import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetBehavior
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.ViewBindingFactory
import emu.skyline.adapter.inflater
import emu.skyline.databinding.AppDialogDragIndicatorBinding
object AppDialogDragIndicatorBindingFactory : ViewBindingFactory {
override fun createBinding(parent : ViewGroup) = AppDialogDragIndicatorBinding.inflate(parent.inflater(), parent, false)
}
class DragIndicatorViewItem(private val behavior : BottomSheetBehavior<View>) : GenericListItem<AppDialogDragIndicatorBinding>() {
override fun getViewBindingFactory() = AppDialogDragIndicatorBindingFactory
override fun bind(binding : AppDialogDragIndicatorBinding, position : Int) {
behavior.addBottomSheetCallback(binding.dragIndicator.callback)
}
}

View file

@ -0,0 +1,72 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.adapter.appdialog
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.graphics.drawable.Icon
import android.view.View
import android.view.ViewGroup
import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.toBitmap
import emu.skyline.EmulationActivity
import emu.skyline.R
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.ViewBindingFactory
import emu.skyline.adapter.inflater
import emu.skyline.data.AppItem
import emu.skyline.databinding.AppDialogGameInfoBinding
import emu.skyline.loader.LoaderResult
import emu.skyline.network.TitleRating
object ControllerBindingFactory : ViewBindingFactory {
override fun createBinding(parent : ViewGroup) = AppDialogGameInfoBinding.inflate(parent.inflater(), parent, false)
}
class GameInfoViewItem(private val context : Context, private val item : AppItem, private val testedVersion : String?, private val rating : TitleRating?) : GenericListItem<AppDialogGameInfoBinding>() {
override fun getViewBindingFactory() = ControllerBindingFactory
override fun bind(binding : AppDialogGameInfoBinding, position : Int) {
val missingIcon = context.getDrawable(R.drawable.default_icon)!!.toBitmap(256, 256)
binding.gameIcon.setImageBitmap(item.icon ?: missingIcon)
binding.gameTitle.text = item.title
binding.gameSubtitle.text = item.subTitle ?: item.loaderResultString(context)
// Make the title text view selected for marquee to work
binding.gameTitle.isSelected = true
binding.gameSubtitle.isSelected = true
binding.flex.visibility = if (rating == null && testedVersion == null) View.INVISIBLE else View.VISIBLE
binding.ratingBar.rating = (rating ?: TitleRating.None).ordinal.toFloat()
binding.testedVersion.text = testedVersion?.let { context.getString(R.string.tested_on, it) } ?: context.getString(R.string.not_tested)
binding.gamePlay.isEnabled = item.loaderResult == LoaderResult.Success
binding.gamePlay.setOnClickListener {
context.startActivity(Intent(context, EmulationActivity::class.java).apply { data = item.uri })
}
val shortcutManager = context.getSystemService<ShortcutManager>()!!
binding.gamePin.isEnabled = shortcutManager.isRequestPinShortcutSupported
binding.gamePin.setOnClickListener {
val info = ShortcutInfo.Builder(context, item.title)
info.setShortLabel(item.title)
info.setActivity(ComponentName(context, EmulationActivity::class.java))
info.setIcon(Icon.createWithAdaptiveBitmap(item.icon ?: missingIcon))
val intent = Intent(context, EmulationActivity::class.java)
intent.data = item.uri
intent.action = Intent.ACTION_VIEW
info.setIntent(intent)
shortcutManager.requestPinShortcut(info.build(), null)
}
}
}

View file

@ -0,0 +1,70 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.adapter.appdialog
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.ViewBindingFactory
import emu.skyline.adapter.inflater
import emu.skyline.databinding.AppDialogIssuesItemBinding
object AppDialogIssuesItemBindingFactory : ViewBindingFactory {
override fun createBinding(parent : ViewGroup) = AppDialogIssuesItemBinding.inflate(parent.inflater(), parent, false)
}
class IssuesViewItem(private val title : String, private val description : String?) : GenericListItem<AppDialogIssuesItemBinding>() {
private var isExpandable : Boolean? = null
private var isExpanded = false
override fun getViewBindingFactory() = AppDialogIssuesItemBindingFactory
override fun bind(binding : AppDialogIssuesItemBinding, position : Int) {
binding.title.text = title
description?.let {
binding.description.text = it
binding.description.visibility = View.VISIBLE
} ?: run { binding.description.visibility = View.GONE }
handleExpand(binding, position)
}
private fun handleExpand(binding : AppDialogIssuesItemBinding, position : Int) {
val setupExpandButton = {
if (isExpandable == true) {
binding.expandButton.visibility = View.VISIBLE
binding.root.setOnClickListener {
isExpanded = !isExpanded
adapter?.notifyItemChanged(position)
}
} else {
binding.expandButton.visibility = View.GONE
}
}
isExpandable ?: binding.root.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw() : Boolean {
isExpandable = binding.title.layout.getEllipsisCount(0) > 0 || description?.isNotEmpty() == true
setupExpandButton.invoke()
binding.root.viewTreeObserver.removeOnPreDrawListener(this)
return true
}
})
if (isExpanded) {
binding.expandButton.rotation = 180F
binding.title.isSingleLine = false
binding.description.visibility = View.VISIBLE
} else {
binding.expandButton.rotation = 0F
binding.title.isSingleLine = true
binding.description.visibility = View.GONE
}
setupExpandButton.invoke()
}
}

View file

@ -0,0 +1,58 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.adapter.appdialog
import android.view.ViewGroup
import android.view.ViewTreeObserver
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.ViewBindingFactory
import emu.skyline.adapter.inflater
import emu.skyline.databinding.AppDialogNotesItemBinding
object AppDialogNotesItemBindingFactory : ViewBindingFactory {
override fun createBinding(parent : ViewGroup) = AppDialogNotesItemBinding.inflate(parent.inflater(), parent, false)
}
class NotesViewItem(private val title : String) : GenericListItem<AppDialogNotesItemBinding>() {
companion object {
const val MAX_LINES = 3
}
private var isExpandable : Boolean? = null
private var isExpanded = false
override fun getViewBindingFactory() = AppDialogNotesItemBindingFactory
override fun bind(binding : AppDialogNotesItemBinding, position : Int) {
binding.title.text = title
handleExpand(binding, position)
}
private fun handleExpand(binding : AppDialogNotesItemBinding, position : Int) {
val setupExpandButton = {
if (isExpandable == true) {
binding.root.setOnClickListener {
isExpanded = !isExpanded
adapter?.notifyItemChanged(position)
}
}
}
isExpandable ?: binding.root.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw() : Boolean {
isExpandable = binding.title.layout.getEllipsisCount(MAX_LINES - 1) > 0
setupExpandButton.invoke()
binding.root.viewTreeObserver.removeOnPreDrawListener(this)
return true
}
})
binding.title.maxLines = if (isExpanded) Int.MAX_VALUE else MAX_LINES
setupExpandButton.invoke()
}
}

View file

@ -0,0 +1,85 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.adapter.appdialog
import android.os.Handler
import android.os.Looper
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.ViewBindingFactory
import emu.skyline.adapter.inflater
import emu.skyline.databinding.AppDialogSavesItemBinding
object AppDialogSavesItemBindingFactory : ViewBindingFactory {
override fun createBinding(parent : ViewGroup) = AppDialogSavesItemBinding.inflate(parent.inflater(), parent, false)
}
class SavesViewItem(
private val title : String,
private val author : String,
private val description : String,
private val onClick : ((item : SavesViewItem, position : Int) -> Unit)? = null
) : GenericListItem<AppDialogSavesItemBinding>() {
companion object {
const val MAX_LINES = 2
}
private var isExpandable : Boolean? = null
private var isExpanded = false
private var isActive = false
override fun getViewBindingFactory() = AppDialogSavesItemBindingFactory
override fun bind(binding : AppDialogSavesItemBinding, position : Int) {
binding.title.text = title
binding.author.text = author
binding.description.text = description
binding.progress.isIndeterminate = true // temp
handleExpand(binding, position)
}
private fun handleExpand(binding : AppDialogSavesItemBinding, position : Int) {
val setupExpandButton = {
if (isExpandable == true) {
binding.expandButton.visibility = View.VISIBLE
binding.root.setOnClickListener {
isExpanded = !isExpanded
adapter?.notifyItemChanged(position)
}
} else {
binding.expandButton.visibility = View.GONE
}
}
isExpandable ?: binding.root.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw() : Boolean {
isExpandable = binding.title.layout.getEllipsisCount(0) > 0 ||
binding.author.layout.getEllipsisCount(0) > 0 ||
binding.description.layout.getEllipsisCount(MAX_LINES - 1) > 0
setupExpandButton.invoke()
binding.root.viewTreeObserver.removeOnPreDrawListener(this)
return true
}
})
if (isExpanded) {
binding.expandButton.rotation = 180F
binding.title.isSingleLine = false
binding.author.isSingleLine = false
binding.description.maxLines = Int.MAX_VALUE
} else {
binding.expandButton.rotation = 0F
binding.title.isSingleLine = true
binding.author.isSingleLine = true
binding.description.maxLines = MAX_LINES
}
setupExpandButton.invoke()
}
}

View file

@ -0,0 +1,42 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.adapter.appdialog
import android.view.View
import android.view.ViewGroup
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.ViewBindingFactory
import emu.skyline.adapter.inflater
import emu.skyline.databinding.AppDialogSectionHeaderBinding
object AppDialogSectionHeaderBindingFactory : ViewBindingFactory {
override fun createBinding(parent : ViewGroup) = AppDialogSectionHeaderBinding.inflate(parent.inflater(), parent, false)
}
class SectionHeaderViewItem(
private val title : String,
private val attribute : String? = null,
private val onButtonClick : ((item : SectionHeaderViewItem, position : Int) -> Unit)? = null
) : GenericListItem<AppDialogSectionHeaderBinding>() {
override fun getViewBindingFactory() = AppDialogSectionHeaderBindingFactory
override fun bind(binding : AppDialogSectionHeaderBinding, position : Int) {
binding.title.text = title
if (attribute != null) {
binding.subtitle.text = attribute
binding.subtitle.visibility = View.VISIBLE
} else {
binding.subtitle.visibility = View.GONE
}
if (onButtonClick != null) {
binding.button.setOnClickListener { onButtonClick.invoke(this, position) }
binding.button.visibility = View.VISIBLE
} else {
binding.button.visibility = View.GONE
}
}
}

View file

@ -0,0 +1,38 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.adapter.appdialog
import android.view.View
import android.view.ViewGroup
import emu.skyline.adapter.GenericListItem
import emu.skyline.adapter.ViewBindingFactory
import emu.skyline.adapter.inflater
import emu.skyline.databinding.AppDialogUpdatesItemBinding
object AppDialogUpdatesItemBindingFactory : ViewBindingFactory {
override fun createBinding(parent : ViewGroup) = AppDialogUpdatesItemBinding.inflate(parent.inflater(), parent, false)
}
class UpdatesViewItem(
private val title : String,
private val onClick : ((item : UpdatesViewItem, position : Int) -> Unit)? = null
) : GenericListItem<AppDialogUpdatesItemBinding>() {
override fun getViewBindingFactory() = AppDialogUpdatesItemBindingFactory
override fun bind(binding : AppDialogUpdatesItemBinding, position : Int) {
binding.radioButton.text = title
binding.radioButton.isChecked = adapter?.selectedPosition == position
binding.radioButton.isSelected = true
binding.radioButton.setOnCheckedChangeListener { _ : View, isChecked : Boolean ->
if (isChecked) {
adapter?.selectedPosition = position
onClick?.invoke(this, position)
adapter?.itemCount?.let { adapter?.notifyItemRangeChanged(0, it) }
}
}
}
}

View file

@ -48,7 +48,6 @@ class ButtonDialog @JvmOverloads constructor(private val item : ControllerButton
override fun onViewCreated(view : View, savedInstanceState : Bundle?) { override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
view.setBackgroundColor(requireContext().getColor(R.color.backgroundColor))
if (item != null && context is ControllerActivity) { if (item != null && context is ControllerActivity) {
val context = requireContext() as ControllerActivity val context = requireContext() as ControllerActivity

View file

@ -47,7 +47,6 @@ class RumbleDialog @JvmOverloads constructor(val item : ControllerGeneralViewIte
override fun onViewCreated(view : View, savedInstanceState : Bundle?) { override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
view.setBackgroundColor(requireContext().getColor(R.color.backgroundColor))
if (item != null && context is ControllerActivity) { if (item != null && context is ControllerActivity) {
val context = requireContext() as ControllerActivity val context = requireContext() as ControllerActivity

View file

@ -225,7 +225,6 @@ class StickDialog @JvmOverloads constructor(val item : ControllerStickViewItem?
override fun onViewCreated(view : View, savedInstanceState : Bundle?) { override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
view.setBackgroundColor(requireContext().getColor(R.color.backgroundColor))
if (item != null && context is ControllerActivity) { if (item != null && context is ControllerActivity) {
val context = requireContext() as ControllerActivity val context = requireContext() as ControllerActivity

View file

@ -0,0 +1,47 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.network
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class TitleMetaData(
val name : String,
val id : String,
val version : String,
val rating : TitleRating,
val discussion : String,
val issues : List<Issue>? = null,
val notes : List<String>? = null,
val cheats : Map<String, Cheat>? = null,
)
@Serializable
enum class TitleRating {
None,
@SerialName("crash") Crash,
@SerialName("intro") Intro,
@SerialName("major-bugs") MajorBugs,
@SerialName("minor-bugs") MinorBugs,
@SerialName("perfect") Perfect,
}
@Serializable
data class Issue(
val title : String,
val description : String? = null,
val url : String,
//val workarounds : List<List<String>>, // TODO
)
@Serializable
data class Cheat(
val title : String,
val description : String? = null,
val author : String? = null,
val code : String,
)

View file

@ -0,0 +1,15 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.network
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Path
interface TitleMetaService {
@GET("main/{id}/title.json")
fun getData(@Path("id") titleId : String) : Call<TitleMetaData>
}

View file

@ -8,8 +8,8 @@ package emu.skyline.preference
import android.graphics.Rect import android.graphics.Rect
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.*
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import emu.skyline.R
import emu.skyline.databinding.LicenseDialogBinding import emu.skyline.databinding.LicenseDialogBinding
/** /**
@ -33,9 +33,15 @@ class LicenseDialog : BottomSheetDialogFragment() {
}.root }.root
} }
override fun onStart() {
super.onStart()
val behavior = BottomSheetBehavior.from(requireView().parent as View)
behavior.addBottomSheetCallback(binding.dragIndicator.callback)
}
override fun onViewCreated(view : View, savedInstanceState : Bundle?) { override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
view.setBackgroundColor(requireContext().getColor(R.color.backgroundColor))
binding.libraryTitle.text = requireArguments().getString(LicensePreference.LIBRARY_TITLE_ARG) binding.libraryTitle.text = requireArguments().getString(LicensePreference.LIBRARY_TITLE_ARG)
binding.libraryUrl.text = requireArguments().getString(LicensePreference.LIBRARY_URL_ARG) binding.libraryUrl.text = requireArguments().getString(LicensePreference.LIBRARY_URL_ARG)

View file

@ -0,0 +1,40 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.views
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import androidx.transition.TransitionManager
import com.google.android.material.bottomsheet.BottomSheetBehavior
import emu.skyline.R
class DragIndicatorView : androidx.appcompat.widget.AppCompatImageView {
val callback = DragIndicatorCallback()
init {
setImageResource(R.drawable.drag_indicator)
}
constructor(context : Context) : super(context)
constructor(context : Context, attrs : AttributeSet?) : super(context, attrs)
constructor(context : Context, attrs : AttributeSet?, defStyleAttr : Int) : super(context, attrs, defStyleAttr)
inner class DragIndicatorCallback : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet : View, newState : Int) {
// Enables animation between visibility states
TransitionManager.beginDelayedTransition(parent as ViewGroup)
visibility = if (newState == BottomSheetBehavior.STATE_EXPANDED && bottomSheet.top == 0)
View.INVISIBLE
else
View.VISIBLE
}
override fun onSlide(bottomSheet : View, slideOffset : Float) {}
}
}

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="@color/onBackgroundLight" />
<corners android:radius="@dimen/corner_radius" />
</shape>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="5dp"
android:height="5dp" />
<solid android:color="@android:color/tertiary_text_light" />
</shape>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="48dp"
android:height="4dp" />
<solid android:color="@color/onBackgroundLight" />
<corners android:radius="4dp" />
</shape>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M16.59,8.59L12,13.17 7.41,8.59 6,10l6,6 6,-6z" />
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M18,15v3H6v-3H4v3c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-3H18zM17,11l-1.41,-1.41L13,12.17V4h-2v8.17L8.41,9.59L7,11l5,5L17,11z" />
</vector>

View file

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp" android:width="24dp"
android:height="32dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:fillColor="?attr/colorOnSecondary" android:fillColor="?attr/colorOnSecondary"
android:pathData="M19,19H5V5h7V3H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2v7zM14,3v2h3.59l-9.83,9.83 1.41,1.41L19,6.41V10h2V3h-7z" /> android:pathData="M19,19H5V5h7V3H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2v7zM14,3v2h3.59l-9.83,9.83 1.41,1.41L19,6.41V10h2V3h-7z" />
</vector> </vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M8,6h8c1.1,0 2,0.9 2,2v8c0,1.1 -0.9,2 -2,2H8c-1.1,0 -2,-0.9 -2,-2V8c0,-1.1 0.9,-2 2,-2z" />
</vector>

View file

@ -1,82 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/content"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:clipChildren="false"
android:nextFocusRight="@id/game_play" android:clipToPadding="false"
android:padding="16dp"> android:paddingHorizontal="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/game_icon"
android:layout_width="150dp"
android:layout_height="150dp"
android:contentDescription="@string/icon"
android:focusable="false"
app:shapeAppearanceOverlay="@style/RoundedAppImage"
tools:src="@drawable/default_icon" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/game_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textSize="18sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:text="The Legend of Zelda: Breath of the Wild" />
<TextView
android:id="@+id/game_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="@android:color/tertiary_text_light"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@id/game_title"
app:layout_constraintStart_toStartOf="@id/game_title"
tools:text="Nintendo" />
<com.google.android.flexbox.FlexboxLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginTop="12dp"
app:layout_constraintStart_toStartOf="@id/game_title"
app:layout_constraintTop_toBottomOf="@id/game_subtitle"
app:flexWrap="wrap">
<Button
android:id="@+id/game_play"
style="@style/Widget.MaterialComponents.Button.OutlinedButton.Icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:focusedByDefault="true"
android:text="@string/play"
android:textColor="?attr/colorAccent"
app:layout_minWidth="146dp"
app:icon="@drawable/ic_play"
app:iconTint="?attr/colorAccent" />
<Button
android:id="@+id/game_pin"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
app:layout_maxWidth="55dp"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:icon="@drawable/ic_add_home"
android:textColor="?attr/colorAccent" />
</com.google.android.flexbox.FlexboxLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View file

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.App.OutlinedCard"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/section_item_card_padding">
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="0dp"
android:minHeight="0dp"
app:layout_constraintBottom_toBottomOf="@id/author"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/title"
tools:checked="true" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:includeFontPadding="false"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
app:layout_constraintEnd_toStartOf="@id/expand_button"
app:layout_constraintStart_toEndOf="@id/checkbox"
app:layout_constraintTop_toTopOf="@id/expand_button"
tools:singleLine="false"
tools:text="Cheat Benchmark Cheat Benchmark Cheat Benchmark Cheat Benchmark" />
<ImageView
android:id="@+id/expand_button"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="8dp"
android:contentDescription="@string/expand_button_title"
android:src="@drawable/expand_indicator"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/title"
app:layout_constraintTop_toTopOf="parent"
app:tint="?android:attr/textColorPrimary"
tools:rotation="180" />
<TextView
android:id="@+id/author"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:includeFontPadding="false"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="@id/title"
app:layout_constraintStart_toStartOf="@id/title"
app:layout_constraintTop_toBottomOf="@id/title"
tools:singleLine="true"
tools:text="by Mark" />
<TextView
android:id="@+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:ellipsize="end"
android:includeFontPadding="false"
app:layout_constraintEnd_toEndOf="@id/expand_button"
app:layout_constraintStart_toStartOf="@id/author"
app:layout_constraintTop_toBottomOf="@id/author"
tools:maxLines="2"
tools:text="A cheat opcode benchmark" />
<TextView
android:id="@+id/code"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/code_block"
android:ellipsize="end"
android:fontFamily="monospace"
android:includeFontPadding="false"
android:padding="8dp"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="@id/expand_button"
app:layout_constraintStart_toStartOf="@id/title"
app:layout_constraintTop_toBottomOf="@id/description"
tools:text="00000000 00000000 00000000\n00000000 00000000 00000000\n00000000 00000000 00000000\n00000000 00000000 00000000\n00000000 00000000 00000000" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.checkbox.MaterialCheckBox xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:minHeight="0dp"
android:singleLine="true"
android:textSize="15sp"
tools:text="Booster Course Pass" />

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<emu.skyline.views.DragIndicatorView
android:id="@+id/drag_indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:focusable="false"
android:paddingTop="10dp" />
</FrameLayout>

View file

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?><!-- This is a dummy layout which serves as a preview of AppDialog -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp">
<include
layout="@layout/app_dialog_drag_indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include
layout="@layout/app_dialog_game_info"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include
android:id="@+id/updates_title"
layout="@layout/app_dialog_section_header" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include layout="@layout/app_dialog_updates_item" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include layout="@layout/app_dialog_updates_item" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include
android:id="@+id/dlcs_title"
layout="@layout/app_dialog_section_header" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include layout="@layout/app_dialog_dlcs_item" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include layout="@layout/app_dialog_dlcs_item" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include
android:id="@+id/issues_title"
layout="@layout/app_dialog_section_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include layout="@layout/app_dialog_issues_item" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include layout="@layout/app_dialog_issues_item" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include
android:id="@+id/notes_title"
layout="@layout/app_dialog_section_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include layout="@layout/app_dialog_notes_item" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include
android:id="@+id/cheats_title"
layout="@layout/app_dialog_section_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include layout="@layout/app_dialog_cheats_item" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include
android:id="@+id/saves_title"
layout="@layout/app_dialog_section_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
<include layout="@layout/app_dialog_saves_item" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/section_spacing" />
</LinearLayout>
</ScrollView>

View file

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/game_icon"
android:layout_width="130dp"
android:layout_height="130dp"
android:contentDescription="@string/icon"
android:focusable="false"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearance="?attr/shapeAppearanceSmallComponent"
tools:src="@drawable/default_icon" />
<TextView
android:id="@+id/game_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/game_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="The Legend of Zelda: Breath of the Wild" />
<TextView
android:id="@+id/game_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
android:textColor="@android:color/tertiary_text_light"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@id/game_title"
app:layout_constraintTop_toBottomOf="@id/game_title"
tools:text="Nintendo" />
<com.google.android.flexbox.FlexboxLayout
android:id="@+id/flex"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:visibility="invisible"
app:alignItems="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/game_title"
app:layout_constraintTop_toBottomOf="@id/game_subtitle"
tools:visibility="visible">
<RatingBar
android:id="@+id/rating_bar"
style="?attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:max="5"
android:min="0"
android:numStars="5"
android:stepSize="1"
tools:rating="3" />
<ImageView
android:id="@+id/dot_separator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:paddingHorizontal="6dp"
android:src="@drawable/dot_separator" />
<TextView
android:id="@+id/tested_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:includeFontPadding="false"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:textColor="@android:color/tertiary_text_light"
tools:text="Tested on 1.0.0" />
</com.google.android.flexbox.FlexboxLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/game_play"
style="@style/Widget.MaterialComponents.Button.Icon"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:focusedByDefault="true"
android:stateListAnimator="@null"
android:text="@string/play"
app:icon="@drawable/ic_play"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/game_pin"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="@id/game_title"
app:layout_constraintTop_toBottomOf="@+id/flex"
app:layout_constraintWidth_max="146dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/game_pin"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="55dp"
android:layout_height="0dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:contentDescription="@string/pin_to_homescreen"
app:icon="@drawable/ic_add_home"
app:iconGravity="textStart"
app:iconPadding="0dp"
app:layout_constraintBottom_toBottomOf="@id/game_play"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/game_play"
app:layout_constraintTop_toTopOf="@id/game_play" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.App.OutlinedCard"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/section_item_card_padding">
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:includeFontPadding="false"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
app:layout_constraintEnd_toStartOf="@id/expand_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/expand_button"
tools:singleLine="true"
tools:text="Chain Chompikins isn't golden" />
<ImageView
android:id="@+id/expand_button"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="8dp"
android:contentDescription="@string/expand_button_title"
android:src="@drawable/expand_indicator"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/title"
app:layout_constraintTop_toTopOf="parent"
app:tint="?android:attr/textColorPrimary"
tools:rotation="180" />
<TextView
android:id="@+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:includeFontPadding="false"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="@id/expand_button"
app:layout_constraintStart_toStartOf="@id/title"
app:layout_constraintTop_toBottomOf="@id/title"
tools:text="Madame Broode's Chain Chompikins from Cascade Kingdom which should appear golden is yellow instead"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.App.OutlinedCard"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/section_item_card_padding">
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:includeFontPadding="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:maxLines="2"
tools:text="Don't change the system time, it'll invalidate your saves." />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

View file

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.App.OutlinedCard"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/section_item_card_padding">
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:max="100"
android:minWidth="0dp"
android:minHeight="0dp"
android:progress="65"
android:visibility="invisible"
app:indicatorSize="32dp"
app:layout_constraintBottom_toBottomOf="@id/author"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/title"
app:trackThickness="3dp" />
<ImageView
android:id="@+id/download_button"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@null"
android:padding="4dp"
android:src="@drawable/ic_download"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@id/progress"
app:layout_constraintEnd_toEndOf="@id/progress"
app:layout_constraintStart_toStartOf="@id/progress"
app:layout_constraintTop_toTopOf="@id/progress" />
<ImageView
android:id="@+id/stop_button"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@null"
android:padding="10dp"
android:src="@drawable/ic_stop"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/progress"
app:layout_constraintEnd_toEndOf="@id/progress"
app:layout_constraintStart_toStartOf="@id/progress"
app:layout_constraintTop_toTopOf="@id/progress" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:includeFontPadding="false"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
app:layout_constraintEnd_toStartOf="@id/expand_button"
app:layout_constraintStart_toEndOf="@id/progress"
app:layout_constraintTop_toTopOf="@id/expand_button"
tools:singleLine="false"
tools:text="Cap Kingdom Cap Kingdom Cap Kingdom Cap Kingdom Cap Kingdom Cap Kingdom" />
<ImageView
android:id="@+id/expand_button"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="8dp"
android:contentDescription="@string/expand_button_title"
android:src="@drawable/expand_indicator"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/title"
app:layout_constraintTop_toTopOf="parent"
app:tint="?android:attr/textColorPrimary"
tools:rotation="180" />
<TextView
android:id="@+id/author"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:fontFamily="sans-serif-medium"
android:includeFontPadding="false"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="@id/title"
app:layout_constraintStart_toStartOf="@id/title"
app:layout_constraintTop_toBottomOf="@id/title"
tools:singleLine="true"
tools:text="by WillFaustCuber" />
<TextView
android:id="@+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:ellipsize="end"
android:includeFontPadding="false"
app:layout_constraintEnd_toEndOf="@id/expand_button"
app:layout_constraintStart_toStartOf="@id/author"
app:layout_constraintTop_toBottomOf="@id/author"
tools:maxLines="2"
tools:text="At the start of the game, right after the intro" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:orientation="horizontal"
android:paddingTop="@dimen/section_title_padding">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/SectionTitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Title" />
<TextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textAppearance="@style/SectionTitle.Attribute"
app:layout_constraintBottom_toBottomOf="@id/title"
app:layout_constraintStart_toEndOf="@id/title"
tools:text="Subtitle" />
<ImageButton
android:id="@+id/button"
style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_width="18dp"
android:layout_height="0dp"
android:background="?android:attr/actionBarItemBackground"
android:contentDescription="@string/open_external"
android:src="@drawable/ic_open"
app:layout_constraintBottom_toBottomOf="@id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/title"
app:tint="?attr/colorAccent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.radiobutton.MaterialRadioButton xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/radio_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:minHeight="0dp"
android:singleLine="true"
android:textSize="15sp"
tools:text="1.3.0" />

View file

@ -15,7 +15,7 @@
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
app:cardCornerRadius="16dp" app:cardCornerRadius="@dimen/corner_radius_large"
app:cardElevation="2dp"> app:cardElevation="2dp">
<ImageView <ImageView
@ -37,7 +37,8 @@
android:marqueeRepeatLimit="marquee_forever" android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true" android:singleLine="true"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp" android:textAppearance="?android:attr/textAppearanceListItem"
android:textSize="14sp"
tools:text="Title" /> tools:text="Title" />
<TextView <TextView
@ -50,6 +51,8 @@
android:ellipsize="marquee" android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever" android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
android:textSize="12sp" android:textSize="12sp"
tools:text="Subtitle" /> tools:text="Subtitle" />
</LinearLayout> </LinearLayout>

View file

@ -9,7 +9,7 @@
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
app:cardCornerRadius="16dp" app:cardCornerRadius="@dimen/corner_radius_large"
app:cardElevation="2dp"> app:cardElevation="2dp">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
@ -33,16 +33,14 @@
android:id="@+id/text_title" android:id="@+id/text_title"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:alpha="242.25" android:paddingHorizontal="8dp"
android:ellipsize="marquee" android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever" android:marqueeRepeatLimit="marquee_forever"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem" android:textAppearance="?android:attr/textAppearanceListItem"
android:textSize="14sp"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textStyle="bold" android:textStyle="bold"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toTopOf="@id/text_subtitle" app:layout_constraintBottom_toTopOf="@id/text_subtitle"
app:layout_constraintEnd_toEndOf="@id/icon" app:layout_constraintEnd_toEndOf="@id/icon"
app:layout_constraintStart_toStartOf="@id/icon" app:layout_constraintStart_toStartOf="@id/icon"
@ -52,16 +50,15 @@
android:id="@+id/text_subtitle" android:id="@+id/text_subtitle"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingHorizontal="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:alpha="242.25"
android:ellipsize="marquee" android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:marqueeRepeatLimit="marquee_forever" android:marqueeRepeatLimit="marquee_forever"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItemSecondary" android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textSize="12sp"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:alpha="0.95"
app:layout_constraintBottom_toBottomOf="@id/icon" app:layout_constraintBottom_toBottomOf="@id/icon"
app:layout_constraintEnd_toEndOf="@id/icon" app:layout_constraintEnd_toEndOf="@id/icon"
app:layout_constraintStart_toStartOf="@id/icon" app:layout_constraintStart_toStartOf="@id/icon"

View file

@ -10,7 +10,7 @@
android:focusable="true" android:focusable="true"
android:padding="16dp"> android:padding="16dp">
<ImageView <com.google.android.material.imageview.ShapeableImageView
android:id="@+id/icon" android:id="@+id/icon"
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
@ -18,14 +18,16 @@
android:focusable="false" android:focusable="false"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:shapeAppearance="?attr/shapeAppearanceSmallComponent"
tools:src="@drawable/default_icon" /> tools:src="@drawable/default_icon" />
<TextView <TextView
android:id="@+id/text_title" android:id="@+id/text_title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="12dp"
android:ellipsize="end" android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem" android:textAppearance="?android:attr/textAppearanceListItem"
app:layout_constrainedWidth="true" app:layout_constrainedWidth="true"
@ -40,14 +42,16 @@
android:id="@+id/text_subtitle" android:id="@+id/text_subtitle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItemSecondary" android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="@android:color/tertiary_text_light" android:textColor="@android:color/tertiary_text_light"
app:layout_constrainedWidth="true" app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0" app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/icon" app:layout_constraintStart_toStartOf="@+id/text_title"
app:layout_constraintTop_toBottomOf="@+id/text_title" app:layout_constraintTop_toBottomOf="@+id/text_title"
tools:text="SubTitle" /> tools:text="SubTitle" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -8,16 +8,21 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingHorizontal="2.5dp" android:paddingHorizontal="2.5dp">
android:paddingTop="10dp">
<emu.skyline.views.DragIndicatorView
android:id="@+id/drag_indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="10dp" />
<TextView <TextView
android:id="@+id/library_title" android:id="@+id/library_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textSize="25sp" android:textSize="32sp"
tools:text="Skyline" /> tools:text="Skyline" />
<TextView <TextView
@ -25,19 +30,21 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autoLink="web" android:autoLink="web"
android:paddingTop="6dp"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
android:textSize="15sp" android:textSize="15sp"
tools:ignore="TouchTargetSizeCheck"
tools:text="https://github.com/skyline-emu/skyline" /> tools:text="https://github.com/skyline-emu/skyline" />
<TextView <TextView
android:id="@+id/library_copyright" android:id="@+id/library_copyright"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="10dp" android:paddingTop="4dp"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline4" android:textAppearance="@style/TextAppearance.MaterialComponents.Headline4"
android:textSize="17sp" android:textSize="15sp"
tools:text="Copyright © 2019-2021\nSkyline Team and Contributors" /> tools:text="Copyright © 2019-2021\nSkyline Team and Contributors" />
<TextView <TextView
@ -45,12 +52,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autoLink="web" android:autoLink="web"
android:paddingTop="10dp"
android:paddingBottom="15dp"
android:paddingHorizontal="15dp"
android:justificationMode="inter_word" android:justificationMode="inter_word"
android:paddingHorizontal="15dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
tools:text="@string/mpl2_license" /> tools:text="@string/mpl2_license" />
</LinearLayout> </LinearLayout>
</ScrollView> </androidx.core.widget.NestedScrollView>

View file

@ -111,7 +111,7 @@
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
app:cardCornerRadius="16dp" app:cardCornerRadius="@dimen/corner_radius_large"
app:cardElevation="2dp" app:cardElevation="2dp"
app:layout_constraintTop_toBottomOf="@id/sub_text" /> app:layout_constraintTop_toBottomOf="@id/sub_text" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/text_title" android:id="@+id/text_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -7,6 +8,6 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:textColor="?android:attr/textColorPrimary" android:textAppearance="@style/SectionTitle"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" /> tools:text="NSP" />

View file

@ -4,4 +4,5 @@
<color name="backgroundColor">#FF121212</color> <color name="backgroundColor">#FF121212</color>
<color name="backgroundColorVariant">#323232</color> <color name="backgroundColorVariant">#323232</color>
<color name="dividerColor">@android:color/white</color> <color name="dividerColor">@android:color/white</color>
<color name="onBackgroundLight">#1AFFFFFF</color>
</resources> </resources>

View file

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<attr name="chipChoiceStyle" format="reference" />
<declare-styleable name="CustomEditTextPreference"> <declare-styleable name="CustomEditTextPreference">
<attr name="limit" format="integer" /> <attr name="limit" format="integer" />
</declare-styleable> </declare-styleable>
<attr name="chipChoiceStyle" format="reference" />
<declare-styleable name="IntegerListPreference"> <declare-styleable name="IntegerListPreference">
<!-- The human-readable array to present as a list. Each entry must have a corresponding <!-- The human-readable array to present as a list. Each entry must have a corresponding
index in entryValues. --> index in entryValues. -->

View file

@ -5,4 +5,5 @@
<color name="backgroundColor">@android:color/white</color> <color name="backgroundColor">@android:color/white</color>
<color name="backgroundColorVariant">#F8F8F8</color> <color name="backgroundColorVariant">#F8F8F8</color>
<color name="dividerColor">@android:color/black</color> <color name="dividerColor">@android:color/black</color>
<color name="onBackgroundLight">#1E000000</color>
</resources> </resources>

View file

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<dimen name="grid_padding">8dp</dimen> <dimen name="grid_padding">8dp</dimen>
<dimen name="corner_radius">6dp</dimen>
<dimen name="corner_radius_large">12dp</dimen>
<!-- Main - AppDialog -->
<dimen name="section_spacing">6dp</dimen>
<dimen name="section_title_padding">6dp</dimen>
<dimen name="section_item_card_padding">12dp</dimen>
</resources> </resources>

View file

@ -21,6 +21,20 @@
<string name="invalid_file">Invalid file</string> <string name="invalid_file">Invalid file</string>
<string name="missing_title_key">Missing title key</string> <string name="missing_title_key">Missing title key</string>
<string name="incomplete_prod_keys">Incomplete production keys</string> <string name="incomplete_prod_keys">Incomplete production keys</string>
<!-- Main - AppDialog -->
<string name="updates">Updates</string>
<string name="dlcs">DLCs</string>
<string name="issues">Issues</string>
<string name="notes">Notes</string>
<string name="cheats">Cheats</string>
<string name="saves">Saves</string>
<string name="no_updates">No updates available</string>
<string name="no_dlcs">No DLCs available</string>
<string name="pin_to_homescreen">Pin to homescreen</string>
<string name="open_external">Open external link</string>
<string name="apply">Apply</string>
<string name="tested_on">Tested on %1$s</string>
<string name="not_tested">Not tested</string>
<!-- Settings - Emulator --> <!-- Settings - Emulator -->
<string name="emulator">Emulator</string> <string name="emulator">Emulator</string>
<string name="search_location">Search Location</string> <string name="search_location">Search Location</string>

View file

@ -1,21 +1,56 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<style name="RoundedAppImage"> <style name="SectionTitle" parent="TextAppearance.MaterialComponents.Headline6">
<item name="cornerFamily">rounded</item> <item name="android:textSize">16sp</item>
<item name="cornerSize">6dp</item>
</style> </style>
<style name="ChipChoice.Material"> <style name="SectionTitle.Attribute" parent="TextAppearance.MaterialComponents.Subtitle2">
<item name="colorPrimary">@color/colorPrimary</item> <item name="android:textColor">@android:color/tertiary_text_light</item>
<item name="colorOnPrimary">@color/colorPrimary</item> </style>
<style name="ShapeAppearance.App.SmallComponent" parent="ShapeAppearance.MaterialComponents.SmallComponent">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">@dimen/corner_radius</item>
</style>
<style name="ShapeAppearance.App.MediumComponent" parent="ShapeAppearance.MaterialComponents.MediumComponent">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">@dimen/corner_radius</item>
</style>
<!-- android:elevation makes BottomSheetDialog background color brighter than it should be -->
<style name="ThemeOverlay.App.BottomSheetDialog" parent="ThemeOverlay.MaterialComponents.BottomSheetDialog">
<item name="bottomSheetStyle">@style/Widget.App.BottomSheet</item>
</style>
<style name="Widget.App.BottomSheet" parent="Widget.MaterialComponents.BottomSheet.Modal">
<item name="android:elevation">@null</item>
<item name="shapeAppearanceOverlay">@style/ShapeAppearance.App.BottomSheetDialog</item>
</style>
<style name="ShapeAppearance.App.BottomSheetDialog" parent="">
<item name="cornerSizeTopLeft">@dimen/corner_radius_large</item>
<item name="cornerSizeTopRight">@dimen/corner_radius_large</item>
</style>
<!-- Workaround for AndroidX Preference as it doesn't use MaterialAlertDialogBuilder -->
<style name="ThemeOverlay.App.MaterialAlertDialog" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="android:dialogCornerRadius">@dimen/corner_radius</item>
</style> </style>
<style name="ChipChoice" parent="Widget.MaterialComponents.Chip.Choice"> <style name="ChipChoice" parent="Widget.MaterialComponents.Chip.Choice">
<item name="android:textAllCaps">true</item> <item name="android:textAllCaps">true</item>
<item name="chipStartPadding">8dp</item> <item name="chipStartPadding">8dp</item>
<item name="chipEndPadding">8dp</item> <item name="chipEndPadding">8dp</item>
<item name="materialThemeOverlay">@style/ChipChoice.Material</item>
<item name="shapeAppearance">@style/ShapeAppearance.MaterialComponents.LargeComponent</item> <item name="shapeAppearance">@style/ShapeAppearance.MaterialComponents.LargeComponent</item>
</style> </style>
<style name="Widget.App.OutlinedCard" parent="Widget.MaterialComponents.CardView">
<item name="cardBackgroundColor">@android:color/transparent</item>
<item name="cardElevation">0dp</item>
<item name="strokeColor" tools:ignore="PrivateResource">@color/mtrl_btn_stroke_color_selector</item>
<item name="strokeWidth">1dp</item>
<item name="android:clickable">true</item>
</style>
</resources> </resources>

View file

@ -3,19 +3,23 @@
<style name="BaseAppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <style name="BaseAppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorOnPrimary">@color/colorPrimary</item> <item name="colorOnPrimary">@android:color/white</item>
<item name="colorSecondary">@color/colorPrimary</item> <item name="colorSecondary">@color/colorPrimary</item>
<item name="colorOnSecondary">@color/colorPrimary</item> <item name="colorOnSecondary">@android:color/white</item>
<item name="android:statusBarColor">@color/backgroundColor</item> <item name="android:statusBarColor">@color/backgroundColor</item>
<item name="android:navigationBarColor">@color/backgroundColor</item> <item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:colorBackground">@color/backgroundColor</item> <item name="android:colorBackground">@color/backgroundColor</item>
<item name="colorBackgroundFloating">@color/backgroundColor</item> <item name="colorBackgroundFloating">@color/backgroundColor</item>
<item name="colorSurface">@color/backgroundColor</item> <item name="colorSurface">@color/backgroundColor</item>
<item name="chipChoiceStyle">@style/ChipChoice</item> <item name="chipChoiceStyle">@style/ChipChoice</item>
<item name="alertDialogTheme">@style/ThemeOverlay.MaterialComponents.MaterialAlertDialog</item> <item name="alertDialogTheme">@style/ThemeOverlay.App.MaterialAlertDialog</item>
<item name="bottomSheetDialogTheme">@style/ThemeOverlay.MaterialComponents.BottomSheetDialog</item> <item name="bottomSheetDialogTheme">@style/ThemeOverlay.App.BottomSheetDialog</item>
<item name="shapeAppearanceSmallComponent">@style/ShapeAppearance.App.SmallComponent</item>
<item name="shapeAppearanceMediumComponent">@style/ShapeAppearance.App.MediumComponent</item>
</style> </style>
<style name="AppTheme" parent="BaseAppTheme"> <style name="AppTheme" parent="BaseAppTheme">

View file

@ -15,6 +15,7 @@ buildscript {
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:7.1.0-beta02' classpath 'com.android.tools.build:gradle:7.1.0-beta02'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong