From ce4d295d816b6a3e80d39b821e0b306930e6c558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=97=B1=20PixelyIon?= Date: Sun, 12 Apr 2020 21:42:46 +0530 Subject: [PATCH] Refactor Preferences and Loaders This refactors all preferences and loaders in regards to This commit mainly refactors the adapters by adding spacing, comments and following other guidelines. In addition, preferences are now moved into their own sub-package and `LicensePreference` has a minor UI update. --- app/src/main/AndroidManifest.xml | 10 +- .../java/emu/skyline/loader/BaseLoader.kt | 10 +- .../main/java/emu/skyline/loader/NroLoader.kt | 6 + .../{utility => preference}/FolderActivity.kt | 21 +++- .../skyline/preference/FolderPreference.kt | 59 +++++++++ .../emu/skyline/preference/LicenseDialog.kt | 47 +++++++ .../LicensePreference.kt | 40 ++++-- .../ThemePreference.kt | 9 +- .../emu/skyline/utility/FolderPreference.kt | 115 ------------------ .../java/emu/skyline/utility/LicenseDialog.kt | 34 ------ app/src/main/res/layout/license_dialog.xml | 41 +++---- app/src/main/res/values/strings.xml | 4 +- app/src/main/res/xml/preferences.xml | 29 +++-- 13 files changed, 220 insertions(+), 205 deletions(-) rename app/src/main/java/emu/skyline/{utility => preference}/FolderActivity.kt (74%) create mode 100644 app/src/main/java/emu/skyline/preference/FolderPreference.kt create mode 100644 app/src/main/java/emu/skyline/preference/LicenseDialog.kt rename app/src/main/java/emu/skyline/{utility => preference}/LicensePreference.kt (66%) rename app/src/main/java/emu/skyline/{utility => preference}/ThemePreference.kt (82%) delete mode 100644 app/src/main/java/emu/skyline/utility/FolderPreference.kt delete mode 100644 app/src/main/java/emu/skyline/utility/LicenseDialog.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 75e10a54..844597fa 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -38,7 +38,12 @@ android:name="android.support.PARENT_ACTIVITY" android:value="emu.skyline.MainActivity" /> - + + + + @@ -47,7 +52,8 @@ android:name="emu.skyline.EmulationActivity" android:configChanges="orientation|screenSize" android:launchMode="singleInstance" - android:screenOrientation="landscape"> + android:screenOrientation="landscape" + tools:ignore="LockedOrientationActivity"> diff --git a/app/src/main/java/emu/skyline/loader/BaseLoader.kt b/app/src/main/java/emu/skyline/loader/BaseLoader.kt index bbae7f94..63367c91 100644 --- a/app/src/main/java/emu/skyline/loader/BaseLoader.kt +++ b/app/src/main/java/emu/skyline/loader/BaseLoader.kt @@ -22,7 +22,9 @@ import java.util.* * An enumeration of all supported ROM formats */ enum class RomFormat { - NRO, XCI, NSP + NRO, + XCI, + NSP, } /** @@ -80,7 +82,7 @@ class AppEntry : Serializable { val nameIndex: Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) cursor.moveToFirst() cursor.getString(nameIndex) - }!! + }!!.dropLast(format.name.length + 1) this.format = format this.uri = uri } @@ -125,12 +127,12 @@ class AppEntry : Serializable { */ internal abstract class BaseLoader(val context: Context, val format: RomFormat) { /** - * This returns an AppEntry object for the supplied document + * This is used to get the [AppEntry] for the specified [file] at the supplied [uri] */ abstract fun getAppEntry(file: RandomAccessDocument, uri: Uri): AppEntry /** - * This returns if the supplied document is a valid ROM or not + * This returns if the supplied [file] is a valid ROM or not */ 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 828c2d07..56d4a5df 100644 --- a/app/src/main/java/emu/skyline/loader/NroLoader.kt +++ b/app/src/main/java/emu/skyline/loader/NroLoader.kt @@ -15,6 +15,9 @@ 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) { + /** + * This is used to get the [AppEntry] for the specified NRO + */ override fun getAppEntry(file: RandomAccessDocument, uri: Uri): AppEntry { return try { file.seek(0x18) // Skip to NroHeader.size @@ -54,6 +57,9 @@ internal class NroLoader(context: Context) : BaseLoader(context, RomFormat.NRO) } } + /** + * This verifies if [file] is a valid NRO file + */ override fun verifyFile(file: RandomAccessDocument): Boolean { try { file.seek(0x10) // Skip to NroHeader.magic diff --git a/app/src/main/java/emu/skyline/utility/FolderActivity.kt b/app/src/main/java/emu/skyline/preference/FolderActivity.kt similarity index 74% rename from app/src/main/java/emu/skyline/utility/FolderActivity.kt rename to app/src/main/java/emu/skyline/preference/FolderActivity.kt index 112a46c0..04d0ba92 100644 --- a/app/src/main/java/emu/skyline/utility/FolderActivity.kt +++ b/app/src/main/java/emu/skyline/preference/FolderActivity.kt @@ -3,7 +3,7 @@ * Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) */ -package emu.skyline.utility +package emu.skyline.preference import android.app.Activity import android.content.Intent @@ -11,26 +11,39 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.preference.PreferenceManager +/** + * This activity is used to select a new search location and set preferences to reflect that + */ class FolderActivity : AppCompatActivity() { + /** + * This launches the [Intent.ACTION_OPEN_DOCUMENT_TREE] intent on creation + */ override fun onCreate(state: Bundle?) { super.onCreate(state) + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) this.startActivityForResult(intent, 1) } + /** + * 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?) { super.onActivityResult(requestCode, resultCode, data) + if (resultCode == Activity.RESULT_OK) { if (requestCode == 1) { val uri = data!!.data!! + contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION) + PreferenceManager.getDefaultSharedPreferences(this).edit() .putString("search_location", uri.toString()) .putBoolean("refresh_required", true) .apply() - finish() } - } else - finish() + } + + finish() } } diff --git a/app/src/main/java/emu/skyline/preference/FolderPreference.kt b/app/src/main/java/emu/skyline/preference/FolderPreference.kt new file mode 100644 index 00000000..d970bf95 --- /dev/null +++ b/app/src/main/java/emu/skyline/preference/FolderPreference.kt @@ -0,0 +1,59 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + */ + +package emu.skyline.preference + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.util.AttributeSet +import androidx.preference.Preference +import androidx.preference.R + +/** + * This preference shows the decoded URI of it's preference and launches [FolderActivity] + */ +class FolderPreference : Preference { + /** + * The directory the preference is currently set to + */ + private var mDirectory: String? = null + + 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?) : this(context, null) + + /** + * This launches [FolderActivity] on click to change the directory + */ + override fun onClick() { + val intent = Intent(context, FolderActivity::class.java) + (context as Activity).startActivityForResult(intent, 0) + } + + /** + * This sets the initial value of [mDirectory] + */ + override fun onSetInitialValue(defaultValue: Any?) { + mDirectory = getPersistedString(defaultValue as String?) + } + + /** + * This [Preference.SummaryProvider] is used to set the summary for URI values + */ + private class SimpleSummaryProvider : SummaryProvider { + /** + * This returns the decoded URI of the directory as the summary + */ + 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 new file mode 100644 index 00000000..55904bf3 --- /dev/null +++ b/app/src/main/java/emu/skyline/preference/LicenseDialog.kt @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + */ + +package emu.skyline.preference + +import android.graphics.Rect +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.Window +import androidx.fragment.app.DialogFragment +import emu.skyline.R +import kotlinx.android.synthetic.main.license_dialog.* + +/** + * This dialog is used to display the contents of a license for a particular project + */ +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? { + val layout = layoutInflater.inflate(R.layout.license_dialog, container) + + val displayRectangle = Rect() + val window: Window = activity!!.window + window.decorView.getWindowVisibleDisplayFrame(displayRectangle) + + layout.minimumWidth = ((displayRectangle.width() * 0.9f).toInt()) + layout.minimumHeight = ((displayRectangle.height() * 0.9f).toInt()) + + return layout + } + + /** + * This sets the [license_url] and [license_content] based on arguments passed + */ + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + license_url.text = arguments?.getString("libraryUrl")!! + license_content.text = context?.getString(arguments?.getInt("libraryLicense")!!)!! + } +} diff --git a/app/src/main/java/emu/skyline/utility/LicensePreference.kt b/app/src/main/java/emu/skyline/preference/LicensePreference.kt similarity index 66% rename from app/src/main/java/emu/skyline/utility/LicensePreference.kt rename to app/src/main/java/emu/skyline/preference/LicensePreference.kt index 0a997ea4..0fb8b297 100644 --- a/app/src/main/java/emu/skyline/utility/LicensePreference.kt +++ b/app/src/main/java/emu/skyline/preference/LicensePreference.kt @@ -3,30 +3,49 @@ * Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) */ -package emu.skyline.utility +package emu.skyline.preference import android.content.Context import android.os.Bundle import android.util.AttributeSet -import android.util.Log import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.DialogFragment.STYLE_NORMAL import androidx.fragment.app.FragmentManager import androidx.preference.Preference import emu.skyline.R -import emu.skyline.SettingsActivity +/** + * This preference is used to show licenses and the source of a library + */ class LicensePreference : Preference { + /** + * The [FragmentManager] is used to show the [LicenseDialog] fragment + */ private val fragmentManager: FragmentManager + + /** + * The tag used by this preference when launching a corresponding fragment + */ private val mDialogFragmentTag = "LicensePreference" + + /** + * The URL of the library + */ private var libraryUrl: String? = null + + /** + * The contents of the license of this library + */ 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) { fragmentManager = (context as AppCompatActivity).supportFragmentManager for (i in 0 until attrs!!.attributeCount) { val attr = attrs.getAttributeName(i) + if (attr.equals("libraryUrl", ignoreCase = true)) libraryUrl = attrs.getAttributeValue(i) else if (attr.equals("libraryLicense", ignoreCase = true)) @@ -34,25 +53,26 @@ class LicensePreference : Preference { } } - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : this(context, attrs, defStyleAttr, R.style.LicenseDialogTheme) + 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?) : this(context, null) + /** + * The [LicenseDialog] fragment is shown using [fragmentManager] on click with [libraryUrl] and [libraryLicense] passed as arguments + */ override fun onClick() { if (fragmentManager.findFragmentByTag(mDialogFragmentTag) != null) return - val fragment = LicenseDialog() + val dialog = LicenseDialog() val bundle = Bundle(2) bundle.putString("libraryUrl", libraryUrl!!) bundle.putInt("libraryLicense", libraryLicense!!) - fragment.arguments = bundle + dialog.arguments = bundle - fragment.setStyle(STYLE_NORMAL, R.style.LicenseDialogTheme) - - fragment.show(fragmentManager, mDialogFragmentTag) + dialog.show(fragmentManager, mDialogFragmentTag) } } diff --git a/app/src/main/java/emu/skyline/utility/ThemePreference.kt b/app/src/main/java/emu/skyline/preference/ThemePreference.kt similarity index 82% rename from app/src/main/java/emu/skyline/utility/ThemePreference.kt rename to app/src/main/java/emu/skyline/preference/ThemePreference.kt index c62f14a7..7750d46f 100644 --- a/app/src/main/java/emu/skyline/utility/ThemePreference.kt +++ b/app/src/main/java/emu/skyline/preference/ThemePreference.kt @@ -3,13 +3,16 @@ * Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) */ -package emu.skyline.utility +package emu.skyline.preference import android.content.Context import android.util.AttributeSet import androidx.appcompat.app.AppCompatDelegate 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) @@ -17,6 +20,9 @@ class ThemePreference : ListPreference { constructor(context: Context?) : super(context) + /** + * This changes [AppCompatDelegate.sDefaultNightMode] based on what the user's selection is + */ override fun callChangeListener(newValue: Any?): Boolean { AppCompatDelegate.setDefaultNightMode(when ((newValue as String).toInt()) { 0 -> AppCompatDelegate.MODE_NIGHT_NO @@ -24,6 +30,7 @@ class ThemePreference : ListPreference { 2 -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else -> AppCompatDelegate.MODE_NIGHT_UNSPECIFIED }) + return super.callChangeListener(newValue) } } diff --git a/app/src/main/java/emu/skyline/utility/FolderPreference.kt b/app/src/main/java/emu/skyline/utility/FolderPreference.kt deleted file mode 100644 index 300aac35..00000000 --- a/app/src/main/java/emu/skyline/utility/FolderPreference.kt +++ /dev/null @@ -1,115 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-3.0-or-later - * Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) - */ - -package emu.skyline.utility - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.content.res.TypedArray -import android.net.Uri -import android.os.Parcel -import android.os.Parcelable -import android.text.TextUtils -import android.util.AttributeSet -import androidx.preference.Preference - -class FolderPreference : Preference { - private var mDirectory: String? = null - - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - summaryProvider = SimpleSummaryProvider.instance - } - - constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) { - summaryProvider = SimpleSummaryProvider.instance - } - - constructor(context: Context?) : super(context) { - summaryProvider = SimpleSummaryProvider.instance - } - - override fun onClick() { - val intent = Intent(context, FolderActivity::class.java) - (context as Activity).startActivityForResult(intent, 0) - } - - var directory: String? - get() = mDirectory - set(directory) { - val changed = !TextUtils.equals(mDirectory, directory) - if (changed) { - mDirectory = directory - persistString(directory) - if (changed) { - notifyChanged() - } - } - } - - override fun onGetDefaultValue(a: TypedArray, index: Int): Any { - return a.getString(index)!! - } - - override fun onSetInitialValue(defaultValue: Any?) { - directory = getPersistedString(defaultValue as String?) - } - - override fun onSaveInstanceState(): Parcelable { - val superState = super.onSaveInstanceState() - if (isPersistent) { - return superState - } - val myState = SavedState(superState) - myState.mDirectory = directory - return myState - } - - override fun onRestoreInstanceState(state: Parcelable?) { - if (state == null || state.javaClass != SavedState::class.java) { - super.onRestoreInstanceState(state) - return - } - val myState = state as SavedState - super.onRestoreInstanceState(myState.superState) - directory = myState.mDirectory - } - - internal class SavedState : BaseSavedState { - var mDirectory: String? = null - - constructor(source: Parcel) : super(source) { - mDirectory = source.readString() - } - - constructor(superState: Parcelable?) : super(superState) - - override fun writeToParcel(dest: Parcel, flags: Int) { - super.writeToParcel(dest, flags) - dest.writeString(mDirectory) - } - - override fun describeContents(): Int { - return 0 - } - } - - class SimpleSummaryProvider private constructor() : SummaryProvider { - override fun provideSummary(preference: FolderPreference): CharSequence { - return Uri.decode(preference.directory!!) - } - - companion object { - private var sSimpleSummaryProvider: SimpleSummaryProvider? = null - val instance: SimpleSummaryProvider? - get() { - if (sSimpleSummaryProvider == null) { - sSimpleSummaryProvider = SimpleSummaryProvider() - } - return sSimpleSummaryProvider - } - } - } -} diff --git a/app/src/main/java/emu/skyline/utility/LicenseDialog.kt b/app/src/main/java/emu/skyline/utility/LicenseDialog.kt deleted file mode 100644 index 32f09ed3..00000000 --- a/app/src/main/java/emu/skyline/utility/LicenseDialog.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-License-Identifier: LGPL-3.0-or-later - * Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) - */ - -package emu.skyline.utility - -import android.os.Bundle -import android.text.method.ScrollingMovementMethod -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment -import emu.skyline.R -import kotlinx.android.synthetic.main.license_dialog.* - -class LicenseDialog : DialogFragment() { - private var libraryUrl: String = "" - private var libraryLicense: String = "" - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - libraryUrl = arguments?.getString("libraryUrl")!! - libraryLicense = context?.getString(arguments?.getInt("libraryLicense")!!)!! - - return requireActivity().layoutInflater.inflate(R.layout.license_dialog, container) - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - - license_url.text = libraryUrl - license_content.text = libraryLicense - } -} diff --git a/app/src/main/res/layout/license_dialog.xml b/app/src/main/res/layout/license_dialog.xml index 36f066cc..42cd0a37 100644 --- a/app/src/main/res/layout/license_dialog.xml +++ b/app/src/main/res/layout/license_dialog.xml @@ -1,35 +1,32 @@ - + android:layout_height="wrap_content"> - + android:orientation="vertical" + android:paddingTop="10dp"> - + + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1" /> - - - + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 74b6539f..4a5d488f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,6 +39,7 @@ The size of the buffer used to store audio samples for ROMs using audren. A lower value will result in less latency but potentially increased audio stutter depending on the performance of the device Licenses + The license of Skyline (LGPLv3 or later) {fmt} We use libfmt for formatting strings (Custom License) oboe @@ -55,5 +56,6 @@ We use Android Material Components to have a consistent material design UI (Apache License 2.0) Kotlin Standard Library We use Kotlin Standard Library for accessing convenience functions in Kotlin (Apache License 2.0) - The license of Skyline (LGPLv3 or later) + Material Design Icons + We use Material Design Icons to have consistent iconography throughout the application diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 79a96a6a..20de3331 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -19,11 +19,11 @@ - - - - - - - - - - - +