mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-25 06:46:54 +01:00
WIP
This commit is contained in:
parent
8360cdf82e
commit
b443287007
@ -2,6 +2,7 @@ plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-kapt'
|
||||
id 'kotlinx-serialization'
|
||||
id 'dagger.hilt.android.plugin'
|
||||
}
|
||||
|
||||
@ -92,6 +93,7 @@ dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.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 'androidx.documentfile:documentfile:1.0.1'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
@ -104,9 +106,12 @@ dependencies {
|
||||
|
||||
/* JetBrains */
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
|
||||
|
||||
/* Other Java */
|
||||
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 {
|
||||
|
28
app/proguard-rules.pro
vendored
28
app/proguard-rules.pro
vendored
@ -4,3 +4,31 @@
|
||||
|
||||
# Retain all classes within Skyline for traces + JNI access + Serializable classes
|
||||
-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
|
||||
|
@ -5,23 +5,32 @@
|
||||
|
||||
package emu.skyline
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.graphics.drawable.Icon
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.recyclerview.widget.*
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
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.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
|
||||
@ -43,6 +52,12 @@ class AppDialog : BottomSheetDialogFragment() {
|
||||
|
||||
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 }
|
||||
|
||||
/**
|
||||
@ -56,9 +71,6 @@ class AppDialog : BottomSheetDialogFragment() {
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
val behavior = BottomSheetBehavior.from(requireView().parent as View)
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
|
||||
dialog?.setOnKeyListener { _, keyCode, event ->
|
||||
if (keyCode == KeyEvent.KEYCODE_BUTTON_B && event.action == KeyEvent.ACTION_UP) {
|
||||
dialog?.onBackPressed()
|
||||
@ -71,33 +83,121 @@ class AppDialog : BottomSheetDialogFragment() {
|
||||
override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val missingIcon = ContextCompat.getDrawable(requireActivity(), 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(requireContext())
|
||||
|
||||
binding.gamePlay.isEnabled = item.loaderResult == LoaderResult.Success
|
||||
binding.gamePlay.setOnClickListener {
|
||||
startActivity(Intent(activity, EmulationActivity::class.java).apply { data = item.uri })
|
||||
baseAdapter.apply {
|
||||
addAdapter(gameInfoAdapter)
|
||||
addAdapter(updatesAdapter)
|
||||
addAdapter(dlcsAdapter)
|
||||
addAdapter(tlmdAdapter)
|
||||
}
|
||||
|
||||
val shortcutManager = requireActivity().getSystemService(ShortcutManager::class.java)
|
||||
binding.gamePin.isEnabled = shortcutManager.isRequestPinShortcutSupported
|
||||
val retrofit = Retrofit.Builder()
|
||||
.baseUrl("https://raw.githubusercontent.com/skyline-emu/title-meta/")
|
||||
.addConverterFactory(Json.asConverterFactory(MediaType.get("application/json")))
|
||||
.build()
|
||||
|
||||
binding.gamePin.setOnClickListener {
|
||||
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 service : TitleMetaService = retrofit.create(TitleMetaService::class.java)
|
||||
|
||||
val intent = Intent(context, EmulationActivity::class.java)
|
||||
intent.data = item.uri
|
||||
intent.action = Intent.ACTION_VIEW
|
||||
service.getData(item.title).enqueue(object : Callback<TitleMetaData> {
|
||||
override fun onResponse(call : Call<TitleMetaData>, response : Response<TitleMetaData>) {
|
||||
//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)
|
||||
}
|
||||
|
@ -23,12 +23,13 @@ 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 : Int?) : GenericListItem<AppDialogGameInfoBinding>() {
|
||||
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) {
|
||||
@ -42,7 +43,7 @@ class GameInfoViewItem(private val context : Context, private val item : AppItem
|
||||
binding.gameSubtitle.isSelected = true
|
||||
|
||||
binding.flex.visibility = if (rating == null && testedVersion == null) View.INVISIBLE else View.VISIBLE
|
||||
binding.ratingBar.rating = (rating ?: 0).toFloat()
|
||||
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
|
||||
|
47
app/src/main/java/emu/skyline/network/TitleMetaData.kt
Normal file
47
app/src/main/java/emu/skyline/network/TitleMetaData.kt
Normal 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,
|
||||
)
|
15
app/src/main/java/emu/skyline/network/TitleMetaService.kt
Normal file
15
app/src/main/java/emu/skyline/network/TitleMetaService.kt
Normal 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>
|
||||
}
|
@ -1,82 +1,10 @@
|
||||
<?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:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:nextFocusRight="@id/game_play"
|
||||
android:padding="16dp">
|
||||
|
||||
<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:shapeAppearance="?attr/shapeAppearanceSmallComponent"
|
||||
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:id="@+id/content"
|
||||
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>
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:paddingHorizontal="16dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||
|
142
app/src/main/res/layout/app_dialog_dummy.xml
Normal file
142
app/src/main/res/layout/app_dialog_dummy.xml
Normal 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>
|
@ -5,7 +5,7 @@
|
||||
<dimen name="corner_radius_large">12dp</dimen>
|
||||
|
||||
<!-- Main - AppDialog -->
|
||||
<dimen name="section_spacing">10dp</dimen>
|
||||
<dimen name="section_spacing">6dp</dimen>
|
||||
<dimen name="section_title_padding">6dp</dimen>
|
||||
<dimen name="section_item_card_padding">12dp</dimen>
|
||||
</resources>
|
||||
|
@ -15,6 +15,7 @@ buildscript {
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.1.0-beta02'
|
||||
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"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
Loading…
Reference in New Issue
Block a user