Skip to content

Commit

Permalink
Rework search
Browse files Browse the repository at this point in the history
* Call search once for all formats
  • Loading branch information
Grarak authored and PixelyIon committed Jun 17, 2021
1 parent 571e189 commit 4792098
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 79 deletions.
1 change: 0 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ dependencies {
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
implementation 'androidx.fragment:fragment-ktx:1.2.5'
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/java/emu/skyline/EmulationActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
private val binding by lazy { EmuActivityBinding.inflate(layoutInflater) }

/**
* A map of [Vibrator]s that correspond to [inputManager.controllers]
* A map of [Vibrator]s that correspond to [InputManager.controllers]
*/
private var vibrators = HashMap<Int, Vibrator>()

Expand All @@ -54,7 +54,8 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
*/
private lateinit var emulationThread : Thread

private val settings by lazy { Settings(this) }
@Inject
lateinit var settings : Settings

@Inject
lateinit var inputManager : InputManager
Expand Down
8 changes: 6 additions & 2 deletions app/src/main/java/emu/skyline/LogActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import emu.skyline.adapter.GenericAdapter
import emu.skyline.adapter.HeaderViewItem
import emu.skyline.adapter.LogViewItem
Expand All @@ -27,8 +28,10 @@ import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
import java.net.URL
import javax.inject.Inject
import javax.net.ssl.HttpsURLConnection

@AndroidEntryPoint
class LogActivity : AppCompatActivity() {
private val binding by lazy { LogActivityBinding.inflate(layoutInflater) }

Expand All @@ -39,6 +42,9 @@ class LogActivity : AppCompatActivity() {

private val adapter = GenericAdapter()

@Inject
lateinit var settings : Settings

override fun onCreate(savedInstanceState : Bundle?) {
super.onCreate(savedInstanceState)

Expand All @@ -47,8 +53,6 @@ class LogActivity : AppCompatActivity() {
setSupportActionBar(binding.titlebar.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)

val settings = Settings(this)

val compact = settings.logCompact
val logLevel = settings.logLevel.toInt()
val logLevels = resources.getStringArray(R.array.log_level)
Expand Down
35 changes: 24 additions & 11 deletions app/src/main/java/emu/skyline/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import emu.skyline.adapter.AppViewItem
import emu.skyline.adapter.GenericAdapter
import emu.skyline.adapter.HeaderViewItem
Expand All @@ -33,13 +34,17 @@ import emu.skyline.data.DataItem
import emu.skyline.data.HeaderItem
import emu.skyline.databinding.MainActivityBinding
import emu.skyline.loader.LoaderResult
import emu.skyline.loader.RomFormat
import emu.skyline.utils.Settings
import javax.inject.Inject
import kotlin.math.ceil

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val binding by lazy { MainActivityBinding.inflate(layoutInflater) }

private val settings by lazy { Settings(this) }
@Inject
lateinit var settings : Settings

private val adapter = GenericAdapter()

Expand All @@ -52,16 +57,15 @@ class MainActivity : AppCompatActivity() {
private fun AppItem.toViewItem() = AppViewItem(layoutType, this, missingIcon, ::selectStartGame, ::selectShowGameDialog)

override fun onCreate(savedInstanceState : Bundle?) {
AppCompatDelegate.setDefaultNightMode(
when ((settings.appTheme.toInt())) {
0 -> AppCompatDelegate.MODE_NIGHT_NO
1 -> AppCompatDelegate.MODE_NIGHT_YES
2 -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
else -> AppCompatDelegate.MODE_NIGHT_UNSPECIFIED
}
)

// Need to create new instance of settings, dependency injection happens
AppCompatDelegate.setDefaultNightMode(when ((Settings(this).appTheme.toInt())) {
0 -> AppCompatDelegate.MODE_NIGHT_NO
1 -> AppCompatDelegate.MODE_NIGHT_YES
2 -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
else -> AppCompatDelegate.MODE_NIGHT_UNSPECIFIED
})
super.onCreate(savedInstanceState)

setContentView(binding.root)

PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
Expand Down Expand Up @@ -195,7 +199,16 @@ class MainActivity : AppCompatActivity() {
}
is MainState.Loaded -> {
binding.swipeRefreshLayout.isRefreshing = false
populateAdapter(state.items)

val formatOrder = arrayOf(RomFormat.NSP, RomFormat.NRO, RomFormat.NSO, RomFormat.NCA)
val items = mutableListOf<DataItem>()
for (format in formatOrder) {
state.items[format]?.let {
items.add(HeaderItem(format.name))
it.forEach { entry -> items.add(AppItem(entry)) }
}
}
populateAdapter(items)
}
is MainState.Error -> Snackbar.make(findViewById(android.R.id.content), getString(R.string.error) + ": ${state.ex.localizedMessage}", Snackbar.LENGTH_SHORT).show()
}
Expand Down
67 changes: 15 additions & 52 deletions app/src/main/java/emu/skyline/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,29 @@ package emu.skyline
import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import emu.skyline.data.AppItem
import emu.skyline.data.DataItem
import emu.skyline.data.HeaderItem
import emu.skyline.loader.RomFile
import dagger.hilt.android.lifecycle.HiltViewModel
import emu.skyline.loader.AppEntry
import emu.skyline.loader.RomFormat
import emu.skyline.utils.loadSerializedList
import emu.skyline.utils.serialize
import emu.skyline.utils.fromFile
import emu.skyline.utils.toFile
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
import java.io.IOException
import javax.inject.Inject

sealed class MainState {
object Loading : MainState()
class Loaded(val items : List<DataItem>) : MainState()
class Loaded(val items : HashMap<RomFormat, ArrayList<AppEntry>>) : MainState()
class Error(val ex : Exception) : MainState()
}

class MainViewModel : ViewModel() {
@HiltViewModel
class MainViewModel @Inject constructor(private val romProvider : RomProvider) : ViewModel() {
companion object {
private val TAG = MainViewModel::class.java.simpleName
}
Expand All @@ -39,30 +38,6 @@ class MainViewModel : ViewModel() {

var searchBarAnimated = false

/**
* This adds all files in [directory] with [extension] as an entry using [RomFile] to load metadata
*/
private fun addEntries(context : Context, extension : String, romFormat : RomFormat, directory : DocumentFile, romElements : ArrayList<DataItem>, found : Boolean = false) : Boolean {
var foundCurrent = found

directory.listFiles().forEach { file ->
if (file.isDirectory) {
foundCurrent = addEntries(context, extension, romFormat, file, romElements, foundCurrent)
} else {
if (extension.equals(file.name?.substringAfterLast("."), ignoreCase = true)) {
RomFile(context, romFormat, file.uri).let { romFile ->
if (!foundCurrent) romElements.add(HeaderItem(romFormat.name))
romElements.add(AppItem(romFile.appEntry))

foundCurrent = true
}
}
}
}

return foundCurrent
}

/**
* This refreshes the contents of the adapter by either trying to load cached adapter data or searches for them to recreate a list
*
Expand All @@ -77,33 +52,21 @@ class MainViewModel : ViewModel() {
viewModelScope.launch(Dispatchers.IO) {
if (loadFromFile) {
try {
state = MainState.Loaded(loadSerializedList(romsFile))
state = MainState.Loaded(fromFile(romsFile))
return@launch
} catch (e : Exception) {
Log.w(TAG, "Ran into exception while loading: ${e.message}")
}
}

val romElements = romProvider.loadRoms(searchLocation)
try {
val searchDocument = DocumentFile.fromTreeUri(context, searchLocation)!!

val romElements = ArrayList<DataItem>()
addEntries(context, "nsp", RomFormat.NSP, searchDocument, romElements)
addEntries(context, "xci", RomFormat.XCI, searchDocument, romElements)
addEntries(context, "nro", RomFormat.NRO, searchDocument, romElements)
addEntries(context, "nso", RomFormat.NSO, searchDocument, romElements)
addEntries(context, "nca", RomFormat.NCA, searchDocument, romElements)

try {
romElements.serialize(romsFile)
} catch (e : IOException) {
Log.w(TAG, "Ran into exception while saving: ${e.message}")
}

state = MainState.Loaded(romElements)
} catch (e : Exception) {
state = MainState.Error(e)
romElements.toFile(romsFile)
} catch (e : IOException) {
Log.w(TAG, "Ran into exception while saving: ${e.message}")
}

state = MainState.Loaded(romElements)
}
}
}
36 changes: 36 additions & 0 deletions app/src/main/java/emu/skyline/RomProvider.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package emu.skyline

import android.content.Context
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import dagger.hilt.android.qualifiers.ApplicationContext
import emu.skyline.loader.AppEntry
import emu.skyline.loader.RomFile
import emu.skyline.loader.RomFormat
import emu.skyline.loader.RomFormat.*
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class RomProvider @Inject constructor(@ApplicationContext private val context : Context) {
/**
* This adds all files in [directory] with [extension] as an entry using [RomFile] to load metadata
*/
private fun addEntries(fileFormats : Map<String, RomFormat>, directory : DocumentFile, entries : HashMap<RomFormat, ArrayList<AppEntry>>) {
directory.listFiles().forEach { file ->
if (file.isDirectory) {
addEntries(fileFormats, file, entries)
} else {
fileFormats[file.name?.substringAfterLast(".")]?.let { romFormat ->
entries.getOrPut(romFormat, { arrayListOf() }).add(RomFile(context, romFormat, file.uri).appEntry)
}
}
}
}

fun loadRoms(searchLocation : Uri) = DocumentFile.fromTreeUri(context, searchLocation)!!.let { documentFile ->
val entries = hashMapOf<RomFormat, ArrayList<AppEntry>>()
addEntries(mapOf("nro" to NRO, "nso" to NSO, "nca" to NCA, "nsp" to NSP, "xci" to XCI), documentFile, entries)
entries
}
}
3 changes: 2 additions & 1 deletion app/src/main/java/emu/skyline/input/ControllerActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class ControllerActivity : AppCompatActivity() {
*/
val axisMap = mutableMapOf<AxisId, ControllerStickViewItem>()

private val settings by lazy { Settings(this) }
@Inject
lateinit var settings : Settings

@Inject
lateinit var inputManager : InputManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,22 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.floatingactionbutton.FloatingActionButton
import dagger.hilt.android.AndroidEntryPoint
import emu.skyline.R
import emu.skyline.databinding.OnScreenEditActivityBinding
import emu.skyline.utils.Settings
import javax.inject.Inject

@AndroidEntryPoint
class OnScreenEditActivity : AppCompatActivity() {
private val binding by lazy { OnScreenEditActivityBinding.inflate(layoutInflater) }

private var fullEditVisible = true
private var editMode = false

@Inject
lateinit var settings : Settings

private val closeAction : () -> Unit = {
if (editMode) {
toggleFabVisibility(true)
Expand Down Expand Up @@ -85,7 +91,7 @@ class OnScreenEditActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState : Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.onScreenControllerView.recenterSticks = Settings(this).onScreenControlRecenterSticks
binding.onScreenControllerView.recenterSticks = settings.onScreenControlRecenterSticks

actions.forEach { pair ->
binding.fabParent.addView(LayoutInflater.from(this).inflate(R.layout.on_screen_edit_mini_fab, binding.fabParent, false).apply {
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/java/emu/skyline/preference/DocumentActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceManager
import dagger.hilt.android.AndroidEntryPoint
import emu.skyline.utils.Settings
import javax.inject.Inject

/**
* This activity is used to launch a document picker and saves the result to preferences
*/
@AndroidEntryPoint
abstract class DocumentActivity : AppCompatActivity() {
companion object {
const val KEY_NAME = "key_name"
Expand All @@ -24,6 +27,9 @@ abstract class DocumentActivity : AppCompatActivity() {

protected abstract val actionIntent : Intent

@Inject
lateinit var settings : Settings

/**
* This launches the [Intent.ACTION_OPEN_DOCUMENT_TREE] intent on creation
*/
Expand All @@ -46,7 +52,7 @@ abstract class DocumentActivity : AppCompatActivity() {

contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)

Settings(this).refreshRequired = true
settings.refreshRequired = true
PreferenceManager.getDefaultSharedPreferences(this).edit()
.putString(keyName, uri.toString())
.apply()
Expand Down
10 changes: 3 additions & 7 deletions app/src/main/java/emu/skyline/utils/SerializationHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,9 @@ import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.io.Serializable

fun <T : Serializable> ArrayList<T>.serialize(file : File) {
ObjectOutputStream(file.outputStream()).use {
it.writeObject(this)
}
fun <T : Serializable> T.toFile(file : File) {
ObjectOutputStream(file.outputStream()).use { it.writeObject(this) }
}

@Suppress("UNCHECKED_CAST")
fun <T : Serializable> loadSerializedList(file : File) = ObjectInputStream(file.inputStream()).use {
it.readObject()
} as ArrayList<T>
fun <T : Serializable> fromFile(file : File) = ObjectInputStream(file.inputStream()).use { it.readObject() } as T
6 changes: 5 additions & 1 deletion app/src/main/java/emu/skyline/utils/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
package emu.skyline.utils

import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import javax.inject.Singleton

class Settings(context : Context) {
@Singleton
class Settings @Inject constructor(@ApplicationContext private val context : Context) {
var layoutType by sharedPreferences(context, "1")

var searchLocation by sharedPreferences(context, "")
Expand Down

0 comments on commit 4792098

Please sign in to comment.