diff --git a/app/src/main/java/emu/skyline/MainActivity.kt b/app/src/main/java/emu/skyline/MainActivity.kt index 8f0e4846..cb91c40f 100644 --- a/app/src/main/java/emu/skyline/MainActivity.kt +++ b/app/src/main/java/emu/skyline/MainActivity.kt @@ -282,7 +282,7 @@ class MainActivity : AppCompatActivity() { } private fun loadRoms(loadFromFile : Boolean) { - viewModel.loadRoms(this, loadFromFile, Uri.parse(settings.searchLocation)) + viewModel.loadRoms(loadFromFile, Uri.parse(settings.searchLocation)) settings.refreshRequired = false } diff --git a/app/src/main/java/emu/skyline/MainViewModel.kt b/app/src/main/java/emu/skyline/MainViewModel.kt index 3652ee2f..2963dc5d 100644 --- a/app/src/main/java/emu/skyline/MainViewModel.kt +++ b/app/src/main/java/emu/skyline/MainViewModel.kt @@ -1,13 +1,12 @@ package emu.skyline +import android.app.Application import android.content.Context import android.net.Uri import android.util.Log -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import androidx.lifecycle.* import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext import emu.skyline.loader.AppEntry import emu.skyline.loader.RomFormat import emu.skyline.utils.fromFile @@ -26,7 +25,7 @@ sealed class MainState { } @HiltViewModel -class MainViewModel @Inject constructor(private val romProvider : RomProvider) : ViewModel() { +class MainViewModel @Inject constructor(@ApplicationContext context : Context, private val romProvider : RomProvider) : AndroidViewModel(context as Application) { companion object { private val TAG = MainViewModel::class.java.simpleName } @@ -44,11 +43,11 @@ class MainViewModel @Inject constructor(private val romProvider : RomProvider) : * * @param loadFromFile If this is false then trying to load cached adapter data is skipped entirely */ - fun loadRoms(context : Context, loadFromFile : Boolean, searchLocation : Uri) { + fun loadRoms(loadFromFile : Boolean, searchLocation : Uri) { if (state == MainState.Loading) return state = MainState.Loading - val romsFile = File(context.filesDir.canonicalPath + "/roms.bin") + val romsFile = File(getApplication().filesDir.canonicalPath + "/roms.bin") viewModelScope.launch(Dispatchers.IO) { if (loadFromFile && romsFile.exists()) { diff --git a/app/src/main/java/emu/skyline/adapter/controller/ControllerHeaderItem.kt b/app/src/main/java/emu/skyline/adapter/controller/ControllerHeaderItem.kt new file mode 100644 index 00000000..f8572642 --- /dev/null +++ b/app/src/main/java/emu/skyline/adapter/controller/ControllerHeaderItem.kt @@ -0,0 +1,24 @@ +package emu.skyline.adapter.controller + +import android.view.ViewGroup +import emu.skyline.adapter.GenericListItem +import emu.skyline.adapter.GenericViewHolder +import emu.skyline.adapter.ViewBindingFactory +import emu.skyline.adapter.inflater +import emu.skyline.databinding.ControllerHeaderBinding + +object ControllerHeaderBindingFactory : ViewBindingFactory { + override fun createBinding(parent : ViewGroup) = ControllerHeaderBinding.inflate(parent.inflater(), parent, false) +} + +class ControllerHeaderItem(private val text : String) : GenericListItem() { + override fun getViewBindingFactory() = ControllerHeaderBindingFactory + + override fun bind(holder : GenericViewHolder, position : Int) { + holder.binding.root.text = text + } + + override fun areItemsTheSame(other : GenericListItem) = other is ControllerHeaderItem + + override fun areContentsTheSame(other : GenericListItem) = other is ControllerHeaderItem && text == other.text +} diff --git a/app/src/main/java/emu/skyline/input/ControllerActivity.kt b/app/src/main/java/emu/skyline/input/ControllerActivity.kt index 1f74d8dc..b25dbc12 100644 --- a/app/src/main/java/emu/skyline/input/ControllerActivity.kt +++ b/app/src/main/java/emu/skyline/input/ControllerActivity.kt @@ -16,7 +16,6 @@ import dagger.hilt.android.AndroidEntryPoint import emu.skyline.R import emu.skyline.adapter.GenericAdapter import emu.skyline.adapter.GenericListItem -import emu.skyline.adapter.HeaderViewItem import emu.skyline.adapter.controller.* import emu.skyline.databinding.ControllerActivityBinding import emu.skyline.input.dialog.ButtonDialog @@ -38,9 +37,6 @@ class ControllerActivity : AppCompatActivity() { */ val id by lazy { intent.getIntExtra("index", 0) } - /** - * The adapter used by [controller_list] to hold all the items - */ private val adapter = GenericAdapter() /** @@ -74,7 +70,7 @@ class ControllerActivity : AppCompatActivity() { return if (id == 0) { - items.add(HeaderViewItem(getString(R.string.osc))) + items.add(ControllerHeaderItem(getString(R.string.osc))) val oscSummary = { checked : Boolean -> getString(if (checked) R.string.osc_shown else R.string.osc_not_shown) } items.add(ControllerCheckBoxViewItem(getString(R.string.osc_enable), oscSummary.invoke(settings.onScreenControl), settings.onScreenControl) { item, position -> @@ -98,7 +94,7 @@ class ControllerActivity : AppCompatActivity() { for (item in GeneralType.values()) { if (item.compatibleControllers == null || item.compatibleControllers.contains(controller.type)) { if (!wroteTitle) { - items.add(HeaderViewItem(getString(R.string.general))) + items.add(ControllerHeaderItem(getString(R.string.general))) wroteTitle = true } @@ -110,7 +106,7 @@ class ControllerActivity : AppCompatActivity() { for (stick in controller.type.sticks) { if (!wroteTitle) { - items.add(HeaderViewItem(getString(R.string.sticks))) + items.add(ControllerHeaderItem(getString(R.string.sticks))) wroteTitle = true } @@ -134,7 +130,7 @@ class ControllerActivity : AppCompatActivity() { for (button in controller.type.buttons.filter { it in buttonArray.second }) { if (!wroteTitle) { - items.add(HeaderViewItem(getString(buttonArray.first))) + items.add(ControllerHeaderItem(getString(buttonArray.first))) wroteTitle = true } @@ -149,7 +145,7 @@ class ControllerActivity : AppCompatActivity() { for (button in controller.type.buttons.filterNot { item -> buttonArrays.any { item in it.second } }.plus(ButtonId.Menu)) { if (!wroteTitle) { - items.add(HeaderViewItem(getString(R.string.misc_buttons))) + items.add(ControllerHeaderItem(getString(R.string.misc_buttons))) wroteTitle = true } @@ -209,29 +205,29 @@ class ControllerActivity : AppCompatActivity() { val typeNames = types.map { getString(it.stringRes) }.toTypedArray() MaterialAlertDialogBuilder(this) - .setTitle(item.content) - .setSingleChoiceItems(typeNames, types.indexOf(controller.type)) { dialog, typeIndex -> - val selectedType = types[typeIndex] - if (controller.type != selectedType) { - if (controller is JoyConLeftController) - controller.partnerId?.let { (inputManager.controllers[it] as JoyConRightController).partnerId = null } - else if (controller is JoyConRightController) - controller.partnerId?.let { (inputManager.controllers[it] as JoyConLeftController).partnerId = null } + .setTitle(item.content) + .setSingleChoiceItems(typeNames, types.indexOf(controller.type)) { dialog, typeIndex -> + val selectedType = types[typeIndex] + if (controller.type != selectedType) { + if (controller is JoyConLeftController) + controller.partnerId?.let { (inputManager.controllers[it] as JoyConRightController).partnerId = null } + else if (controller is JoyConRightController) + controller.partnerId?.let { (inputManager.controllers[it] as JoyConLeftController).partnerId = null } - inputManager.controllers[id] = when (selectedType) { - ControllerType.None -> Controller(id, ControllerType.None) - ControllerType.HandheldProController -> HandheldController(id) - ControllerType.ProController -> ProController(id) - ControllerType.JoyConLeft -> JoyConLeftController(id) - ControllerType.JoyConRight -> JoyConRightController(id) - } - - update() + inputManager.controllers[id] = when (selectedType) { + ControllerType.None -> Controller(id, ControllerType.None) + ControllerType.HandheldProController -> HandheldController(id) + ControllerType.ProController -> ProController(id) + ControllerType.JoyConLeft -> JoyConLeftController(id) + ControllerType.JoyConRight -> JoyConRightController(id) } - dialog.dismiss() + update() } - .show() + + dialog.dismiss() + } + .show() Unit } @@ -248,20 +244,20 @@ class ControllerActivity : AppCompatActivity() { } ?: 0 MaterialAlertDialogBuilder(this) - .setTitle(item.content) - .setSingleChoiceItems(rJoyConNames, partnerNameIndex) { dialog, index -> - (inputManager.controllers[controller.partnerId ?: -1] as JoyConRightController?)?.partnerId = null + .setTitle(item.content) + .setSingleChoiceItems(rJoyConNames, partnerNameIndex) { dialog, index -> + (inputManager.controllers[controller.partnerId ?: -1] as JoyConRightController?)?.partnerId = null - controller.partnerId = if (index == 0) null else rJoyCons[index - 1].id + controller.partnerId = if (index == 0) null else rJoyCons[index - 1].id - if (controller.partnerId != null) - (inputManager.controllers[controller.partnerId ?: -1] as JoyConRightController?)?.partnerId = controller.id + if (controller.partnerId != null) + (inputManager.controllers[controller.partnerId ?: -1] as JoyConRightController?)?.partnerId = controller.id - item.update() + item.update() - dialog.dismiss() - } - .show() + dialog.dismiss() + } + .show() } GeneralType.RumbleDevice -> { diff --git a/app/src/main/res/layout/controller_activity.xml b/app/src/main/res/layout/controller_activity.xml index 8963c1a3..551bf600 100644 --- a/app/src/main/res/layout/controller_activity.xml +++ b/app/src/main/res/layout/controller_activity.xml @@ -14,5 +14,6 @@ android:id="@+id/controller_list" android:layout_width="match_parent" android:layout_height="match_parent" + android:clipToPadding="false" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> diff --git a/app/src/main/res/layout/controller_checkbox_item.xml b/app/src/main/res/layout/controller_checkbox_item.xml index 7c637069..12691c82 100644 --- a/app/src/main/res/layout/controller_checkbox_item.xml +++ b/app/src/main/res/layout/controller_checkbox_item.xml @@ -1,42 +1,50 @@ + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:gravity="center_vertical" + android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:orientation="horizontal" + android:paddingStart="72dp" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> + + + android:ellipsize="marquee" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceListItem" + tools:text="Title" /> - - + android:id="@+id/text_subtitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="10" + android:textAppearance="?android:attr/textAppearanceListItemSecondary" + android:textColor="?android:attr/textColorSecondary" + tools:text="Summary" /> + android:id="@+id/checkbox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:clickable="false" + android:gravity="end|center_vertical" + android:paddingStart="16dp" + android:paddingEnd="0dp" /> diff --git a/app/src/main/res/layout/controller_header.xml b/app/src/main/res/layout/controller_header.xml new file mode 100644 index 00000000..48eb13ec --- /dev/null +++ b/app/src/main/res/layout/controller_header.xml @@ -0,0 +1,12 @@ + + diff --git a/app/src/main/res/layout/controller_item.xml b/app/src/main/res/layout/controller_item.xml index 8f5a9765..4bf46556 100644 --- a/app/src/main/res/layout/controller_item.xml +++ b/app/src/main/res/layout/controller_item.xml @@ -1,31 +1,34 @@ - + + + android:ellipsize="marquee" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceListItem" /> - - - + android:id="@+id/text_subtitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="10" + android:textAppearance="?android:attr/textAppearanceListItemSecondary" + android:textColor="?android:attr/textColorSecondary" /> +