diff --git a/app/src/main/cpp/main.cpp b/app/src/main/cpp/main.cpp
index 48ef8b08..18b8f57c 100644
--- a/app/src/main/cpp/main.cpp
+++ b/app/src/main/cpp/main.cpp
@@ -21,7 +21,7 @@ void signalHandler(int signal) {
FaultCount++;
}
-extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeRom(JNIEnv *env, jobject instance, jstring romUriJstring, jint romType, jint romFd, jint preferenceFd, jint logFd) {
+extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(JNIEnv *env, jobject instance, jstring romUriJstring, jint romType, jint romFd, jint preferenceFd, jint logFd) {
Halt = false;
FaultCount = 0;
diff --git a/app/src/main/java/emu/skyline/EmulationActivity.kt b/app/src/main/java/emu/skyline/EmulationActivity.kt
index e8d2cbff..48749c88 100644
--- a/app/src/main/java/emu/skyline/EmulationActivity.kt
+++ b/app/src/main/java/emu/skyline/EmulationActivity.kt
@@ -18,9 +18,6 @@ import emu.skyline.loader.getRomFormat
import kotlinx.android.synthetic.main.app_activity.*
import java.io.File
-/**
- * This activity is used for emulation using libskyline
- */
class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
init {
System.loadLibrary("skyline") // libskyline.so
@@ -65,7 +62,7 @@ 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 executeRom(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
@@ -86,7 +83,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
*
* @param rom The URI of the ROM to execute
*/
- private fun executeRom(rom : Uri) {
+ private fun executeApplication(rom: Uri) {
val romType = getRomFormat(rom, contentResolver).ordinal
romFd = contentResolver.openFileDescriptor(rom, "r")!!
@@ -94,7 +91,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
while ((surface == null))
Thread.yield()
- executeRom(Uri.decode(rom.toString()), romType, romFd.fd, preferenceFd.fd, logFd.fd)
+ executeApplication(Uri.decode(rom.toString()), romType, romFd.fd, preferenceFd.fd, logFd.fd)
if (shouldFinish)
runOnUiThread { finish() }
@@ -104,12 +101,12 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
}
/**
- * The onCreate handler for the activity, it sets up the FDs and calls [executeRom]
+ * This sets up [preferenceFd] and [logFd] then calls [executeApplication] for executing the application
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.game_activity)
+ setContentView(R.layout.app_activity)
val preference = File("${applicationInfo.dataDir}/shared_prefs/${applicationInfo.packageName}_preferences.xml")
preferenceFd = ParcelFileDescriptor.open(preference, ParcelFileDescriptor.MODE_READ_WRITE)
@@ -120,11 +117,11 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
game_view.holder.addCallback(this)
- executeRom(intent.data!!)
+ executeApplication(intent.data!!)
}
/**
- * The onNewIntent handler is used to stop the currently executing ROM and replace it with the one specified in the new intent
+ * 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?) {
shouldFinish = false
@@ -136,13 +133,13 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
romFd.close()
- executeRom(intent?.data!!)
+ executeApplication(intent?.data!!)
super.onNewIntent(intent)
}
/**
- * The onDestroy handler is used to halt emulation
+ * This is used to halt emulation entirely
*/
override fun onDestroy() {
shouldFinish = false
@@ -158,7 +155,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
}
/**
- * The surfaceCreated handler passes in the surface to libskyline
+ * This sets [surface] to [holder].surface and passes it into libskyline
*/
override fun surfaceCreated(holder: SurfaceHolder?) {
Log.d("surfaceCreated", "Holder: ${holder.toString()}")
@@ -167,14 +164,14 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
}
/**
- * The surfaceChanged handler is purely used for debugging purposes
+ * This is purely used for debugging surface changes
*/
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
Log.d("surfaceChanged", "Holder: ${holder.toString()}, Format: $format, Width: $width, Height: $height")
}
/**
- * The surfaceDestroyed handler passes sets the surface to null
+ * This sets [surface] to null and passes it into libskyline
*/
override fun surfaceDestroyed(holder: SurfaceHolder?) {
Log.d("surfaceDestroyed", "Holder: ${holder.toString()}")
diff --git a/app/src/main/java/emu/skyline/LogActivity.kt b/app/src/main/java/emu/skyline/LogActivity.kt
index 66f14c7d..c86c41a6 100644
--- a/app/src/main/java/emu/skyline/LogActivity.kt
+++ b/app/src/main/java/emu/skyline/LogActivity.kt
@@ -10,7 +10,6 @@ import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
-import android.widget.ListView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
@@ -18,23 +17,37 @@ import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.snackbar.Snackbar
import emu.skyline.adapter.LogAdapter
import kotlinx.android.synthetic.main.log_activity.*
+import kotlinx.android.synthetic.main.titlebar.*
import org.json.JSONObject
-import java.io.*
+import java.io.File
+import java.io.FileNotFoundException
+import java.io.IOException
import java.net.URL
-import java.nio.charset.StandardCharsets
-import java.util.stream.Collectors
import javax.net.ssl.HttpsURLConnection
class LogActivity : AppCompatActivity() {
+ /**
+ * The log file is used to read log entries from or to clear all entries
+ */
private lateinit var logFile: File
+
+ /**
+ * The adapter used for adding elements from the log to [log_list]
+ */
private lateinit var adapter: LogAdapter
+ /**
+ * This initializes [toolbar] and fills [log_list] with data from the logs
+ */
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+
setContentView(R.layout.log_activity)
- setSupportActionBar(findViewById(R.id.toolbar))
+
+ setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
@@ -51,24 +64,30 @@ class LogActivity : AppCompatActivity() {
try {
logFile = File("${applicationInfo.dataDir}/skyline.log")
+
logFile.forEachLine {
adapter.add(it)
}
} 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) {
Log.w("Logger", "IO Error during access of log file: " + e.message)
- Toast.makeText(applicationContext, getString(R.string.io_error) + ": " + e.message, Toast.LENGTH_LONG).show()
+ Toast.makeText(applicationContext, getString(R.string.error) + ": ${e.localizedMessage}", Toast.LENGTH_LONG).show()
}
}
+ /**
+ * This inflates the layout for the menu [R.menu.toolbar_log] and sets up searching the logs
+ */
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.toolbar_log, menu)
- val mSearch = menu.findItem(R.id.action_search_log)
- val searchView = mSearch.actionView as SearchView
+
+ 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 {
searchView.isIconified = false
@@ -80,9 +99,13 @@ class LogActivity : AppCompatActivity() {
return true
}
})
+
return super.onCreateOptionsMenu(menu)
}
+ /**
+ * This handles menu selection for [R.id.action_clear] and [R.id.action_share_log]
+ */
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_clear -> {
@@ -90,57 +113,67 @@ class LogActivity : AppCompatActivity() {
logFile.writeText("")
} catch (e: IOException) {
Log.w("Logger", "IO Error while clearing the log file: " + e.message)
- Toast.makeText(applicationContext, getString(R.string.io_error) + ": " + e.message, Toast.LENGTH_LONG).show()
+ Toast.makeText(applicationContext, getString(R.string.error) + ": ${e.localizedMessage}", Toast.LENGTH_LONG).show()
}
+
Toast.makeText(applicationContext, getString(R.string.cleared), Toast.LENGTH_LONG).show()
finish()
true
}
+
R.id.action_share_log -> {
uploadAndShareLog()
true
}
+
else -> super.onOptionsItemSelected(item)
}
}
+ /**
+ * This uploads the logs and launches the [Intent.ACTION_SEND] intent
+ */
private fun uploadAndShareLog() {
+ Snackbar.make(findViewById(android.R.id.content), getString(R.string.upload_logs), Snackbar.LENGTH_SHORT).show()
+
val shareThread = Thread(Runnable {
var urlConnection: HttpsURLConnection? = null
+
try {
val url = URL("https://hastebin.com/documents")
+
urlConnection = url.openConnection() as HttpsURLConnection
urlConnection.requestMethod = "POST"
urlConnection.setRequestProperty("Host", "hastebin.com")
urlConnection.setRequestProperty("Content-Type", "application/json; charset=utf-8")
urlConnection.setRequestProperty("Referer", "https://hastebin.com/")
+
val bufferedWriter = urlConnection.outputStream.bufferedWriter()
bufferedWriter.write(logFile.readText())
bufferedWriter.flush()
bufferedWriter.close()
+
if (urlConnection.responseCode != 200) {
Log.e("LogUpload", "HTTPS Status Code: " + urlConnection.responseCode)
throw Exception()
}
+
val bufferedReader = urlConnection.inputStream.bufferedReader()
val key = JSONObject(bufferedReader.readText()).getString("key")
bufferedReader.close()
+
val result = "https://hastebin.com/$key"
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) {
- runOnUiThread { Toast.makeText(applicationContext, getString(R.string.share_error), Toast.LENGTH_LONG).show() }
+ runOnUiThread { Snackbar.make(findViewById(android.R.id.content), getString(R.string.error) + ": ${e.localizedMessage}", Snackbar.LENGTH_LONG).show() }
e.printStackTrace()
} finally {
urlConnection!!.disconnect()
}
})
+
shareThread.start()
- try {
- shareThread.join(1000)
- } catch (e: Exception) {
- Toast.makeText(applicationContext, getString(R.string.share_error), Toast.LENGTH_LONG).show()
- e.printStackTrace()
- }
}
}
diff --git a/app/src/main/java/emu/skyline/MainActivity.kt b/app/src/main/java/emu/skyline/MainActivity.kt
index de1255ad..54e488bd 100644
--- a/app/src/main/java/emu/skyline/MainActivity.kt
+++ b/app/src/main/java/emu/skyline/MainActivity.kt
@@ -11,8 +11,6 @@ import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
-import android.widget.AdapterView
-import android.widget.AdapterView.OnItemClickListener
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.widget.SearchView
@@ -32,48 +30,63 @@ 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.*
import java.io.File
import java.io.IOException
import kotlin.concurrent.thread
import kotlin.math.ceil
-class MainActivity : AppCompatActivity(), View.OnClickListener {
+class MainActivity : AppCompatActivity(), View.OnClickListener, View.OnLongClickListener {
+ /**
+ * This is used to get/set shared preferences
+ */
private lateinit var sharedPreferences: SharedPreferences
- private var adapter = AppAdapter(this)
- private fun notifyUser(text: String) {
- Snackbar.make(findViewById(android.R.id.content), text, Snackbar.LENGTH_SHORT).show()
- }
+ /**
+ * The adapter used for adding elements to [app_list]
+ */
+ private lateinit var adapter: AppAdapter
- private fun findFile(ext: String, loader: BaseLoader, directory: DocumentFile, found: Boolean = false): Boolean {
+ /**
+ * 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 {
var foundCurrent = found
- directory.listFiles()
- .forEach { file ->
- if (file.isDirectory) {
- foundCurrent = findFile(ext, loader, file, foundCurrent)
- } else {
- if (ext.equals(file.name?.substringAfterLast("."), ignoreCase = true)) {
- val document = RandomAccessDocument(this, file)
- if (loader.verifyFile(document)) {
- val entry = loader.getAppEntry(document, file.uri)
- runOnUiThread {
- if (!foundCurrent) {
- adapter.addHeader(loader.format.name)
- foundCurrent = true
- }
- adapter.addItem(AppItem(entry))
- }
+ directory.listFiles().forEach { file ->
+ if (file.isDirectory) {
+ foundCurrent = addEntries(extension, loader, file, foundCurrent)
+ } else {
+ if (extension.equals(file.name?.substringAfterLast("."), ignoreCase = true)) {
+ val document = RandomAccessDocument(this, file)
+
+ if (loader.verifyFile(document)) {
+ val entry = loader.getAppEntry(document, file.uri)
+
+ runOnUiThread {
+ if (!foundCurrent) {
+ adapter.addHeader(loader.format.name)
+ foundCurrent = true
}
- document.close()
+
+ adapter.addItem(AppItem(entry))
}
}
+
+ document.close()
}
+ }
+ }
return foundCurrent
}
- private fun refreshFiles(tryLoad: Boolean) {
+ /**
+ * This refreshes the contents of the adapter by either trying to load cached adapter data or searches for them to recreate a list
+ *
+ * @param tryLoad If this is false then trying to load cached adapter data is skipped entirely
+ */
+ private fun refreshAdapter(tryLoad: Boolean) {
if (tryLoad) {
try {
adapter.load(File("${applicationInfo.dataDir}/roms.bin"))
@@ -89,7 +102,8 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
try {
runOnUiThread { adapter.clear() }
- val foundNros = findFile("nro", NroLoader(this), DocumentFile.fromTreeUri(this, Uri.parse(sharedPreferences.getString("search_location", "")))!!)
+
+ val foundNros = addEntries("nro", NroLoader(this), DocumentFile.fromTreeUri(this, Uri.parse(sharedPreferences.getString("search_location", "")))!!)
runOnUiThread {
if (!foundNros)
@@ -113,7 +127,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
}
} catch (e: Exception) {
runOnUiThread {
- notifyUser(e.message!!)
+ Snackbar.make(findViewById(android.R.id.content), getString(R.string.error) + ": ${e.localizedMessage}", Snackbar.LENGTH_SHORT).show()
}
}
@@ -121,18 +135,26 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
}
}
+ /**
+ * This initializes [toolbar], [open_fab], [log_fab] and [app_list]
+ */
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+
setContentView(R.layout.main_activity)
+
+ setSupportActionBar(toolbar)
+
PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
+
AppCompatDelegate.setDefaultNightMode(when ((sharedPreferences.getString("app_theme", "2")?.toInt())) {
0 -> AppCompatDelegate.MODE_NIGHT_NO
1 -> AppCompatDelegate.MODE_NIGHT_YES
2 -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
else -> AppCompatDelegate.MODE_NIGHT_UNSPECIFIED
})
- setSupportActionBar(toolbar)
+
open_fab.setOnClickListener(this)
log_fab.setOnClickListener(this)
@@ -157,22 +179,25 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
app_list.layoutManager = layoutManager
}
- true
}
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
+
startActivityForResult(intent, 1)
} else
- refreshFiles(!sharedPreferences.getBoolean("refresh_required", false))
+ refreshAdapter(!sharedPreferences.getBoolean("refresh_required", false))
}
+ /**
+ * This inflates the layout for the menu [R.menu.toolbar_main] and sets up searching the logs
+ */
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.toolbar_main, menu)
- val mSearch = menu.findItem(R.id.action_search_main)
- val searchView = mSearch.actionView as SearchView
- searchView.isSubmitButtonEnabled = false
+
+ val searchView = menu.findItem(R.id.action_search_main).actionView as SearchView
+
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
searchView.clearFocus()
@@ -184,19 +209,26 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
return true
}
})
+
return super.onCreateOptionsMenu(menu)
}
+ /**
+ * 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) {
when (view.id) {
R.id.log_fab -> startActivity(Intent(this, LogActivity::class.java))
+
R.id.open_fab -> {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
+
startActivityForResult(intent, 2)
}
- R.id.app_item_linear -> {
+
+ R.id.app_item_linear, R.id.app_item_grid -> {
val tag = view.tag
if (tag is AppItem) {
@@ -209,9 +241,12 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
}
}
+ /**
+ * This handles long-click interaction with [R.id.app_item_linear] and [R.id.app_item_grid]
+ */
override fun onLongClick(view: View?): Boolean {
when (view?.id) {
- R.id.app_item_linear -> {
+ R.id.app_item_linear, R.id.app_item_grid -> {
val tag = view.tag
if (tag is AppItem) {
@@ -225,47 +260,58 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
return false
}
+ /**
+ * This handles menu interaction for [R.id.action_settings] and [R.id.action_refresh]
+ */
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_settings -> {
startActivityForResult(Intent(this, SettingsActivity::class.java), 3)
true
}
+
R.id.action_refresh -> {
- refreshFiles(false)
- notifyUser(getString(R.string.refreshed))
+ refreshAdapter(false)
true
}
+
else -> super.onOptionsItemSelected(item)
}
}
+ /**
+ * 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?) {
super.onActivityResult(requestCode, resultCode, intent)
+
if (resultCode == RESULT_OK) {
when (requestCode) {
1 -> {
val uri = intent!!.data!!
contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
sharedPreferences.edit().putString("search_location", uri.toString()).apply()
- refreshFiles(!sharedPreferences.getBoolean("refresh_required", false))
+
+ refreshAdapter(!sharedPreferences.getBoolean("refresh_required", false))
}
+
2 -> {
try {
- val uri = (intent!!.data!!)
val intentGame = Intent(this, EmulationActivity::class.java)
- intentGame.data = uri
+ intentGame.data = intent!!.data!!
+
if (resultCode != 0)
startActivityForResult(intentGame, resultCode)
else
startActivity(intentGame)
} catch (e: Exception) {
- notifyUser(e.message!!)
+ Snackbar.make(findViewById(android.R.id.content), getString(R.string.error) + ": ${e.localizedMessage}", Snackbar.LENGTH_SHORT).show()
}
}
+
3 -> {
if (sharedPreferences.getBoolean("refresh_required", false))
- refreshFiles(false)
+ refreshAdapter(false)
}
}
}
diff --git a/app/src/main/java/emu/skyline/SettingsActivity.kt b/app/src/main/java/emu/skyline/SettingsActivity.kt
index 89627b90..cf0a27a4 100644
--- a/app/src/main/java/emu/skyline/SettingsActivity.kt
+++ b/app/src/main/java/emu/skyline/SettingsActivity.kt
@@ -9,33 +9,54 @@ import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceFragmentCompat
-import kotlinx.android.synthetic.main.log_activity.*
+import kotlinx.android.synthetic.main.titlebar.*
class SettingsActivity : AppCompatActivity() {
+ /**
+ * This is the instance of [PreferenceFragment] that is shown inside [R.id.settings]
+ */
private val preferenceFragment: PreferenceFragment = PreferenceFragment()
+ /**
+ * This initializes [toolbar] and [R.id.settings]
+ */
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+
setContentView(R.layout.settings_activity)
+
+ setSupportActionBar(toolbar)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, preferenceFragment)
.commit()
- setSupportActionBar(toolbar)
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
+ /**
+ * This is used to refresh the preferences after [emu.skyline.preference.FolderActivity] has returned
+ */
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
preferenceFragment.refreshPreferences()
}
+ /**
+ * This fragment is used to display all of the preferences and handle refreshing the preferences
+ */
class PreferenceFragment : PreferenceFragmentCompat() {
+ /**
+ * This clears the preference screen and reloads all preferences
+ */
fun refreshPreferences() {
preferenceScreen = null
addPreferencesFromResource(R.xml.preferences)
}
+ /**
+ * This constructs the preferences from [R.xml.preferences]
+ */
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
}
diff --git a/app/src/main/res/drawable/ic_open.xml b/app/src/main/res/drawable/ic_open.xml
index b2353ced..12ac4182 100644
--- a/app/src/main/res/drawable/ic_open.xml
+++ b/app/src/main/res/drawable/ic_open.xml
@@ -1,9 +1,9 @@
+ 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" />
diff --git a/app/src/main/res/layout/log_activity.xml b/app/src/main/res/layout/log_activity.xml
index 5ff247b8..2e9e684b 100644
--- a/app/src/main/res/layout/log_activity.xml
+++ b/app/src/main/res/layout/log_activity.xml
@@ -1,22 +1,12 @@
-
-
+
-
+ app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+
diff --git a/app/src/main/res/layout/main_activity.xml b/app/src/main/res/layout/main_activity.xml
index 44782500..5df194f0 100644
--- a/app/src/main/res/layout/main_activity.xml
+++ b/app/src/main/res/layout/main_activity.xml
@@ -1,61 +1,45 @@
-
-
+
-
-
+ app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+ android:layout_gravity="bottom|end"
+ android:layout_margin="16dp"
+ android:orientation="vertical">
-
+
diff --git a/app/src/main/res/layout/settings_activity.xml b/app/src/main/res/layout/settings_activity.xml
index a5275947..0466f167 100644
--- a/app/src/main/res/layout/settings_activity.xml
+++ b/app/src/main/res/layout/settings_activity.xml
@@ -4,17 +4,7 @@
android:layout_height="wrap_content"
android:orientation="vertical">
-
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 4a5d488f..5406abd5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,24 +2,25 @@
Skyline
Search
+ An error has occurred
Settings
Logger
Refresh
- The list of ROMs has been refreshed.
Metadata Missing
Icon
Cannot find any ROMs
Pin
Play
+ Searching for ROMs
Clear
Share
The log file was not found
An I/O error has occurred
- An error has occurred while sharing
+ The logs are being uploaded
The logs have been cleared
Emulator