diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 4dde1733..53be8ac0 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -2,7 +2,7 @@ # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html --keep class emu.skyline.loader.TitleEntry { +-keep class emu.skyline.loader.AppEntry { void writeObject(java.io.ObjectOutputStream); void readObject(java.io.ObjectInputStream); } diff --git a/app/src/main/java/emu/skyline/AppDialog.kt b/app/src/main/java/emu/skyline/AppDialog.kt index 831a02d7..743491f6 100644 --- a/app/src/main/java/emu/skyline/AppDialog.kt +++ b/app/src/main/java/emu/skyline/AppDialog.kt @@ -3,7 +3,7 @@ * Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) */ -package emu.skyline.utility +package emu.skyline import android.content.ComponentName import android.content.Intent @@ -11,14 +11,13 @@ import android.content.pm.ShortcutInfo import android.content.pm.ShortcutManager import android.graphics.drawable.Icon import android.os.Bundle +import android.view.KeyEvent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.graphics.drawable.toBitmap import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import emu.skyline.EmulationActivity -import emu.skyline.R import emu.skyline.adapter.AppItem import kotlinx.android.synthetic.main.app_dialog.* @@ -27,29 +26,38 @@ import kotlinx.android.synthetic.main.app_dialog.* * * @param item This is used to hold the [AppItem] between instances */ -class AppDialog(val item: AppItem? = null) : BottomSheetDialogFragment() { +class AppDialog(val item : AppItem? = null) : BottomSheetDialogFragment() { /** * This inflates the layout of the dialog after initial view creation */ - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView(inflater : LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) : View? { return requireActivity().layoutInflater.inflate(R.layout.app_dialog, container) } /** - * This expands the bottom sheet so that it's fully visible + * This expands the bottom sheet so that it's fully visible and map the B button to back */ override fun onStart() { super.onStart() val behavior = BottomSheetBehavior.from(requireView().parent as View) behavior.state = BottomSheetBehavior.STATE_EXPANDED + + dialog?.setOnKeyListener { _, keyCode, event -> + if (keyCode == KeyEvent.KEYCODE_BUTTON_B && event.action == KeyEvent.ACTION_DOWN) { + dialog?.onBackPressed() + true + } else { + false + } + } } /** * This fills all the dialog with the information from [item] if it is valid and setup all user interaction */ - override fun onActivityCreated(savedInstanceState: Bundle?) { + override fun onActivityCreated(savedInstanceState : Bundle?) { super.onActivityCreated(savedInstanceState) if (item is AppItem) { @@ -59,6 +67,13 @@ class AppDialog(val item: AppItem? = null) : BottomSheetDialogFragment() { game_title.text = item.title game_subtitle.text = item.subTitle ?: getString(R.string.metadata_missing) + game_play.setOnClickListener { + val intent = Intent(activity, EmulationActivity::class.java) + intent.data = item.uri + + startActivity(intent) + } + val shortcutManager = activity?.getSystemService(ShortcutManager::class.java)!! game_pin.isEnabled = shortcutManager.isRequestPinShortcutSupported @@ -76,13 +91,6 @@ class AppDialog(val item: AppItem? = null) : BottomSheetDialogFragment() { shortcutManager.requestPinShortcut(info.build(), null) } - - game_play.setOnClickListener { - val intent = Intent(activity, EmulationActivity::class.java) - intent.data = item.uri - - startActivity(intent) - } } else activity?.supportFragmentManager?.beginTransaction()?.remove(this)?.commit() } diff --git a/app/src/main/java/emu/skyline/EmulationActivity.kt b/app/src/main/java/emu/skyline/EmulationActivity.kt index 1e2e567f..76fd29b7 100644 --- a/app/src/main/java/emu/skyline/EmulationActivity.kt +++ b/app/src/main/java/emu/skyline/EmulationActivity.kt @@ -13,7 +13,7 @@ import android.os.ParcelFileDescriptor import android.util.Log import android.view.Surface import android.view.SurfaceHolder -import android.view.WindowManager +import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.preference.PreferenceManager import emu.skyline.loader.getRomFormat @@ -28,32 +28,32 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback { /** * The file descriptor of the ROM */ - private lateinit var romFd: ParcelFileDescriptor + private lateinit var romFd : ParcelFileDescriptor /** * The file descriptor of the application Preference XML */ - private lateinit var preferenceFd: ParcelFileDescriptor + private lateinit var preferenceFd : ParcelFileDescriptor /** * The file descriptor of the Log file */ - private lateinit var logFd: ParcelFileDescriptor + private lateinit var logFd : ParcelFileDescriptor /** * The surface object used for displaying frames */ - private var surface: Surface? = null + private var surface : Surface? = null /** * A boolean flag denoting if the emulation thread should call finish() or not */ - private var shouldFinish: Boolean = true + private var shouldFinish : Boolean = true /** * The Kotlin thread on which emulation code executes */ - private lateinit var emulationThread: Thread + private lateinit var emulationThread : Thread /** * This is the entry point into the emulation code for libskyline @@ -64,38 +64,38 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback { * @param preferenceFd The file descriptor of the Preference XML * @param logFd The file descriptor of the Log file */ - private external fun executeApplication(romUri: String, romType: Int, romFd: Int, preferenceFd: Int, logFd: Int) + private external fun executeApplication(romUri : String, romType : Int, romFd : Int, preferenceFd : Int, logFd : Int) /** * This sets the halt flag in libskyline to the provided value, if set to true it causes libskyline to halt emulation * * @param halt The value to set halt to */ - private external fun setHalt(halt: Boolean) + private external fun setHalt(halt : Boolean) /** * This sets the surface object in libskyline to the provided value, emulation is halted if set to null * * @param surface The value to set surface to */ - private external fun setSurface(surface: Surface?) + private external fun setSurface(surface : Surface?) /** * This returns the current FPS of the application */ - private external fun getFps(): Int + private external fun getFps() : Int /** * This returns the current frame-time of the application */ - private external fun getFrametime(): Float + private external fun getFrametime() : Float /** * This executes the specified ROM, [preferenceFd] and [logFd] are assumed to be valid beforehand * * @param rom The URI of the ROM to execute */ - private fun executeApplication(rom: Uri) { + private fun executeApplication(rom : Uri) { val romType = getRomFormat(rom, contentResolver).ordinal romFd = contentResolver.openFileDescriptor(rom, "r")!! @@ -116,12 +116,17 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback { * This makes the window fullscreen then sets up [preferenceFd] and [logFd], sets up the performance statistics and finally calls [executeApplication] for executing the application */ @SuppressLint("SetTextI18n") - override fun onCreate(savedInstanceState: Bundle?) { + override fun onCreate(savedInstanceState : Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.emu_activity) - window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN) + window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE + or View.SYSTEM_UI_FLAG_LAYOUT_STABLE + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_FULLSCREEN) val preference = File("${applicationInfo.dataDir}/shared_prefs/${applicationInfo.packageName}_preferences.xml") preferenceFd = ParcelFileDescriptor.open(preference, ParcelFileDescriptor.MODE_READ_WRITE) @@ -134,7 +139,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback { val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) if (sharedPreferences.getBoolean("perf_stats", false)) { - lateinit var perfRunnable: Runnable + lateinit var perfRunnable : Runnable perfRunnable = Runnable { perf_stats.text = "${getFps()} FPS\n${getFrametime()}ms" @@ -150,7 +155,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback { /** * This is used to stop the currently executing ROM and replace it with the one specified in the new intent */ - override fun onNewIntent(intent: Intent?) { + override fun onNewIntent(intent : Intent?) { shouldFinish = false setHalt(true) @@ -184,7 +189,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback { /** * This sets [surface] to [holder].surface and passes it into libskyline */ - override fun surfaceCreated(holder: SurfaceHolder?) { + override fun surfaceCreated(holder : SurfaceHolder?) { Log.d("surfaceCreated", "Holder: ${holder.toString()}") surface = holder!!.surface setSurface(surface) @@ -193,14 +198,14 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback { /** * This is purely used for debugging surface changes */ - override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) { + override fun surfaceChanged(holder : SurfaceHolder?, format : Int, width : Int, height : Int) { Log.d("surfaceChanged", "Holder: ${holder.toString()}, Format: $format, Width: $width, Height: $height") } /** * This sets [surface] to null and passes it into libskyline */ - override fun surfaceDestroyed(holder: SurfaceHolder?) { + override fun surfaceDestroyed(holder : SurfaceHolder?) { Log.d("surfaceDestroyed", "Holder: ${holder.toString()}") surface = null setSurface(surface) diff --git a/app/src/main/java/emu/skyline/LogActivity.kt b/app/src/main/java/emu/skyline/LogActivity.kt index 58673a57..eab05cc5 100644 --- a/app/src/main/java/emu/skyline/LogActivity.kt +++ b/app/src/main/java/emu/skyline/LogActivity.kt @@ -32,17 +32,17 @@ class LogActivity : AppCompatActivity() { /** * The log file is used to read log entries from or to clear all entries */ - private lateinit var logFile: File + private lateinit var logFile : File /** * The adapter used for adding elements from the log to [log_list] */ - private lateinit var adapter: LogAdapter + private lateinit var adapter : LogAdapter /** * This initializes [toolbar] and fills [log_list] with data from the logs */ - override fun onCreate(savedInstanceState: Bundle?) { + override fun onCreate(savedInstanceState : Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.log_activity) @@ -68,12 +68,12 @@ class LogActivity : AppCompatActivity() { logFile.forEachLine { adapter.add(it) } - } catch (e: FileNotFoundException) { + } catch (e : FileNotFoundException) { Log.w("Logger", "IO Error during access of log file: " + e.message) Toast.makeText(applicationContext, getString(R.string.file_missing), Toast.LENGTH_LONG).show() finish() - } catch (e: IOException) { + } catch (e : IOException) { Log.w("Logger", "IO Error during access of log file: " + e.message) Toast.makeText(applicationContext, getString(R.string.error) + ": ${e.localizedMessage}", Toast.LENGTH_LONG).show() } @@ -82,19 +82,19 @@ class LogActivity : AppCompatActivity() { /** * This inflates the layout for the menu [R.menu.toolbar_log] and sets up searching the logs */ - override fun onCreateOptionsMenu(menu: Menu): Boolean { + override fun onCreateOptionsMenu(menu : Menu) : Boolean { menuInflater.inflate(R.menu.toolbar_log, menu) val searchView = menu.findItem(R.id.action_search_log).actionView as SearchView searchView.isSubmitButtonEnabled = false searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String): Boolean { + override fun onQueryTextSubmit(query : String) : Boolean { searchView.isIconified = false return false } - override fun onQueryTextChange(newText: String): Boolean { + override fun onQueryTextChange(newText : String) : Boolean { adapter.filter.filter(newText) return true } @@ -106,12 +106,12 @@ class LogActivity : AppCompatActivity() { /** * This handles menu selection for [R.id.action_clear] and [R.id.action_share_log] */ - override fun onOptionsItemSelected(item: MenuItem): Boolean { + override fun onOptionsItemSelected(item : MenuItem) : Boolean { return when (item.itemId) { R.id.action_clear -> { try { logFile.writeText("") - } catch (e: IOException) { + } catch (e : IOException) { Log.w("Logger", "IO Error while clearing the log file: " + e.message) Toast.makeText(applicationContext, getString(R.string.error) + ": ${e.localizedMessage}", Toast.LENGTH_LONG).show() } @@ -137,7 +137,7 @@ class LogActivity : AppCompatActivity() { Snackbar.make(findViewById(android.R.id.content), getString(R.string.upload_logs), Snackbar.LENGTH_SHORT).show() val shareThread = Thread(Runnable { - var urlConnection: HttpsURLConnection? = null + var urlConnection : HttpsURLConnection? = null try { val url = URL("https://hastebin.com/documents") @@ -166,7 +166,7 @@ class LogActivity : AppCompatActivity() { val sharingIntent = Intent(Intent.ACTION_SEND).setType("text/plain").putExtra(Intent.EXTRA_TEXT, result) startActivity(Intent.createChooser(sharingIntent, "Share log url with:")) - } catch (e: Exception) { + } catch (e : Exception) { runOnUiThread { Snackbar.make(findViewById(android.R.id.content), getString(R.string.error) + ": ${e.localizedMessage}", Snackbar.LENGTH_LONG).show() } e.printStackTrace() } finally { diff --git a/app/src/main/java/emu/skyline/MainActivity.kt b/app/src/main/java/emu/skyline/MainActivity.kt index 628abd63..935f0dce 100644 --- a/app/src/main/java/emu/skyline/MainActivity.kt +++ b/app/src/main/java/emu/skyline/MainActivity.kt @@ -7,6 +7,7 @@ package emu.skyline import android.content.Intent import android.content.SharedPreferences +import android.content.pm.ActivityInfo import android.net.Uri import android.os.Bundle import android.util.Log @@ -29,7 +30,6 @@ import emu.skyline.adapter.GridLayoutSpan import emu.skyline.adapter.LayoutType import emu.skyline.loader.BaseLoader import emu.skyline.loader.NroLoader -import emu.skyline.utility.AppDialog import emu.skyline.utility.RandomAccessDocument import kotlinx.android.synthetic.main.main_activity.* import kotlinx.android.synthetic.main.titlebar.* @@ -42,17 +42,17 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick /** * This is used to get/set shared preferences */ - private lateinit var sharedPreferences: SharedPreferences + private lateinit var sharedPreferences : SharedPreferences /** * The adapter used for adding elements to [app_list] */ - private lateinit var adapter: AppAdapter + private lateinit var adapter : AppAdapter /** * This adds all files in [directory] with [extension] as an entry in [adapter] using [loader] to load metadata */ - private fun addEntries(extension: String, loader: BaseLoader, directory: DocumentFile, found: Boolean = false): Boolean { + private fun addEntries(extension : String, loader : BaseLoader, directory : DocumentFile, found : Boolean = false) : Boolean { var foundCurrent = found directory.listFiles().forEach { file -> @@ -89,19 +89,22 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick * * @param tryLoad If this is false then trying to load cached adapter data is skipped entirely */ - private fun refreshAdapter(tryLoad: Boolean) { + private fun refreshAdapter(tryLoad : Boolean) { if (tryLoad) { try { adapter.load(File("${applicationInfo.dataDir}/roms.bin")) return - } catch (e: Exception) { + } catch (e : Exception) { Log.w("refreshFiles", "Ran into exception while loading: ${e.message}") } } thread(start = true) { val snackbar = Snackbar.make(findViewById(android.R.id.content), getString(R.string.searching_roms), Snackbar.LENGTH_INDEFINITE) - runOnUiThread { snackbar.show() } + runOnUiThread { + snackbar.show() + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED + } try { runOnUiThread { adapter.clear() } @@ -114,13 +117,13 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick try { adapter.save(File("${applicationInfo.dataDir}/roms.bin")) - } catch (e: IOException) { + } catch (e : IOException) { Log.w("refreshFiles", "Ran into exception while saving: ${e.message}") } } sharedPreferences.edit().putBoolean("refresh_required", false).apply() - } catch (e: IllegalArgumentException) { + } catch (e : IllegalArgumentException) { runOnUiThread { sharedPreferences.edit().remove("search_location").apply() @@ -128,20 +131,23 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick finish() startActivity(intent) } - } catch (e: Exception) { + } catch (e : Exception) { runOnUiThread { Snackbar.make(findViewById(android.R.id.content), getString(R.string.error) + ": ${e.localizedMessage}", Snackbar.LENGTH_SHORT).show() } } - runOnUiThread { snackbar.dismiss() } + runOnUiThread { + snackbar.dismiss() + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED + } } } /** * This initializes [toolbar], [open_fab], [log_fab] and [app_list] */ - override fun onCreate(savedInstanceState: Bundle?) { + override fun onCreate(savedInstanceState : Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) @@ -184,6 +190,23 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick } } + app_list.addOnScrollListener(object : RecyclerView.OnScrollListener() { + var y : Int = 0 + + override fun onScrolled(recyclerView : RecyclerView, dx : Int, dy : Int) { + y += dy + + if (!app_list.isInTouchMode) { + if (y == 0) + toolbar_layout.setExpanded(true) + else + toolbar_layout.setExpanded(false) + } + + super.onScrolled(recyclerView, dx, dy) + } + }) + if (sharedPreferences.getString("search_location", "") == "") { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) intent.flags = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION @@ -196,18 +219,18 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick /** * This inflates the layout for the menu [R.menu.toolbar_main] and sets up searching the logs */ - override fun onCreateOptionsMenu(menu: Menu): Boolean { + override fun onCreateOptionsMenu(menu : Menu) : Boolean { menuInflater.inflate(R.menu.toolbar_main, menu) val searchView = menu.findItem(R.id.action_search_main).actionView as SearchView searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String): Boolean { + override fun onQueryTextSubmit(query : String) : Boolean { searchView.clearFocus() return false } - override fun onQueryTextChange(newText: String): Boolean { + override fun onQueryTextChange(newText : String) : Boolean { adapter.filter.filter(newText) return true } @@ -219,7 +242,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick /** * This handles on-click interaction with [R.id.log_fab], [R.id.open_fab], [R.id.app_item_linear] and [R.id.app_item_grid] */ - override fun onClick(view: View) { + override fun onClick(view : View) { when (view.id) { R.id.log_fab -> startActivity(Intent(this, LogActivity::class.java)) @@ -250,7 +273,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick /** * This handles long-click interaction with [R.id.app_item_linear] and [R.id.app_item_grid] */ - override fun onLongClick(view: View?): Boolean { + override fun onLongClick(view : View?) : Boolean { when (view?.id) { R.id.app_item_linear, R.id.app_item_grid -> { val tag = view.tag @@ -269,7 +292,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick /** * This handles menu interaction for [R.id.action_settings] and [R.id.action_refresh] */ - override fun onOptionsItemSelected(item: MenuItem): Boolean { + override fun onOptionsItemSelected(item : MenuItem) : Boolean { return when (item.itemId) { R.id.action_settings -> { startActivityForResult(Intent(this, SettingsActivity::class.java), 3) @@ -288,7 +311,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick /** * This handles receiving activity result from [Intent.ACTION_OPEN_DOCUMENT_TREE], [Intent.ACTION_OPEN_DOCUMENT] and [SettingsActivity] */ - override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { + override fun onActivityResult(requestCode : Int, resultCode : Int, intent : Intent?) { super.onActivityResult(requestCode, resultCode, intent) if (resultCode == RESULT_OK) { @@ -310,7 +333,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClick startActivityForResult(intentGame, resultCode) else startActivity(intentGame) - } catch (e: Exception) { + } catch (e : Exception) { Snackbar.make(findViewById(android.R.id.content), getString(R.string.error) + ": ${e.localizedMessage}", Snackbar.LENGTH_SHORT).show() } } diff --git a/app/src/main/java/emu/skyline/SettingsActivity.kt b/app/src/main/java/emu/skyline/SettingsActivity.kt index 13f01299..ad694d67 100644 --- a/app/src/main/java/emu/skyline/SettingsActivity.kt +++ b/app/src/main/java/emu/skyline/SettingsActivity.kt @@ -15,12 +15,12 @@ class SettingsActivity : AppCompatActivity() { /** * This is the instance of [PreferenceFragment] that is shown inside [R.id.settings] */ - private val preferenceFragment: PreferenceFragment = PreferenceFragment() + private val preferenceFragment : PreferenceFragment = PreferenceFragment() /** * This initializes [toolbar] and [R.id.settings] */ - override fun onCreate(savedInstanceState: Bundle?) { + override fun onCreate(savedInstanceState : Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.settings_activity) @@ -37,7 +37,7 @@ class SettingsActivity : AppCompatActivity() { /** * This is used to refresh the preferences after [emu.skyline.preference.FolderActivity] has returned */ - public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + public override fun onActivityResult(requestCode : Int, resultCode : Int, data : Intent?) { super.onActivityResult(requestCode, resultCode, data) preferenceFragment.refreshPreferences() } @@ -57,7 +57,7 @@ class SettingsActivity : AppCompatActivity() { /** * This constructs the preferences from [R.xml.preferences] */ - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + override fun onCreatePreferences(savedInstanceState : Bundle?, rootKey : String?) { setPreferencesFromResource(R.xml.preferences, rootKey) } } diff --git a/app/src/main/java/emu/skyline/adapter/AppAdapter.kt b/app/src/main/java/emu/skyline/adapter/AppAdapter.kt index dd0dd52a..e5c297b4 100644 --- a/app/src/main/java/emu/skyline/adapter/AppAdapter.kt +++ b/app/src/main/java/emu/skyline/adapter/AppAdapter.kt @@ -28,41 +28,41 @@ import emu.skyline.loader.AppEntry /** * This class is a wrapper around [AppEntry], it is used for passing around game metadata */ -class AppItem(val meta: AppEntry) : BaseItem() { +class AppItem(val meta : AppEntry) : BaseItem() { /** * The icon of the application */ - val icon: Bitmap? + val icon : Bitmap? get() = meta.icon /** * The title of the application */ - val title: String + val title : String get() = meta.name /** * The string used as the sub-title, we currently use the author */ - val subTitle: String? + val subTitle : String? get() = meta.author /** * The URI of the application's image file */ - val uri: Uri + val uri : Uri get() = meta.uri /** * The format of the application ROM as a string */ - private val type: String + private val type : String get() = meta.format.name /** * The name and author is used as the key */ - override fun key(): String? { + override fun key() : String? { return if (meta.author != null) meta.name + " " + meta.author else meta.name } } @@ -78,21 +78,21 @@ enum class LayoutType { /** * This adapter is used to display all found applications using their metadata */ -internal class AppAdapter(val context: Context?, private val layoutType: LayoutType) : HeaderAdapter(), View.OnClickListener { +internal class AppAdapter(val context : Context?, private val layoutType : LayoutType) : HeaderAdapter(), View.OnClickListener { private val missingIcon = context?.resources?.getDrawable(R.drawable.default_icon, context.theme)?.toBitmap(256, 256) private val missingString = context?.getString(R.string.metadata_missing) /** * This adds a header to the view with the contents of [string] */ - fun addHeader(string: String) { + fun addHeader(string : String) { super.addHeader(BaseHeader(string)) } /** * The onClick handler for the supplied [view], used for the icon preview */ - override fun onClick(view: View) { + override fun onClick(view : View) { val position = view.tag as Int if (getItem(position) is AppItem) { @@ -120,7 +120,7 @@ internal class AppAdapter(val context: Context?, private val layoutType: LayoutT * @param title The TextView associated with the title * @param subtitle The TextView associated with the subtitle */ - private class ItemViewHolder(val parent: View, var icon: ImageView, var title: TextView, var subtitle: TextView, var card: View? = null) : RecyclerView.ViewHolder(parent) + private class ItemViewHolder(val parent : View, var icon : ImageView, var title : TextView, var subtitle : TextView, var card : View? = null) : RecyclerView.ViewHolder(parent) /** * The ViewHolder used by headers is used to hold the views associated with an headers @@ -128,14 +128,14 @@ internal class AppAdapter(val context: Context?, private val layoutType: LayoutT * @param parent The parent view that contains all the others * @param header The TextView associated with the header */ - private class HeaderViewHolder(val parent: View, var header: TextView? = null) : RecyclerView.ViewHolder(parent) + private class HeaderViewHolder(val parent : View, var header : TextView? = null) : RecyclerView.ViewHolder(parent) /** * This function creates the view-holder of type [viewType] with the layout parent as [parent] */ - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + override fun onCreateViewHolder(parent : ViewGroup, viewType : Int) : RecyclerView.ViewHolder { val inflater = LayoutInflater.from(context) - var holder: RecyclerView.ViewHolder? = null + var holder : RecyclerView.ViewHolder? = null if (viewType == Item.ordinal) { val view = inflater.inflate(if (layoutType == LayoutType.List) R.layout.app_item_linear else R.layout.app_item_grid, parent, false) @@ -155,6 +155,8 @@ internal class AppAdapter(val context: Context?, private val layoutType: LayoutT if (context is View.OnLongClickListener) holder.card!!.setOnLongClickListener(context as View.OnLongClickListener) + + holder.title.isSelected = true } } else if (viewType == Header.ordinal) { val view = inflater.inflate(R.layout.section_item, parent, false) @@ -169,7 +171,7 @@ internal class AppAdapter(val context: Context?, private val layoutType: LayoutT /** * This function binds the item at [position] to the supplied [viewHolder] */ - override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) { + override fun onBindViewHolder(viewHolder : RecyclerView.ViewHolder, position : Int) { val item = getItem(position) if (item is AppItem) { diff --git a/app/src/main/java/emu/skyline/adapter/HeaderAdapter.kt b/app/src/main/java/emu/skyline/adapter/HeaderAdapter.kt index 98ae93e2..f6265612 100644 --- a/app/src/main/java/emu/skyline/adapter/HeaderAdapter.kt +++ b/app/src/main/java/emu/skyline/adapter/HeaderAdapter.kt @@ -20,7 +20,7 @@ import kotlin.collections.ArrayList /** * An enumeration of the type of elements in this adapter */ -enum class ElementType(val type: Int) { +enum class ElementType(val type : Int) { Header(0x0), Item(0x1) } @@ -28,12 +28,12 @@ enum class ElementType(val type: Int) { /** * This is an abstract class that all adapter element classes inherit from */ -abstract class BaseElement constructor(val elementType: ElementType) : Serializable +abstract class BaseElement constructor(val elementType : ElementType) : Serializable /** * This is an abstract class that all adapter header classes inherit from */ -class BaseHeader constructor(val title: String) : BaseElement(ElementType.Header) +class BaseHeader constructor(val title : String) : BaseElement(ElementType.Header) /** * This is an abstract class that all adapter item classes inherit from @@ -42,7 +42,7 @@ abstract class BaseItem : BaseElement(ElementType.Item) { /** * This function returns a string used for searching */ - abstract fun key(): String? + abstract fun key() : String? } /** @@ -52,12 +52,12 @@ abstract class HeaderAdapter = ArrayList() + var elementArray : ArrayList = ArrayList() /** * This holds the indices of all the visible items in [elementArray] */ - var visibleArray: ArrayList = ArrayList() + var visibleArray : ArrayList = ArrayList() /** * This holds the search term if there is any, to filter any items added during a search @@ -67,7 +67,7 @@ abstract class HeaderAdapter): Array { - val scoredItems: MutableList = ArrayList() + fun extractSorted(term : String, keyArray : ArrayList) : Array { + val scoredItems : MutableList = ArrayList() keyArray.forEachIndexed { index, item -> val similarity = (jw.similarity(term, item) + cos.similarity(term, item)) / 2 @@ -187,7 +187,7 @@ abstract class HeaderAdapter) { @Suppress("UNCHECKED_CAST") visibleArray = results.values as ArrayList @@ -244,11 +244,11 @@ abstract class HeaderAdapter(val adapter: HeaderAdapter, var headerSpan: Int) : GridLayoutManager.SpanSizeLookup() { +class GridLayoutSpan(val adapter : HeaderAdapter, var headerSpan : Int) : GridLayoutManager.SpanSizeLookup() { /** * This returns the size of the span based on the type of the element at [position] */ - override fun getSpanSize(position: Int): Int { + override fun getSpanSize(position : Int) : Int { val item = adapter.getItem(position)!! return if (item.elementType == ElementType.Item) 1 diff --git a/app/src/main/java/emu/skyline/adapter/LogAdapter.kt b/app/src/main/java/emu/skyline/adapter/LogAdapter.kt index 0edd3dc9..6d5d4ebc 100644 --- a/app/src/main/java/emu/skyline/adapter/LogAdapter.kt +++ b/app/src/main/java/emu/skyline/adapter/LogAdapter.kt @@ -20,11 +20,11 @@ import emu.skyline.R /** * This class is used to hold all data about a log entry */ -internal class LogItem(val message: String, val level: String) : BaseItem() { +internal class LogItem(val message : String, val level : String) : BaseItem() { /** * The log message itself is used as the search key */ - override fun key(): String? { + override fun key() : String? { return message } } @@ -32,13 +32,13 @@ internal class LogItem(val message: String, val level: String) : BaseItem() { /** * This adapter is used for displaying logs outputted by the application */ -internal class LogAdapter internal constructor(val context: Context, val compact: Boolean, private val debug_level: Int, private val level_str: Array) : HeaderAdapter(), OnLongClickListener { - private val clipboard: ClipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager +internal class LogAdapter internal constructor(val context : Context, val compact : Boolean, private val debug_level : Int, private val level_str : Array) : HeaderAdapter(), OnLongClickListener { + private val clipboard : ClipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager /** * This function adds a line to this log adapter */ - fun add(logLine: String) { + fun add(logLine : String) { try { val logMeta = logLine.split("|", limit = 3) @@ -50,8 +50,8 @@ internal class LogAdapter internal constructor(val context: Context, val compact } else { addHeader(BaseHeader(logMeta[1])) } - } catch (ignored: IndexOutOfBoundsException) { - } catch (ignored: NumberFormatException) { + } catch (ignored : IndexOutOfBoundsException) { + } catch (ignored : NumberFormatException) { } } @@ -62,7 +62,7 @@ internal class LogAdapter internal constructor(val context: Context, val compact * @param title The TextView associated with the title * @param subtitle The TextView associated with the subtitle */ - private class ItemViewHolder(val parent: View, var title: TextView, var subtitle: TextView? = null) : RecyclerView.ViewHolder(parent) + private class ItemViewHolder(val parent : View, var title : TextView, var subtitle : TextView? = null) : RecyclerView.ViewHolder(parent) /** * The ViewHolder used by headers is used to hold the views associated with an headers @@ -70,12 +70,12 @@ internal class LogAdapter internal constructor(val context: Context, val compact * @param parent The parent view that contains all the others * @param header The TextView associated with the header */ - private class HeaderViewHolder(val parent: View, var header: TextView) : RecyclerView.ViewHolder(parent) + private class HeaderViewHolder(val parent : View, var header : TextView) : RecyclerView.ViewHolder(parent) /** * The onLongClick handler for the supplied [view], used to copy a log into the clipboard */ - override fun onLongClick(view: View): Boolean { + override fun onLongClick(view : View) : Boolean { val item = view.tag as LogItem clipboard.setPrimaryClip(ClipData.newPlainText("Log Message", item.message + " (" + item.level + ")")) Toast.makeText(view.context, "Copied to clipboard", Toast.LENGTH_LONG).show() @@ -85,9 +85,9 @@ internal class LogAdapter internal constructor(val context: Context, val compact /** * This function creates the view-holder of type [viewType] with the layout parent as [parent] */ - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + override fun onCreateViewHolder(parent : ViewGroup, viewType : Int) : RecyclerView.ViewHolder { val inflater = LayoutInflater.from(context) - var holder: RecyclerView.ViewHolder? = null + var holder : RecyclerView.ViewHolder? = null if (viewType == ElementType.Item.ordinal) { if (compact) { @@ -112,7 +112,7 @@ internal class LogAdapter internal constructor(val context: Context, val compact /** * This function binds the item at [position] to the supplied [viewHolder] */ - override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) { + override fun onBindViewHolder(viewHolder : RecyclerView.ViewHolder, position : Int) { val item = getItem(position) if (item is LogItem) { diff --git a/app/src/main/java/emu/skyline/loader/BaseLoader.kt b/app/src/main/java/emu/skyline/loader/BaseLoader.kt index 86e7bae7..811ca1fb 100644 --- a/app/src/main/java/emu/skyline/loader/BaseLoader.kt +++ b/app/src/main/java/emu/skyline/loader/BaseLoader.kt @@ -33,10 +33,10 @@ enum class RomFormat { * @param uri The URL of the ROM * @param contentResolver The instance of ContentResolver associated with the current context */ -fun getRomFormat(uri: Uri, contentResolver: ContentResolver): RomFormat { +fun getRomFormat(uri : Uri, contentResolver : ContentResolver) : RomFormat { var uriStr = "" contentResolver.query(uri, null, null, null, null)?.use { cursor -> - val nameIndex: Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) + val nameIndex : Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) cursor.moveToFirst() uriStr = cursor.getString(nameIndex) } @@ -50,26 +50,26 @@ class AppEntry : Serializable { /** * The name of the application */ - var name: String + var name : String /** * The author of the application, if it can be extracted from the metadata */ - var author: String? = null + var author : String? = null - var icon: Bitmap? = null + var icon : Bitmap? = null /** * The format of the application ROM */ - var format: RomFormat + var format : RomFormat /** * The URI of the application ROM */ - var uri: Uri + var uri : Uri - constructor(name: String, author: String, format: RomFormat, uri: Uri, icon: Bitmap) { + constructor(name : String, author : String, format : RomFormat, uri : Uri, icon : Bitmap) { this.name = name this.author = author this.icon = icon @@ -77,9 +77,9 @@ class AppEntry : Serializable { this.uri = uri } - constructor(context: Context, format: RomFormat, uri: Uri) { + constructor(context : Context, format : RomFormat, uri : Uri) { this.name = context.contentResolver.query(uri, null, null, null, null)?.use { cursor -> - val nameIndex: Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) + val nameIndex : Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) cursor.moveToFirst() cursor.getString(nameIndex) }!!.dropLast(format.name.length + 1) @@ -93,7 +93,7 @@ class AppEntry : Serializable { * @param output The stream to which the object is written into */ @Throws(IOException::class) - private fun writeObject(output: ObjectOutputStream) { + private fun writeObject(output : ObjectOutputStream) { output.writeUTF(name) output.writeObject(format) output.writeUTF(uri.toString()) @@ -111,7 +111,7 @@ class AppEntry : Serializable { * @param input The stream from which the object data is retrieved from */ @Throws(IOException::class, ClassNotFoundException::class) - private fun readObject(input: ObjectInputStream) { + private fun readObject(input : ObjectInputStream) { name = input.readUTF() format = input.readObject() as RomFormat uri = Uri.parse(input.readUTF()) @@ -125,14 +125,14 @@ class AppEntry : Serializable { /** * This class is used as the base class for all loaders */ -internal abstract class BaseLoader(val context: Context, val format: RomFormat) { +internal abstract class BaseLoader(val context : Context, val format : RomFormat) { /** * This is used to get the [AppEntry] for the specified [file] at the supplied [uri] */ - abstract fun getAppEntry(file: RandomAccessDocument, uri: Uri): AppEntry + abstract fun getAppEntry(file : RandomAccessDocument, uri : Uri) : AppEntry /** * This returns if the supplied [file] is a valid ROM or not */ - abstract fun verifyFile(file: RandomAccessDocument): Boolean + abstract fun verifyFile(file : RandomAccessDocument) : Boolean } diff --git a/app/src/main/java/emu/skyline/loader/NroLoader.kt b/app/src/main/java/emu/skyline/loader/NroLoader.kt index b0a90bcf..fdcf3853 100644 --- a/app/src/main/java/emu/skyline/loader/NroLoader.kt +++ b/app/src/main/java/emu/skyline/loader/NroLoader.kt @@ -14,11 +14,11 @@ import java.io.IOException /** * This loader is used to load in NRO (Nintendo Relocatable Object) files (https://switchbrew.org/wiki/NRO) */ -internal class NroLoader(context: Context) : BaseLoader(context, RomFormat.NRO) { +internal class NroLoader(context : Context) : BaseLoader(context, RomFormat.NRO) { /** * This is used to get the [AppEntry] for the specified NRO */ - override fun getAppEntry(file: RandomAccessDocument, uri: Uri): AppEntry { + override fun getAppEntry(file : RandomAccessDocument, uri : Uri) : AppEntry { return try { file.seek(0x18) // Skip to NroHeader.size @@ -52,7 +52,7 @@ internal class NroLoader(context: Context) : BaseLoader(context, RomFormat.NRO) file.read(author) AppEntry(String(name).substringBefore((0.toChar())), String(author).substringBefore((0.toChar())), format, uri, icon) - } catch (e: IOException) { + } catch (e : IOException) { AppEntry(context, format, uri) } } @@ -60,14 +60,14 @@ internal class NroLoader(context: Context) : BaseLoader(context, RomFormat.NRO) /** * This verifies if [file] is a valid NRO file */ - override fun verifyFile(file: RandomAccessDocument): Boolean { + override fun verifyFile(file : RandomAccessDocument) : Boolean { try { file.seek(0x10) // Skip to NroHeader.magic val buffer = ByteArray(4) file.read(buffer) if (String(buffer) != "NRO0") return false - } catch (e: IOException) { + } catch (e : IOException) { return false } return true diff --git a/app/src/main/java/emu/skyline/preference/FolderActivity.kt b/app/src/main/java/emu/skyline/preference/FolderActivity.kt index afaf6fb7..d4c5c8c3 100644 --- a/app/src/main/java/emu/skyline/preference/FolderActivity.kt +++ b/app/src/main/java/emu/skyline/preference/FolderActivity.kt @@ -18,7 +18,7 @@ class FolderActivity : AppCompatActivity() { /** * This launches the [Intent.ACTION_OPEN_DOCUMENT_TREE] intent on creation */ - override fun onCreate(state: Bundle?) { + override fun onCreate(state : Bundle?) { super.onCreate(state) val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) @@ -28,7 +28,7 @@ class FolderActivity : AppCompatActivity() { /** * This changes the search location preference if the [Intent.ACTION_OPEN_DOCUMENT_TREE] has returned and [finish]es the activity */ - public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + public override fun onActivityResult(requestCode : Int, resultCode : Int, data : Intent?) { super.onActivityResult(requestCode, resultCode, data) if (resultCode == Activity.RESULT_OK) { diff --git a/app/src/main/java/emu/skyline/preference/FolderPreference.kt b/app/src/main/java/emu/skyline/preference/FolderPreference.kt index 65f0ba40..c99d9ffa 100644 --- a/app/src/main/java/emu/skyline/preference/FolderPreference.kt +++ b/app/src/main/java/emu/skyline/preference/FolderPreference.kt @@ -20,15 +20,15 @@ class FolderPreference : Preference { /** * The directory the preference is currently set to */ - private var mDirectory: String? = null + private var mDirectory : String? = null - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + constructor(context : Context?, attrs : AttributeSet?, defStyleAttr : Int) : super(context, attrs, defStyleAttr) { summaryProvider = SimpleSummaryProvider() } - constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, R.attr.preferenceStyle) + constructor(context : Context?, attrs : AttributeSet?) : this(context, attrs, R.attr.preferenceStyle) - constructor(context: Context?) : this(context, null) + constructor(context : Context?) : this(context, null) /** * This launches [FolderActivity] on click to change the directory @@ -41,7 +41,7 @@ class FolderPreference : Preference { /** * This sets the initial value of [mDirectory] */ - override fun onSetInitialValue(defaultValue: Any?) { + override fun onSetInitialValue(defaultValue : Any?) { mDirectory = getPersistedString(defaultValue as String?) } @@ -52,7 +52,7 @@ class FolderPreference : Preference { /** * This returns the decoded URI of the directory as the summary */ - override fun provideSummary(preference: FolderPreference): CharSequence { + override fun provideSummary(preference : FolderPreference) : CharSequence { return Uri.decode(preference.mDirectory) ?: "" } } diff --git a/app/src/main/java/emu/skyline/preference/LicenseDialog.kt b/app/src/main/java/emu/skyline/preference/LicenseDialog.kt index 9c5b2a2e..bf24dca3 100644 --- a/app/src/main/java/emu/skyline/preference/LicenseDialog.kt +++ b/app/src/main/java/emu/skyline/preference/LicenseDialog.kt @@ -22,11 +22,11 @@ class LicenseDialog : DialogFragment() { /** * This inflates the layout of the dialog and sets the minimum width/height to 90% of the screen size */ - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView(inflater : LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) : View? { val layout = layoutInflater.inflate(R.layout.license_dialog, container) val displayRectangle = Rect() - val window: Window = activity!!.window + val window : Window = activity!!.window window.decorView.getWindowVisibleDisplayFrame(displayRectangle) layout.minimumWidth = ((displayRectangle.width() * 0.9f).toInt()) @@ -38,7 +38,7 @@ class LicenseDialog : DialogFragment() { /** * This sets the [license_url] and [license_content] based on arguments passed */ - override fun onActivityCreated(savedInstanceState: Bundle?) { + override fun onActivityCreated(savedInstanceState : Bundle?) { super.onActivityCreated(savedInstanceState) license_url.text = arguments?.getString("libraryUrl")!! diff --git a/app/src/main/java/emu/skyline/preference/LicensePreference.kt b/app/src/main/java/emu/skyline/preference/LicensePreference.kt index 9e598801..1f26eb5a 100644 --- a/app/src/main/java/emu/skyline/preference/LicensePreference.kt +++ b/app/src/main/java/emu/skyline/preference/LicensePreference.kt @@ -20,7 +20,7 @@ class LicensePreference : Preference { /** * The [FragmentManager] is used to show the [LicenseDialog] fragment */ - private val fragmentManager: FragmentManager + private val fragmentManager : FragmentManager /** * The tag used by this preference when launching a corresponding fragment @@ -30,17 +30,17 @@ class LicensePreference : Preference { /** * The URL of the library */ - private var libraryUrl: String? = null + private var libraryUrl : String? = null /** * The contents of the license of this library */ - private var libraryLicense: Int? = null + private var libraryLicense : Int? = null /** * The constructor assigns the [fragmentManager] from the activity and finds [libraryUrl] and [libraryLicense] in the attributes */ - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { + constructor(context : Context?, attrs : AttributeSet?, defStyleAttr : Int, defStyleRes : Int) : super(context, attrs, defStyleAttr, defStyleRes) { fragmentManager = (context as AppCompatActivity).supportFragmentManager for (i in 0 until attrs!!.attributeCount) { @@ -53,11 +53,11 @@ class LicensePreference : Preference { } } - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : this(context, attrs, defStyleAttr, 0) + constructor(context : Context?, attrs : AttributeSet?, defStyleAttr : Int) : this(context, attrs, defStyleAttr, 0) - constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, R.attr.dialogPreferenceStyle) + constructor(context : Context?, attrs : AttributeSet?) : this(context, attrs, R.attr.dialogPreferenceStyle) - constructor(context: Context?) : this(context, null) + constructor(context : Context?) : this(context, null) /** * The [LicenseDialog] fragment is shown using [fragmentManager] on click with [libraryUrl] and [libraryLicense] passed as arguments diff --git a/app/src/main/java/emu/skyline/preference/ThemePreference.kt b/app/src/main/java/emu/skyline/preference/ThemePreference.kt index 18692316..d7fcc81c 100644 --- a/app/src/main/java/emu/skyline/preference/ThemePreference.kt +++ b/app/src/main/java/emu/skyline/preference/ThemePreference.kt @@ -14,16 +14,16 @@ import androidx.preference.ListPreference * This preference is used to set the theme to Light/Dark mode */ class ThemePreference : ListPreference { - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + constructor(context : Context?, attrs : AttributeSet?, defStyleAttr : Int) : super(context, attrs, defStyleAttr) - constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) + constructor(context : Context?, attrs : AttributeSet?) : super(context, attrs) - constructor(context: Context?) : super(context) + constructor(context : Context?) : super(context) /** * This changes [AppCompatDelegate.sDefaultNightMode] based on what the user's selection is */ - override fun callChangeListener(newValue: Any?): Boolean { + override fun callChangeListener(newValue : Any?) : Boolean { AppCompatDelegate.setDefaultNightMode(when ((newValue as String).toInt()) { 0 -> AppCompatDelegate.MODE_NIGHT_NO 1 -> AppCompatDelegate.MODE_NIGHT_YES diff --git a/app/src/main/java/emu/skyline/utility/RandomAccessDocument.kt b/app/src/main/java/emu/skyline/utility/RandomAccessDocument.kt index 24a40a30..60b948bb 100644 --- a/app/src/main/java/emu/skyline/utility/RandomAccessDocument.kt +++ b/app/src/main/java/emu/skyline/utility/RandomAccessDocument.kt @@ -15,7 +15,7 @@ import java.nio.ByteBuffer * * @param parcelFileDescriptor The file descriptor for the [DocumentFile] */ -class RandomAccessDocument(private var parcelFileDescriptor: ParcelFileDescriptor) { +class RandomAccessDocument(private var parcelFileDescriptor : ParcelFileDescriptor) { /** * The actual file descriptor for the [DocumentFile] as an [FileDescriptor] object */ @@ -24,19 +24,19 @@ class RandomAccessDocument(private var parcelFileDescriptor: ParcelFileDescripto /** * The current position of where the file is being read */ - private var position: Long = 0 + private var position : Long = 0 /** * The constructor sets [parcelFileDescriptor] by opening a read-only FD to [file] */ - constructor(context: Context, file: DocumentFile) : this(context.contentResolver.openFileDescriptor(file.uri, "r")!!) + constructor(context : Context, file : DocumentFile) : this(context.contentResolver.openFileDescriptor(file.uri, "r")!!) /** * This reads in as many as possible bytes into [array] (Generally [array].size) * * @return The amount of bytes read from the file */ - fun read(array: ByteArray): Int { + fun read(array : ByteArray) : Int { val bytesRead = android.system.Os.pread(fileDescriptor, array, 0, array.size, position) position += bytesRead return bytesRead @@ -47,7 +47,7 @@ class RandomAccessDocument(private var parcelFileDescriptor: ParcelFileDescripto * * @return The amount of bytes read from the file */ - fun read(buffer: ByteBuffer): Int { + fun read(buffer : ByteBuffer) : Int { val bytesRead = android.system.Os.pread(fileDescriptor, buffer.array(), 0, buffer.array().size, position) position += bytesRead return bytesRead @@ -56,8 +56,8 @@ class RandomAccessDocument(private var parcelFileDescriptor: ParcelFileDescripto /** * This returns a single [Long] from the file at the current [position] */ - fun readLong(): Long { - val buffer: ByteBuffer = ByteBuffer.allocate(Long.SIZE_BYTES) + fun readLong() : Long { + val buffer : ByteBuffer = ByteBuffer.allocate(Long.SIZE_BYTES) read(buffer) return buffer.long } @@ -65,8 +65,8 @@ class RandomAccessDocument(private var parcelFileDescriptor: ParcelFileDescripto /** * This returns a single [Int] from the file at the current [position] */ - fun readInt(): Int { - val buffer: ByteBuffer = ByteBuffer.allocate(Int.SIZE_BYTES) + fun readInt() : Int { + val buffer : ByteBuffer = ByteBuffer.allocate(Int.SIZE_BYTES) read(buffer) return buffer.int } @@ -74,14 +74,14 @@ class RandomAccessDocument(private var parcelFileDescriptor: ParcelFileDescripto /** * This sets [RandomAccessDocument.position] to the supplied [position] */ - fun seek(position: Long) { + fun seek(position : Long) { this.position = position } /** * This increments [position] by [amount] */ - fun skipBytes(amount: Long) { + fun skipBytes(amount : Long) { this.position += amount } diff --git a/app/src/main/res/layout/app_dialog.xml b/app/src/main/res/layout/app_dialog.xml index f67dfae6..a7e743b5 100644 --- a/app/src/main/res/layout/app_dialog.xml +++ b/app/src/main/res/layout/app_dialog.xml @@ -4,6 +4,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" + android:nextFocusRight="@id/game_play" android:padding="16dp"> diff --git a/app/src/main/res/layout/app_item_grid.xml b/app/src/main/res/layout/app_item_grid.xml index 720fe7c5..8d023883 100644 --- a/app/src/main/res/layout/app_item_grid.xml +++ b/app/src/main/res/layout/app_item_grid.xml @@ -16,38 +16,46 @@ card_view:cardCornerRadius="4dp"> + android:contentDescription="@string/icon" + android:scaleType="centerCrop" /> diff --git a/app/src/main/res/layout/emu_activity.xml b/app/src/main/res/layout/emu_activity.xml index 90fbff51..3f3c368f 100644 --- a/app/src/main/res/layout/emu_activity.xml +++ b/app/src/main/res/layout/emu_activity.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:keepScreenOn="true" tools:context=".EmulationActivity"> @@ -37,7 +36,6 @@ style="@style/Widget.MaterialComponents.FloatingActionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:padding="8dp" app:maxImageSize="26dp" app:srcCompat="@drawable/ic_log" /> diff --git a/app/src/main/res/layout/titlebar.xml b/app/src/main/res/layout/titlebar.xml index 9cce6c22..c5fc1cac 100644 --- a/app/src/main/res/layout/titlebar.xml +++ b/app/src/main/res/layout/titlebar.xml @@ -1,8 +1,10 @@