Compare commits
12 commits
ftx1
...
title-meta
Author | SHA1 | Date | |
---|---|---|---|
|
b443287007 | ||
|
8360cdf82e | ||
|
25ddc846bb | ||
|
67881d2215 | ||
|
c5797fdff6 | ||
|
8d56fa3194 | ||
|
be38c8b7a2 | ||
|
e00db910f1 | ||
|
bf331abcdc | ||
|
b22ad8035c | ||
|
74d75505e9 | ||
|
6ee5e7e629 |
57 changed files with 1646 additions and 246 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -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
79
.idea/misc.xml
generated
|
@ -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>
|
|
|
@ -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 {
|
||||||
|
|
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
|
# 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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
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>
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
40
app/src/main/java/emu/skyline/views/DragIndicatorView.kt
Normal file
40
app/src/main/java/emu/skyline/views/DragIndicatorView.kt
Normal 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) {}
|
||||||
|
}
|
||||||
|
}
|
5
app/src/main/res/drawable/code_block.xml
Normal file
5
app/src/main/res/drawable/code_block.xml
Normal 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>
|
8
app/src/main/res/drawable/dot_separator.xml
Normal file
8
app/src/main/res/drawable/dot_separator.xml
Normal 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>
|
9
app/src/main/res/drawable/drag_indicator.xml
Normal file
9
app/src/main/res/drawable/drag_indicator.xml
Normal 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>
|
10
app/src/main/res/drawable/expand_indicator.xml
Normal file
10
app/src/main/res/drawable/expand_indicator.xml
Normal 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>
|
10
app/src/main/res/drawable/ic_download.xml
Normal file
10
app/src/main/res/drawable/ic_download.xml
Normal 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>
|
|
@ -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>
|
||||||
|
|
10
app/src/main/res/drawable/ic_stop.xml
Normal file
10
app/src/main/res/drawable/ic_stop.xml
Normal 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>
|
|
@ -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>
|
|
||||||
|
|
100
app/src/main/res/layout/app_dialog_cheats_item.xml
Normal file
100
app/src/main/res/layout/app_dialog_cheats_item.xml
Normal 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>
|
12
app/src/main/res/layout/app_dialog_dlcs_item.xml
Normal file
12
app/src/main/res/layout/app_dialog_dlcs_item.xml
Normal 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" />
|
14
app/src/main/res/layout/app_dialog_drag_indicator.xml
Normal file
14
app/src/main/res/layout/app_dialog_drag_indicator.xml
Normal 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>
|
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>
|
127
app/src/main/res/layout/app_dialog_game_info.xml
Normal file
127
app/src/main/res/layout/app_dialog_game_info.xml
Normal 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>
|
54
app/src/main/res/layout/app_dialog_issues_item.xml
Normal file
54
app/src/main/res/layout/app_dialog_issues_item.xml
Normal 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>
|
27
app/src/main/res/layout/app_dialog_notes_item.xml
Normal file
27
app/src/main/res/layout/app_dialog_notes_item.xml
Normal 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>
|
114
app/src/main/res/layout/app_dialog_saves_item.xml
Normal file
114
app/src/main/res/layout/app_dialog_saves_item.xml
Normal 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>
|
43
app/src/main/res/layout/app_dialog_section_header.xml
Normal file
43
app/src/main/res/layout/app_dialog_section_header.xml
Normal 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>
|
12
app/src/main/res/layout/app_dialog_updates_item.xml
Normal file
12
app/src/main/res/layout/app_dialog_updates_item.xml
Normal 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" />
|
|
@ -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>
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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. -->
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue