mirror of
https://github.com/IllusionMan1212/NPS-Browser.git
synced 2026-10-24 02:12:37 +00:00
Change singleapp to fragment, put toolbar in activity, add search bar
This commit is contained in:
+5
-4
@@ -57,18 +57,19 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.core:core-ktx:1.3.2'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||||
implementation 'com.github.doyaaaaaken:kotlin-csv-jvm:0.11.1'
|
implementation 'com.github.doyaaaaaken:kotlin-csv-jvm:0.11.1'
|
||||||
|
implementation 'com.github.wrdlbrnft:sorted-list-adapter:0.3.0.27'
|
||||||
implementation "androidx.cardview:cardview:1.0.0"
|
implementation "androidx.cardview:cardview:1.0.0"
|
||||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
|
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
|
||||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
|
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.13'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
implementation 'com.google.android.material:material:1.2.1'
|
implementation 'com.google.android.material:material:1.2.1'
|
||||||
|
|||||||
@@ -18,18 +18,12 @@
|
|||||||
<activity android:name=".activities.SplashActivity" android:theme="@style/NPSTheme.Splash">
|
<activity android:name=".activities.SplashActivity" android:theme="@style/NPSTheme.Splash">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".activities.MainActivity"
|
<activity android:name=".activities.MainActivity"
|
||||||
android:configChanges="screenSize|screenLayout|keyboardHidden">
|
android:configChanges="screenSize|screenLayout|keyboardHidden|orientation">
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
|
||||||
android:name=".activities.SingleAppActivity"
|
|
||||||
android:screenOrientation="portrait"
|
|
||||||
tools:ignore="LockedOrientationActivity"
|
|
||||||
android:parentActivityName=".activities.MainActivity" />
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -1,5 +1,59 @@
|
|||||||
package com.illusionware.npsbrowser
|
package com.illusionware.npsbrowser
|
||||||
|
|
||||||
data class AppData(val titleID: String?, val region: String?, val title : String?, val link : String?,
|
import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
|
||||||
val license : String?, val contentID : String?, val lastDateTime: String?,
|
|
||||||
val fileSize : Number?, val sha256 : String?, val minFW : String?)
|
data class AppData(
|
||||||
|
val titleID: String?, val region: String?, val title: String?, val link: String?,
|
||||||
|
val license: String?, val contentID: String?, val lastDateTime: String?,
|
||||||
|
val fileSize: Number?, val sha256: String?, val minFW: String?
|
||||||
|
) : SortedListAdapter.ViewModel {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as AppData
|
||||||
|
|
||||||
|
if (titleID != other.titleID) return false
|
||||||
|
if (region != other.region) return false
|
||||||
|
if (title != other.title) return false
|
||||||
|
if (link != other.link) return false
|
||||||
|
if (license != other.license) return false
|
||||||
|
if (contentID != other.contentID) return false
|
||||||
|
if (lastDateTime != other.lastDateTime) return false
|
||||||
|
if (fileSize != other.fileSize) return false
|
||||||
|
if (sha256 != other.sha256) return false
|
||||||
|
if (minFW != other.minFW) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = titleID?.hashCode() ?: 0
|
||||||
|
result = 31 * result + (region?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (title?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (link?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (license?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (contentID?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (lastDateTime?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (fileSize?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (sha256?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (minFW?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any?> isSameModelAs(model: T): Boolean {
|
||||||
|
if (model is AppData) {
|
||||||
|
val other: AppData = model as AppData
|
||||||
|
return "${other.titleID} ${other.title}" == "$titleID $title"
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any?> isContentTheSameAs(model: T): Boolean {
|
||||||
|
if (model is AppData) {
|
||||||
|
val other: AppData = model as AppData
|
||||||
|
return title?.equals(other.title) ?: (other.title == null)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,18 +2,26 @@ package com.illusionware.npsbrowser.activities
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
import com.illusionware.npsbrowser.R
|
import com.illusionware.npsbrowser.R
|
||||||
import com.illusionware.npsbrowser.fragments.mainactivity.MainActivityFragment
|
import com.illusionware.npsbrowser.fragments.mainactivity.MainActivityFragment
|
||||||
|
|
||||||
class MainActivity : BaseActivity() {
|
class MainActivity : BaseActivity(), FragmentManager.OnBackStackChangedListener {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setTheme(R.style.NPSTheme)
|
setTheme(R.style.NPSTheme)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
setSupportActionBar(findViewById(R.id.toolbar))
|
||||||
|
supportFragmentManager.addOnBackStackChangedListener(this);
|
||||||
|
|
||||||
|
if (supportFragmentManager.backStackEntryCount > 0) {
|
||||||
|
showUpButton()
|
||||||
|
}
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
supportFragmentManager.beginTransaction()
|
supportFragmentManager.beginTransaction()
|
||||||
.replace(R.id.container, MainActivityFragment.newInstance())
|
.replace(R.id.container, MainActivityFragment())
|
||||||
.commitNow()
|
.commitNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,12 +36,20 @@ class MainActivity : BaseActivity() {
|
|||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showUpButton() {
|
override fun onBackStackChanged() {
|
||||||
|
// enable Up button only if there are entries on the backstack
|
||||||
|
if (supportFragmentManager.backStackEntryCount < 1) {
|
||||||
|
hideUpButton()
|
||||||
|
} else {
|
||||||
|
showUpButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showUpButton() {
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideUpButton() {
|
private fun hideUpButton() {
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(false)
|
supportActionBar!!.setDisplayHomeAsUpEnabled(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
package com.illusionware.npsbrowser.activities
|
|
||||||
|
|
||||||
import android.app.DownloadManager
|
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Environment
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.Toast
|
|
||||||
import com.illusionware.npsbrowser.AppData
|
|
||||||
import com.illusionware.npsbrowser.databinding.ActivitySingleAppBinding
|
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
class SingleAppActivity: BaseActivity() {
|
|
||||||
companion object {
|
|
||||||
lateinit var app : AppData
|
|
||||||
}
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
val binding = ActivitySingleAppBinding.inflate(layoutInflater)
|
|
||||||
setContentView(binding.root)
|
|
||||||
|
|
||||||
var downloadManager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
|
|
||||||
|
|
||||||
binding.singleAppTitle.text = "[${app.titleID}] ${app.title}"
|
|
||||||
if (app.fileSize != null) {
|
|
||||||
binding.singleAppSize.text = prettifySize()
|
|
||||||
} else {
|
|
||||||
binding.singleAppSizeTitle.visibility = View.INVISIBLE
|
|
||||||
}
|
|
||||||
binding.singleAppContentId.text = app.contentID
|
|
||||||
binding.singleAppFwVer.text = app.minFW
|
|
||||||
// TODO: get and set app icon
|
|
||||||
if (app.minFW.isNullOrBlank()) {
|
|
||||||
binding.singleAppFwVerTitle.visibility = View.INVISIBLE
|
|
||||||
}
|
|
||||||
if (app.license == "MISSING") {
|
|
||||||
binding.singleAppError.text = "Warning: No license was provided for this app."
|
|
||||||
}
|
|
||||||
if (app.link == "CART ONLY") {
|
|
||||||
binding.singleAppError.text = "CART ONLY GAME"
|
|
||||||
binding.singleAppDownloadButton.isEnabled = false
|
|
||||||
} else if (app.link == "MISSING") {
|
|
||||||
binding.singleAppError.text = "Warning: No download link was provided for this app."
|
|
||||||
binding.singleAppDownloadButton.isEnabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.singleAppContentId.setOnLongClickListener {
|
|
||||||
val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
val clipData = ClipData.newPlainText("Content ID", binding.singleAppContentId.text)
|
|
||||||
clipboardManager.setPrimaryClip(clipData)
|
|
||||||
Toast.makeText(this, "Content ID Copied to Clipboard!", Toast.LENGTH_SHORT).show()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.singleAppDownloadButton.setOnClickListener {
|
|
||||||
try {
|
|
||||||
var request = DownloadManager.Request(Uri.parse(app.link))
|
|
||||||
request.setTitle(app.title)
|
|
||||||
request.setDescription("Downloading...")
|
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
|
||||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, app.title + ".pkg") // TODO: set up preference for this
|
|
||||||
downloadManager.enqueue(request)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Toast.makeText(this, "An error occurred while downloading. please try again", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.singleAppDownloadButton.setOnLongClickListener {
|
|
||||||
val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
val clipData = ClipData.newPlainText("PKG URL", app.link)
|
|
||||||
clipboardManager.setPrimaryClip(clipData)
|
|
||||||
Toast.makeText(this, "PKG URL Copied to Clipboard", Toast.LENGTH_SHORT).show()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prettifySize(): String {
|
|
||||||
if (app.fileSize!!.toFloat() / (1024 * 1024 * 1024) > 1) {
|
|
||||||
return "%.1f GB".format(toGB(app.fileSize!!))
|
|
||||||
}
|
|
||||||
if (app.fileSize!!.toFloat() / (1024 * 1024) > 1) {
|
|
||||||
return "%.1f MB".format(toMB(app.fileSize!!))
|
|
||||||
}
|
|
||||||
if (app.fileSize!!.toFloat() / 1024 > 1) {
|
|
||||||
return "%.1f KB".format(toKB(app.fileSize!!))
|
|
||||||
}
|
|
||||||
return "${app.fileSize!!} Bytes";
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun toKB(size: Number): Number {
|
|
||||||
return size.toFloat() / 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun toMB(size: Number): Number {
|
|
||||||
return size.toFloat() / (1024 * 1024)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun toGB(size: Number): Number {
|
|
||||||
return size.toFloat() / (1024 * 1024 * 1024)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +1,73 @@
|
|||||||
package com.illusionware.npsbrowser.adapters
|
package com.illusionware.npsbrowser.adapters
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import com.github.wrdlbrnft.modularadapter.ModularAdapter
|
||||||
|
import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
|
||||||
import com.illusionware.npsbrowser.AppData
|
import com.illusionware.npsbrowser.AppData
|
||||||
import com.illusionware.npsbrowser.R
|
import com.illusionware.npsbrowser.R
|
||||||
import kotlin.collections.ArrayList
|
import com.illusionware.npsbrowser.activities.MainActivity
|
||||||
|
import com.illusionware.npsbrowser.fragments.SingleAppFragment
|
||||||
|
import com.illusionware.npsbrowser.fragments.mainactivity.MainActivityFragment
|
||||||
|
import java.util.Comparator
|
||||||
|
|
||||||
class AppAdapter(private val appsList: ArrayList<AppData>, val context : Context) : RecyclerView.Adapter<AppAdapter.ViewHolder>() {
|
private val comparator: Comparator<AppData> = SortedListAdapter.ComparatorBuilder<AppData>()
|
||||||
private final val LIST_ITEM = 0
|
.setOrderForModel(AppData::class.java) { a, b -> a.title?.compareTo(b.title!!)!! }
|
||||||
private final val GRID_ITEM = 1
|
.build()
|
||||||
var isSwitchView = true
|
|
||||||
|
|
||||||
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
class AppAdapter(val context: Context) : SortedListAdapter<AppData>(context, AppData::class.java, comparator) {
|
||||||
var appTitle: TextView = view.findViewById(R.id.appTitle)
|
private val LIST_ITEM = 0
|
||||||
var appRegion: TextView = view.findViewById(R.id.appRegion)
|
private val GRID_ITEM = 1
|
||||||
var appMinFW: TextView = view.findViewById(R.id.appMinFW)
|
private var isSwitchView = true
|
||||||
var appLastDate: TextView = view.findViewById(R.id.appLastDate)
|
|
||||||
|
inner class AppViewHolder(itemView: View) :
|
||||||
|
SortedListAdapter.ViewHolder<AppData?>(itemView) {
|
||||||
|
var appTitle: TextView = itemView.findViewById(R.id.appTitle)
|
||||||
|
var appRegion: TextView = itemView.findViewById(R.id.appRegion)
|
||||||
|
var appMinFW: TextView = itemView.findViewById(R.id.appMinFW)
|
||||||
|
var appLastDate: TextView = itemView.findViewById(R.id.appLastDate)
|
||||||
|
|
||||||
|
override fun performBind(item: AppData) {
|
||||||
|
appTitle.text = item.title
|
||||||
|
appTitle.isSelected = true
|
||||||
|
appRegion.text = item.region
|
||||||
|
appMinFW.text = item.minFW
|
||||||
|
appMinFW.background = null;
|
||||||
|
|
||||||
|
if (appMinFW.text.isNotBlank()) {
|
||||||
|
val drawable = ResourcesCompat.getDrawable(
|
||||||
|
context.resources,
|
||||||
|
R.drawable.rect_red,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
appMinFW.background = drawable;
|
||||||
|
}
|
||||||
|
appLastDate.text = item.lastDateTime
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup, viewType: Int): AppViewHolder {
|
||||||
return if (viewType == LIST_ITEM) {
|
return if (viewType == LIST_ITEM) {
|
||||||
ViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false))
|
AppViewHolder(
|
||||||
|
inflater.inflate(
|
||||||
|
R.layout.recycler_item_list,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
ViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.grid_item, parent, false))
|
AppViewHolder(
|
||||||
|
inflater.inflate(
|
||||||
|
R.layout.recycler_item_grid,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,34 +79,8 @@ class AppAdapter(private val appsList: ArrayList<AppData>, val context : Context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun toggleItemViewType(type: Int): Boolean {
|
fun toggleItemViewType(type: Int): Boolean {
|
||||||
isSwitchView = type == 0
|
isSwitchView = type == 0
|
||||||
return isSwitchView
|
return isSwitchView
|
||||||
}
|
}
|
||||||
|
}
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
||||||
holder.appTitle.text = appsList[position].title
|
|
||||||
holder.appTitle.isSelected = true
|
|
||||||
holder.appRegion.text = appsList[position].region
|
|
||||||
holder.appMinFW.text = appsList[position].minFW
|
|
||||||
holder.appMinFW.background = null;
|
|
||||||
|
|
||||||
if (holder.appMinFW.text.isNotBlank()) {
|
|
||||||
val drawable = ResourcesCompat.getDrawable(context.resources, R.drawable.rect_red, null)
|
|
||||||
holder.appMinFW.background = drawable;
|
|
||||||
}
|
|
||||||
holder.appLastDate.text = appsList[position].lastDateTime
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
|
||||||
return appsList.size
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateData(apps: ArrayList<AppData>) {
|
|
||||||
appsList.clear()
|
|
||||||
notifyDataSetChanged()
|
|
||||||
appsList.addAll(apps)
|
|
||||||
notifyDataSetChanged()
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,33 +1,23 @@
|
|||||||
package com.illusionware.npsbrowser.fragments
|
package com.illusionware.npsbrowser.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.*
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN
|
import androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.illusionware.npsbrowser.R
|
import com.illusionware.npsbrowser.R
|
||||||
import com.illusionware.npsbrowser.activities.BaseActivity
|
|
||||||
import com.illusionware.npsbrowser.activities.MainActivity
|
|
||||||
import com.illusionware.npsbrowser.fragments.mainactivity.MainActivityFragment
|
|
||||||
import kotlinx.android.synthetic.main.appbar.*
|
|
||||||
|
|
||||||
class SettingsFragment : Fragment() {
|
class SettingsFragment : Fragment() {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
if (activity!!.supportFragmentManager.backStackEntryCount < 1) {
|
|
||||||
(activity as MainActivity?)?.showUpButton()
|
|
||||||
MainActivityFragment().recyclerView?.adapter = MainActivityFragment().viewAdapter
|
|
||||||
}
|
|
||||||
PreferenceManager.setDefaultValues(context, R.xml.root_preferences, false);
|
PreferenceManager.setDefaultValues(context, R.xml.root_preferences, false);
|
||||||
activity?.supportFragmentManager
|
activity?.supportFragmentManager
|
||||||
?.beginTransaction()
|
?.beginTransaction()
|
||||||
?.replace(
|
?.replace(
|
||||||
R.id.prefs,
|
R.id.prefs,
|
||||||
SettingsFragment()
|
PrefsFragment()
|
||||||
)
|
)
|
||||||
?.setTransition(TRANSIT_FRAGMENT_OPEN)
|
?.setTransition(TRANSIT_FRAGMENT_OPEN)
|
||||||
?.commit()
|
?.commit()
|
||||||
@@ -42,24 +32,11 @@ class SettingsFragment : Fragment() {
|
|||||||
return inflater.inflate(R.layout.settings_fragment, container, false)
|
return inflater.inflate(R.layout.settings_fragment, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
class PrefsFragment : PreferenceFragmentCompat() {
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
(activity as BaseActivity?)!!.setSupportActionBar(toolbar)
|
|
||||||
(activity as BaseActivity?)!!.supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
|
||||||
//viewModel = ViewModelProviders.of(this).get(MainActivity2ViewModel::class.java)
|
|
||||||
// TODO: Use the ViewModel
|
|
||||||
}
|
|
||||||
|
|
||||||
class SettingsFragment : PreferenceFragmentCompat() {
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.root_preferences, rootKey)
|
setPreferencesFromResource(R.xml.root_preferences, rootKey)
|
||||||
PreferenceManager.setDefaultValues(context, R.xml.root_preferences, false);
|
PreferenceManager.setDefaultValues(context, R.xml.root_preferences, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
//(activity as BaseActivity?)!!.setSupportActionBar(toolbar)
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
package com.illusionware.npsbrowser.fragments
|
||||||
|
|
||||||
|
import android.app.DownloadManager
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context.CLIPBOARD_SERVICE
|
||||||
|
import android.content.Context.DOWNLOAD_SERVICE
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Environment
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.illusionware.npsbrowser.AppData
|
||||||
|
import com.illusionware.npsbrowser.R
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
|
class SingleAppFragment : Fragment() {
|
||||||
|
companion object {
|
||||||
|
lateinit var app : AppData
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState)
|
||||||
|
activity?.title = app.title
|
||||||
|
val view = inflater.inflate(R.layout.single_app_fragment, container, false)
|
||||||
|
val downloadManager = requireActivity().getSystemService(DOWNLOAD_SERVICE) as DownloadManager
|
||||||
|
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppTitle)?.text = "[${app.titleID}] ${app.title}"
|
||||||
|
if (app.fileSize != null) {
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppSize)?.text = prettifySize()
|
||||||
|
} else {
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppSizeTitle)?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppContentId)?.text = app.contentID
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppFwVer)?.text = app.minFW
|
||||||
|
// TODO: get and set app icon
|
||||||
|
if (app.minFW.isNullOrBlank()) {
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppFwVerTitle)?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
if (app.license == "MISSING") {
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppError)?.text = "Warning: No license was provided for this app."
|
||||||
|
}
|
||||||
|
if (app.link == "CART ONLY") {
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppError)?.text = "CART ONLY GAME"
|
||||||
|
view?.findViewById<Button>(R.id.singleAppDownloadButton)?.isEnabled = false
|
||||||
|
} else if (app.link == "MISSING") {
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppError)?.text = "Warning: No download link was provided for this app."
|
||||||
|
view?.findViewById<Button>(R.id.singleAppDownloadButton)?.isEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
view?.findViewById<TextView>(R.id.singleAppContentId)?.setOnLongClickListener {
|
||||||
|
val clipboardManager = requireActivity().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
val clipData = ClipData.newPlainText("Content ID", view?.findViewById<TextView>(R.id.singleAppContentId)?.text)
|
||||||
|
clipboardManager.setPrimaryClip(clipData)
|
||||||
|
Toast.makeText(requireContext(), "Content ID Copied to Clipboard!", Toast.LENGTH_SHORT).show()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
view?.findViewById<Button>(R.id.singleAppDownloadButton)?.setOnClickListener {
|
||||||
|
try {
|
||||||
|
var request = DownloadManager.Request(Uri.parse(app.link))
|
||||||
|
request.setTitle(app.title)
|
||||||
|
request.setDescription("Downloading...")
|
||||||
|
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||||
|
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, app.title + ".pkg") // TODO: set up preference for this
|
||||||
|
downloadManager.enqueue(request)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Toast.makeText(requireContext(), "An error occurred while downloading. please try again", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view?.findViewById<Button>(R.id.singleAppDownloadButton)?.setOnLongClickListener {
|
||||||
|
val clipboardManager = requireActivity().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
val clipData = ClipData.newPlainText("PKG URL", app.link)
|
||||||
|
clipboardManager.setPrimaryClip(clipData)
|
||||||
|
Toast.makeText(requireContext(), "PKG URL Copied to Clipboard", Toast.LENGTH_SHORT).show()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prettifySize(): String {
|
||||||
|
if (app.fileSize!!.toFloat() / (1024 * 1024 * 1024) > 1) {
|
||||||
|
return "%.1f GB".format(toGB(app.fileSize!!))
|
||||||
|
}
|
||||||
|
if (app.fileSize!!.toFloat() / (1024 * 1024) > 1) {
|
||||||
|
return "%.1f MB".format(toMB(app.fileSize!!))
|
||||||
|
}
|
||||||
|
if (app.fileSize!!.toFloat() / 1024 > 1) {
|
||||||
|
return "%.1f KB".format(toKB(app.fileSize!!))
|
||||||
|
}
|
||||||
|
return "${app.fileSize!!} Bytes";
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toKB(size: Number): Number {
|
||||||
|
return size.toFloat() / 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toMB(size: Number): Number {
|
||||||
|
return size.toFloat() / (1024 * 1024)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toGB(size: Number): Number {
|
||||||
|
return size.toFloat() / (1024 * 1024 * 1024)
|
||||||
|
}
|
||||||
|
}
|
||||||
+155
-92
@@ -6,12 +6,11 @@ import android.content.Intent
|
|||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.content.ContextCompat.checkSelfPermission
|
import androidx.core.content.ContextCompat.checkSelfPermission
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
|
||||||
import androidx.lifecycle.ViewModelProviders
|
import androidx.lifecycle.ViewModelProviders
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
@@ -22,21 +21,18 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton
|
|||||||
import com.illusionware.npsbrowser.AppData
|
import com.illusionware.npsbrowser.AppData
|
||||||
import com.illusionware.npsbrowser.R
|
import com.illusionware.npsbrowser.R
|
||||||
import com.illusionware.npsbrowser.RecyclerTouchListener
|
import com.illusionware.npsbrowser.RecyclerTouchListener
|
||||||
import com.illusionware.npsbrowser.activities.SingleAppActivity
|
import com.illusionware.npsbrowser.fragments.SingleAppFragment
|
||||||
import com.illusionware.npsbrowser.activities.MainActivity
|
|
||||||
import com.illusionware.npsbrowser.adapters.AppAdapter
|
import com.illusionware.npsbrowser.adapters.AppAdapter
|
||||||
import com.illusionware.npsbrowser.fragments.SettingsFragment
|
import com.illusionware.npsbrowser.fragments.SettingsFragment
|
||||||
import kotlinx.android.synthetic.main.appbar.*
|
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
class MainActivityFragment : Fragment(), FragmentManager.OnBackStackChangedListener {
|
class MainActivityFragment : Fragment() {
|
||||||
|
|
||||||
var recyclerView : RecyclerView? = null
|
var recyclerView : RecyclerView? = null
|
||||||
var viewAdapter: AppAdapter? = null
|
var viewAdapter: AppAdapter? = null
|
||||||
|
var filteredModelList: ArrayList<AppData>? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun newInstance() = MainActivityFragment()
|
|
||||||
var apps : ArrayList<AppData>? = arrayListOf()
|
var apps : ArrayList<AppData>? = arrayListOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,69 +47,15 @@ class MainActivityFragment : Fragment(), FragmentManager.OnBackStackChangedListe
|
|||||||
|
|
||||||
private lateinit var viewModel: MainActivityViewModel
|
private lateinit var viewModel: MainActivityViewModel
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
activity?.supportFragmentManager?.addOnBackStackChangedListener(this);
|
|
||||||
setHasOptionsMenu(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackStackChanged() {
|
|
||||||
// enable Up button only if there are entries on the backstack
|
|
||||||
if (requireActivity().supportFragmentManager.backStackEntryCount < 1) {
|
|
||||||
(activity as MainActivity?)?.hideUpButton()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
|
setHasOptionsMenu(true)
|
||||||
activity?.title = resources.getString(R.string.app_name)
|
activity?.title = resources.getString(R.string.app_name)
|
||||||
|
|
||||||
val view = inflater.inflate(R.layout.main_fragment, container, false)
|
val view = inflater.inflate(R.layout.main_fragment, container, false)
|
||||||
|
|
||||||
recyclerView = view?.findViewById(R.id.appsRecycler)
|
|
||||||
|
|
||||||
if (apps != null) {
|
|
||||||
viewAdapter = AppAdapter(apps!!, requireContext())
|
|
||||||
}
|
|
||||||
viewAdapter?.notifyDataSetChanged()
|
|
||||||
val orientation = this.resources.configuration.orientation
|
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
|
||||||
val isViewAsList = prefs.getString("layout_type", "0")
|
|
||||||
if (isViewAsList == "0") {
|
|
||||||
viewAdapter?.toggleItemViewType(0)
|
|
||||||
recyclerView?.layoutManager = LinearLayoutManager(context)
|
|
||||||
viewAdapter?.notifyDataSetChanged()
|
|
||||||
} else {
|
|
||||||
viewAdapter?.toggleItemViewType(1)
|
|
||||||
recyclerView?.layoutManager = GridLayoutManager(context,
|
|
||||||
if (orientation == Configuration.ORIENTATION_LANDSCAPE) 4 else 2)
|
|
||||||
viewAdapter?.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
recyclerView?.adapter = viewAdapter
|
|
||||||
|
|
||||||
recyclerView?.addOnItemTouchListener(RecyclerTouchListener(requireContext(), recyclerView!!, object : RecyclerTouchListener.ClickListener {
|
|
||||||
override fun onClick(view: View?, position: Int) {
|
|
||||||
val myIntent = Intent(context, SingleAppActivity::class.java)
|
|
||||||
SingleAppActivity.app = apps!![position]
|
|
||||||
|
|
||||||
startActivity(myIntent)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLongClick(view: View?, recyclerView: RecyclerView?, position: Int) {
|
|
||||||
Toast.makeText(context, "TODO: Long Click ", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
))
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
|
|
||||||
(activity as MainActivity?)!!.setSupportActionBar(toolbar)
|
|
||||||
|
|
||||||
view?.findViewById<FloatingActionButton>(R.id.tsvChooserButton)?.setOnClickListener {
|
view?.findViewById<FloatingActionButton>(R.id.tsvChooserButton)?.setOnClickListener {
|
||||||
if (!isStoragePermissionGranted())
|
if (!isStoragePermissionGranted())
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
@@ -125,35 +67,68 @@ class MainActivityFragment : Fragment(), FragmentManager.OnBackStackChangedListe
|
|||||||
}
|
}
|
||||||
viewModel = ViewModelProviders.of(this).get(MainActivityViewModel::class.java)
|
viewModel = ViewModelProviders.of(this).get(MainActivityViewModel::class.java)
|
||||||
// TODO: Use the ViewModel
|
// TODO: Use the ViewModel
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu : Menu, menuInflater : MenuInflater) {
|
recyclerView = view?.findViewById(R.id.appsRecycler)
|
||||||
menuInflater.inflate(R.menu.toolbar_main, menu)
|
|
||||||
super.onCreateOptionsMenu(menu, menuInflater)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
if (viewAdapter == null) {
|
||||||
return when (item.itemId) {
|
viewAdapter = AppAdapter(requireContext())
|
||||||
R.id.action_settings -> {
|
viewAdapter?.edit()?.add(apps!!)?.commit()
|
||||||
activity?.supportFragmentManager
|
|
||||||
?.beginTransaction()
|
|
||||||
?.replace(
|
|
||||||
R.id.container,
|
|
||||||
SettingsFragment()
|
|
||||||
)
|
|
||||||
?.addToBackStack("settings")
|
|
||||||
?.commit()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> return super.onOptionsItemSelected(item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (apps != null) {
|
||||||
|
filteredModelList = apps
|
||||||
|
}
|
||||||
|
viewAdapter?.notifyDataSetChanged()
|
||||||
|
|
||||||
|
recyclerView?.adapter = viewAdapter
|
||||||
|
|
||||||
|
val orientation = resources.configuration.orientation
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
val isViewAsList = prefs.getString("layout_type", "0")
|
||||||
|
if (isViewAsList == "0") {
|
||||||
|
viewAdapter?.toggleItemViewType(0)
|
||||||
|
recyclerView?.layoutManager = LinearLayoutManager(context)
|
||||||
|
viewAdapter?.notifyDataSetChanged()
|
||||||
|
} else {
|
||||||
|
viewAdapter?.toggleItemViewType(1)
|
||||||
|
recyclerView?.layoutManager = GridLayoutManager(
|
||||||
|
context,
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE) 4 else 2
|
||||||
|
)
|
||||||
|
viewAdapter?.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
recyclerView?.addOnItemTouchListener(RecyclerTouchListener(
|
||||||
|
requireContext(),
|
||||||
|
recyclerView!!,
|
||||||
|
object : RecyclerTouchListener.ClickListener {
|
||||||
|
override fun onClick(view: View?, position: Int) {
|
||||||
|
SingleAppFragment.app = filteredModelList!![position]
|
||||||
|
activity?.supportFragmentManager
|
||||||
|
?.beginTransaction()
|
||||||
|
?.replace(R.id.container,
|
||||||
|
SingleAppFragment()
|
||||||
|
)
|
||||||
|
?.addToBackStack("single app")
|
||||||
|
?.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick(
|
||||||
|
view: View?,
|
||||||
|
recyclerView: RecyclerView?,
|
||||||
|
position: Int
|
||||||
|
) {
|
||||||
|
Toast.makeText(context, "TODO: Long Click $position", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
))
|
||||||
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||||
super.onActivityResult(requestCode, resultCode, resultData)
|
super.onActivityResult(requestCode, resultCode, resultData)
|
||||||
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
|
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
|
||||||
resultData?.data?.also { uri ->
|
resultData?.data?.also { uri ->
|
||||||
Log.d("file_location", uri.toString())
|
|
||||||
val inputStream: InputStream? = activity?.contentResolver?.openInputStream(uri)
|
val inputStream: InputStream? = activity?.contentResolver?.openInputStream(uri)
|
||||||
val entries : List<Map<String, String?>> = tsvReader.readAllWithHeader(inputStream!!)
|
val entries : List<Map<String, String?>> = tsvReader.readAllWithHeader(inputStream!!)
|
||||||
apps?.clear()
|
apps?.clear()
|
||||||
@@ -176,15 +151,19 @@ class MainActivityFragment : Fragment(), FragmentManager.OnBackStackChangedListe
|
|||||||
val fileSize = entry["File Size"]?.toLongOrNull()
|
val fileSize = entry["File Size"]?.toLongOrNull()
|
||||||
val sha256 = entry["SHA256"]
|
val sha256 = entry["SHA256"]
|
||||||
val minFW = entry["Required FW"]
|
val minFW = entry["Required FW"]
|
||||||
val app = AppData(id, region, name, link ?: "MISSING", license ?: "MISSING",
|
val app = AppData(
|
||||||
|
id, region, name, link ?: "MISSING", license ?: "MISSING",
|
||||||
contentID ?: "MISSING", lastDateTime ?: "MISSING",
|
contentID ?: "MISSING", lastDateTime ?: "MISSING",
|
||||||
fileSize, sha256 ?: "MISSING", minFW)
|
fileSize, sha256 ?: "MISSING", minFW
|
||||||
|
)
|
||||||
apps?.add(app)
|
apps?.add(app)
|
||||||
}
|
}
|
||||||
apps?.sortBy { it.title }
|
apps?.sortBy { it.title }
|
||||||
|
filteredModelList = apps
|
||||||
|
|
||||||
recyclerView = view?.findViewById(R.id.appsRecycler)
|
recyclerView = view?.findViewById(R.id.appsRecycler)
|
||||||
viewAdapter = AppAdapter(apps!!, requireContext())
|
viewAdapter = AppAdapter(requireContext())
|
||||||
|
viewAdapter?.edit()?.add(apps!!)?.commit()
|
||||||
val orientation = this.resources.configuration.orientation
|
val orientation = this.resources.configuration.orientation
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
val isViewAsList = prefs.getString("layout_type", "0")
|
val isViewAsList = prefs.getString("layout_type", "0")
|
||||||
@@ -195,8 +174,10 @@ class MainActivityFragment : Fragment(), FragmentManager.OnBackStackChangedListe
|
|||||||
viewAdapter?.notifyDataSetChanged()
|
viewAdapter?.notifyDataSetChanged()
|
||||||
} else {
|
} else {
|
||||||
viewAdapter?.toggleItemViewType(1)
|
viewAdapter?.toggleItemViewType(1)
|
||||||
recyclerView?.layoutManager = GridLayoutManager(context,
|
recyclerView?.layoutManager = GridLayoutManager(
|
||||||
if (orientation == Configuration.ORIENTATION_LANDSCAPE) 4 else 2)
|
context,
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE) 4 else 2
|
||||||
|
)
|
||||||
viewAdapter?.notifyDataSetChanged()
|
viewAdapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,14 +186,96 @@ class MainActivityFragment : Fragment(), FragmentManager.OnBackStackChangedListe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||||
|
menuInflater.inflate(R.menu.main, menu)
|
||||||
|
|
||||||
|
val searchItem = menu.findItem(R.id.action_search)
|
||||||
|
val searchView: SearchView = searchItem.actionView as SearchView
|
||||||
|
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onQueryTextChange(query: String): Boolean {
|
||||||
|
filteredModelList = filter(apps!!, query) as ArrayList<AppData>?
|
||||||
|
viewAdapter?.edit()?.replaceAll(filteredModelList!!)?.commit()
|
||||||
|
recyclerView?.scrollToPosition(0)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
super.onCreateOptionsMenu(menu, menuInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.action_settings -> {
|
||||||
|
activity?.supportFragmentManager
|
||||||
|
?.beginTransaction()
|
||||||
|
?.replace(
|
||||||
|
R.id.container,
|
||||||
|
SettingsFragment()
|
||||||
|
)
|
||||||
|
?.addToBackStack("settings")
|
||||||
|
?.commit()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
R.id.action_search -> {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
viewAdapter?.edit()?.replaceAll(apps!!)?.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
|
super.onConfigurationChanged(newConfig)
|
||||||
|
val orientation = newConfig.orientation
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
val isViewAsList = prefs.getString("layout_type", "0")
|
||||||
|
if (isViewAsList == "0") {
|
||||||
|
val pos = (recyclerView?.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
|
||||||
|
viewAdapter?.toggleItemViewType(0)
|
||||||
|
recyclerView?.layoutManager = LinearLayoutManager(context)
|
||||||
|
(recyclerView?.layoutManager as LinearLayoutManager).scrollToPosition(pos)
|
||||||
|
viewAdapter?.notifyDataSetChanged()
|
||||||
|
} else {
|
||||||
|
val pos = (recyclerView?.layoutManager as GridLayoutManager).findFirstVisibleItemPosition()
|
||||||
|
viewAdapter?.toggleItemViewType(1)
|
||||||
|
recyclerView?.layoutManager = GridLayoutManager(
|
||||||
|
context,
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE) 4 else 2
|
||||||
|
)
|
||||||
|
(recyclerView?.layoutManager as GridLayoutManager).scrollToPosition(pos)
|
||||||
|
viewAdapter?.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun isStoragePermissionGranted(): Boolean {
|
private fun isStoragePermissionGranted(): Boolean {
|
||||||
return if (checkSelfPermission(this.context!!, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
return if (checkSelfPermission(
|
||||||
Log.v("perms", "Permission is granted")
|
this.requireContext(),
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
|
) == PackageManager.PERMISSION_GRANTED) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
Log.v("perms", "Permission is revoked")
|
|
||||||
requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)
|
requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun filter(models: List<AppData>, query: String): List<AppData>? {
|
||||||
|
val lowerCaseQuery = query.toLowerCase()
|
||||||
|
val filteredModelList: MutableList<AppData> = ArrayList()
|
||||||
|
for (model in models) {
|
||||||
|
val title: String = model.title?.toLowerCase()!!
|
||||||
|
val id: String = model.titleID?.toLowerCase()!!
|
||||||
|
if (title.contains(lowerCaseQuery) || id.contains(lowerCaseQuery)) {
|
||||||
|
filteredModelList.add(model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filteredModelList
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
|
||||||
|
</vector>
|
||||||
@@ -1,7 +1,31 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/container"
|
android:id="@+id/main"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".activities.MainActivity" />
|
android:clipChildren="false">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/include"
|
||||||
|
layout="@layout/appbar"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="56dp"
|
||||||
|
android:background="@color/colorAmoled"
|
||||||
|
android:backgroundTint="@color/colorAmoled"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/include"
|
||||||
|
tools:context=".activities.MainActivity" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
style="@style/Widget.MaterialComponents.Toolbar.Primary"
|
style="@style/Widget.MaterialComponents.Toolbar.Primary"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="@color/colorAmoled"
|
||||||
android:theme="@style/NPSTheme.ActionBar"
|
android:theme="@style/NPSTheme.ActionBar"
|
||||||
app:layout_scrollFlags="scroll|enterAlways|snap" />
|
app:layout_scrollFlags="scroll|enterAlways|snap" />
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
@@ -7,8 +7,6 @@
|
|||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
tools:context=".fragments.mainactivity.MainActivityFragment">
|
tools:context=".fragments.mainactivity.MainActivityFragment">
|
||||||
|
|
||||||
<include layout="@layout/appbar" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/appsRecycler"
|
android:id="@+id/appsRecycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -21,18 +19,21 @@
|
|||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
app:spanCount="2"
|
app:spanCount="2"
|
||||||
tools:listitem="@layout/grid_item" />
|
tools:listitem="@layout/recycler_item_grid" />
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/tsvChooserButton"
|
android:id="@+id/tsvChooserButton"
|
||||||
android:layout_width="52dp"
|
android:layout_width="52dp"
|
||||||
android:layout_height="52dp"
|
android:layout_height="52dp"
|
||||||
android:layout_marginBottom="40dp"
|
android:layout_marginBottom="40dp"
|
||||||
|
android:backgroundTint="@color/colorPrimary"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:src="@drawable/ic_add_yellow_24dp"
|
android:src="@drawable/ic_add_24dp"
|
||||||
|
app:borderWidth="2dp"
|
||||||
app:fabCustomSize="52dp"
|
app:fabCustomSize="52dp"
|
||||||
app:layout_anchor="@+id/appsRecycler"
|
app:layout_anchor="@+id/appsRecycler"
|
||||||
app:layout_anchorGravity="bottom|center"
|
app:layout_anchorGravity="bottom|center"
|
||||||
app:maxImageSize="32dp" />
|
app:maxImageSize="32dp" />
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|||||||
+2
-1
@@ -15,6 +15,7 @@
|
|||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="214dp"
|
android:layout_height="214dp"
|
||||||
|
android:backgroundTint="@color/colorAmoled"
|
||||||
app:cardBackgroundColor="@color/colorPrimary"
|
app:cardBackgroundColor="@color/colorPrimary"
|
||||||
app:cardElevation="4dp"
|
app:cardElevation="4dp"
|
||||||
app:cardUseCompatPadding="false"
|
app:cardUseCompatPadding="false"
|
||||||
@@ -34,7 +35,7 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:srcCompat="@drawable/ic_games_black_24dp" />
|
app:srcCompat="@drawable/ic_games_placeholder_24dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/appTitle"
|
android:id="@+id/appTitle"
|
||||||
+2
-1
@@ -15,6 +15,7 @@
|
|||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:backgroundTint="@color/colorAmoled"
|
||||||
app:cardBackgroundColor="@color/colorPrimary"
|
app:cardBackgroundColor="@color/colorPrimary"
|
||||||
app:cardElevation="4dp"
|
app:cardElevation="4dp"
|
||||||
app:cardUseCompatPadding="false"
|
app:cardUseCompatPadding="false"
|
||||||
@@ -32,7 +33,7 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:srcCompat="@drawable/ic_games_black_24dp" />
|
app:srcCompat="@drawable/ic_games_placeholder_24dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/appTitle"
|
android:id="@+id/appTitle"
|
||||||
@@ -7,24 +7,14 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipChildren="false">
|
android:clipChildren="false">
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/include"
|
|
||||||
layout="@layout/appbar"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/prefs"
|
android:id="@+id/prefs"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginTop="56dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/include">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -173,7 +173,7 @@
|
|||||||
android:layout_marginTop="30dp"
|
android:layout_marginTop="30dp"
|
||||||
android:layout_marginEnd="141dp"
|
android:layout_marginEnd="141dp"
|
||||||
android:contentDescription="Single app icon"
|
android:contentDescription="Single app icon"
|
||||||
app:srcCompat="@drawable/ic_games_black_24dp" />
|
app:srcCompat="@drawable/ic_games_placeholder_24dp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_search"
|
||||||
|
android:icon="@drawable/ic_search_24dp"
|
||||||
|
android:title="@string/search"
|
||||||
|
app:iconTint="?attr/colorOnPrimary"
|
||||||
|
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||||
|
app:showAsAction="always" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_settings"
|
android:id="@+id/action_settings"
|
||||||
android:icon="@drawable/ic_settings"
|
android:icon="@drawable/ic_settings"
|
||||||
@@ -6,5 +6,6 @@
|
|||||||
<color name="colorSecondary">#696969</color>
|
<color name="colorSecondary">#696969</color>
|
||||||
<color name="colorSecondaryDark">#515151</color>
|
<color name="colorSecondaryDark">#515151</color>
|
||||||
<color name="colorOnSecondary">#DFFFFFFF</color>
|
<color name="colorOnSecondary">#DFFFFFFF</color>
|
||||||
|
<color name="colorAmoled">#000000</color>
|
||||||
<color name="colorAccent">#F93422</color>
|
<color name="colorAccent">#F93422</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -6,5 +6,6 @@
|
|||||||
<color name="colorSecondary">#999999</color>
|
<color name="colorSecondary">#999999</color>
|
||||||
<color name="colorSecondaryDark">#888888</color>
|
<color name="colorSecondaryDark">#888888</color>
|
||||||
<color name="colorOnSecondary">#111111</color>
|
<color name="colorOnSecondary">#111111</color>
|
||||||
|
<color name="colorAmoled">#FFFFFF</color>
|
||||||
<color name="colorAccent">#F93422</color>
|
<color name="colorAccent">#F93422</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">NPS Browser</string>
|
<string name="app_name">NPS Browser</string>
|
||||||
<string name="title_activity_settings">Settings</string>
|
<string name="title_activity_settings">Settings</string>
|
||||||
|
<string name="search">Search</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<item name="colorSecondaryVariant">@color/colorSecondaryDark</item>
|
<item name="colorSecondaryVariant">@color/colorSecondaryDark</item>
|
||||||
<item name="colorOnSecondary">@color/colorOnSecondary</item>
|
<item name="colorOnSecondary">@color/colorOnSecondary</item>
|
||||||
|
|
||||||
<item name="android:statusBarColor">@color/colorPrimary</item>
|
<item name="android:statusBarColor">@color/colorAmoled</item>
|
||||||
<item name="alertDialogTheme">@style/NPSTheme.AlertDialog</item>
|
<item name="alertDialogTheme">@style/NPSTheme.AlertDialog</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
<PreferenceCategory android:title="Customization">
|
<PreferenceCategory android:title="Appearance">
|
||||||
|
|
||||||
<com.illusionware.npsbrowser.ThemePreference
|
<com.illusionware.npsbrowser.ThemePreference
|
||||||
android:defaultValue="2"
|
android:defaultValue="2"
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.72'
|
ext.kotlin_version = '1.4.10'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
|||||||
Reference in New Issue
Block a user