Some changes (#1)

* Add copy zrif button

* Add zh-CN

* Update zh-CN

* Fix string

* Update zh-CN

* Downloading remove invalid characters

* Update zh-cn and sdk version

* Update dependencies

* Move namespace

* Support Asia game images

* Update README.md

* Restored

* Update README.md
This commit is contained in:
22
2023-02-14 05:17:14 +02:00
committed by GitHub
parent d71ca817ad
commit 764b1c7045
13 changed files with 188 additions and 118 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
NPS Client app for android written in kotlin. NPS Client app for android written in kotlin.
## Building ## Building
The application targets android 10 (API 29) with a minimum version of android 6 (API 23). The application targets android 13 (API 33) with a minimum version of android 6 (API 23).
1. Create a `keystore` using android studio: `Build > Generate Signed Bundle / APK > Next > Create new` 1. Create a `keystore` using android studio: `Build > Generate Signed Bundle / APK > Next > Create new`
2. Create a `keystore.properties` file in the root directory of the repo. 2. Create a `keystore.properties` file in the root directory of the repo.
+36 -33
View File
@@ -1,40 +1,41 @@
apply plugin: 'com.android.application' plugins {
apply plugin: 'kotlin-android' id 'com.android.application'
apply plugin: 'kotlin-android-extensions' id 'kotlin-android'
id 'kotlin-parcelize'
id 'kotlin-kapt'
}
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties() def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('keystore.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android { android {
compileSdkVersion 30 namespace 'com.illusionware.npsbrowser'
buildToolsVersion "29.0.3" compileSdkVersion 33
defaultConfig { defaultConfig {
applicationId "com.illusionware.npsbrowser" applicationId "com.illusionware.npsbrowser"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 30 targetSdkVersion 33
versionCode 1 versionCode 1
versionName "0.1.0" versionName "0.1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
dataBinding { buildFeatures {
enabled = true dataBinding = true
} viewBinding = true
viewBinding {
enabled = true
} }
signingConfigs { signingConfigs {
release { release {
storeFile file(keystoreProperties['storeFile']) keyAlias keystoreProperties['keyAlias']
storePassword keystoreProperties['storePassword']
keyAlias = keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword'] keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
} }
} }
@@ -45,10 +46,12 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_11
} }
buildToolsVersion '33.0.1'
} }
@@ -60,25 +63,25 @@ repositories {
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'androidx.core:core-ktx:1.6.0' implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0" implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'
implementation 'com.github.doyaaaaaken:kotlin-csv-jvm:0.11.1' implementation 'com.github.doyaaaaaken:kotlin-csv-jvm:1.8.0'
implementation 'com.github.wrdlbrnft:sorted-list-adapter:0.3.0.27' 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.5' implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5' implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
implementation 'androidx.preference:preference-ktx:1.1.1' implementation 'androidx.preference:preference-ktx:1.2.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.recyclerview:recyclerview:1.2.1'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'com.google.android.material:material:1.4.0' implementation 'com.google.android.material:material:1.8.0'
implementation 'com.github.bumptech.glide:glide:4.12.0' implementation 'com.github.bumptech.glide:glide:4.14.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
} }
+3 -3
View File
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools">
package="com.illusionware.npsbrowser">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -15,7 +14,8 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/NPSTheme"> android:theme="@style/NPSTheme">
<activity android:name=".activities.SplashActivity" android:theme="@style/NPSTheme.Splash"> <activity android:name=".activities.SplashActivity" android:theme="@style/NPSTheme.Splash"
android:exported="true">
<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" />
@@ -41,17 +41,17 @@ data class AppData(
return result return result
} }
override fun <T : Any?> isSameModelAs(model: T): Boolean { override fun <T : Any> isSameModelAs(model: T): Boolean {
if (model is AppData) { if (model is AppData) {
val other: AppData = model as AppData val other: AppData = model
return "${other.titleID} ${other.title}" == "$titleID $title" return "${other.titleID} ${other.title}" == "$titleID $title"
} }
return false return false
} }
override fun <T : Any?> isContentTheSameAs(model: T): Boolean { override fun <T : Any> isContentTheSameAs(model: T): Boolean {
if (model is AppData) { if (model is AppData) {
val other: AppData = model as AppData val other: AppData = model
return title?.equals(other.title) ?: (other.title == null) return title?.equals(other.title) ?: (other.title == null)
} }
return false return false
@@ -6,11 +6,11 @@ import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.ListPreference import androidx.preference.ListPreference
class ThemePreference : ListPreference { class ThemePreference : ListPreference {
constructor(context : Context?, attrs : AttributeSet?, defStyleAttr : Int) : super(context, attrs, defStyleAttr) constructor(context : Context?, attrs : AttributeSet?, defStyleAttr : Int) : super(context!!, attrs, defStyleAttr)
constructor(context : Context?, attrs : AttributeSet?) : super(context, attrs) constructor(context : Context?, attrs : AttributeSet?) : super(context!!, attrs)
constructor(context : Context?) : super(context) constructor(context : Context?) : super(context!!)
override fun callChangeListener(newValue : Any?) : Boolean { override fun callChangeListener(newValue : Any?) : Boolean {
AppCompatDelegate.setDefaultNightMode(when ((newValue as String).toInt()) { AppCompatDelegate.setDefaultNightMode(when ((newValue as String).toInt()) {
@@ -12,7 +12,7 @@ class SettingsFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
PreferenceManager.setDefaultValues(context, R.xml.root_preferences, false); PreferenceManager.setDefaultValues(requireContext(), R.xml.root_preferences, false)
activity?.supportFragmentManager activity?.supportFragmentManager
?.beginTransaction() ?.beginTransaction()
?.replace( ?.replace(
@@ -35,7 +35,7 @@ class SettingsFragment : Fragment() {
class PrefsFragment : PreferenceFragmentCompat() { class PrefsFragment : 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(requireContext(), R.xml.root_preferences, false)
} }
} }
@@ -53,43 +53,46 @@ class SingleAppFragment : Fragment() {
view?.findViewById<TextView>(R.id.singleAppFwVerTitle)?.visibility = View.INVISIBLE view?.findViewById<TextView>(R.id.singleAppFwVerTitle)?.visibility = View.INVISIBLE
} }
if (app.license == "MISSING") { if (app.license == "MISSING") {
view?.findViewById<TextView>(R.id.singleAppError)?.text = "Warning: No license was provided for this app." view?.findViewById<TextView>(R.id.singleAppError)?.text = getString(R.string.no_license)
view?.findViewById<Button>(R.id.singleAppCopyZRIFButton)?.isEnabled = false
} }
if (app.link == "CART ONLY") { if (app.link == "CART ONLY") {
view?.findViewById<TextView>(R.id.singleAppError)?.text = "CART ONLY GAME" view?.findViewById<TextView>(R.id.singleAppError)?.text = getString(R.string.cart_only)
view?.findViewById<Button>(R.id.singleAppDownloadButton)?.isEnabled = false view?.findViewById<Button>(R.id.singleAppDownloadButton)?.isEnabled = false
view?.findViewById<Button>(R.id.singleAppCopyZRIFButton)?.isEnabled = false
} else if (app.link == "MISSING") { } else if (app.link == "MISSING") {
view?.findViewById<TextView>(R.id.singleAppError)?.text = "Warning: No download link was provided for this app." view?.findViewById<TextView>(R.id.singleAppError)?.text = getString(R.string.no_download_link)
view?.findViewById<Button>(R.id.singleAppDownloadButton)?.isEnabled = false view?.findViewById<Button>(R.id.singleAppDownloadButton)?.isEnabled = false
view?.findViewById<Button>(R.id.singleAppCopyZRIFButton)?.isEnabled = false
} }
view?.findViewById<TextView>(R.id.singleAppContentId)?.setOnLongClickListener { view?.findViewById<TextView>(R.id.singleAppContentId)?.setOnLongClickListener {
val clipboardManager = requireActivity().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager val clipboardManager = requireActivity().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText( val clipData = ClipData.newPlainText(
"Content ID", "Content ID",
view?.findViewById<TextView>(R.id.singleAppContentId)?.text view.findViewById<TextView>(R.id.singleAppContentId)?.text
) )
clipboardManager.setPrimaryClip(clipData) clipboardManager.setPrimaryClip(clipData)
Toast.makeText(requireContext(), "Content ID Copied to Clipboard!", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), getString(R.string.content_id_copied), Toast.LENGTH_SHORT).show()
true true
} }
// click listener for the download button // click listener for the download button
view?.findViewById<Button>(R.id.singleAppDownloadButton)?.setOnClickListener { view?.findViewById<Button>(R.id.singleAppDownloadButton)?.setOnClickListener {
try { try {
var request = DownloadManager.Request(Uri.parse(app.link)) val request = DownloadManager.Request(Uri.parse(app.link))
request.setTitle(app.title) request.setTitle(app.title)
request.setDescription("Downloading...") request.setDescription(getString(R.string.downloading))
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalPublicDir( request.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS, Environment.DIRECTORY_DOWNLOADS,
app.title + ".pkg" app.title!!.replace("[\\\\/:*?\"<>|]".toRegex(), " ") + ".pkg"
) // TODO: set up preference for this ) // TODO: set up preference for this
downloadManager.enqueue(request) downloadManager.enqueue(request)
} catch (e: Exception) { } catch (e: Exception) {
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
"An error occurred while downloading. please try again", getString(R.string.download_error),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} }
@@ -100,10 +103,18 @@ class SingleAppFragment : Fragment() {
val clipboardManager = requireActivity().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager val clipboardManager = requireActivity().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText("PKG URL", app.link) val clipData = ClipData.newPlainText("PKG URL", app.link)
clipboardManager.setPrimaryClip(clipData) clipboardManager.setPrimaryClip(clipData)
Toast.makeText(requireContext(), "PKG URL Copied to Clipboard", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), getString(R.string.pkg_url_copied), Toast.LENGTH_SHORT).show()
true true
} }
// click listener for the copyzrifbutton button
view?.findViewById<Button>(R.id.singleAppCopyZRIFButton)?.setOnClickListener {
val clipboardManager = requireActivity().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText("zRIF", app.license)
clipboardManager.setPrimaryClip(clipData)
Toast.makeText(requireContext(),getString(R.string.zrif_copied),Toast.LENGTH_SHORT).show()
}
// set the height for the error text to 0 if there's no error so that the scrollview can take more space // set the height for the error text to 0 if there's no error so that the scrollview can take more space
if (view?.findViewById<TextView>(R.id.singleAppError)?.text.isNullOrEmpty()) { if (view?.findViewById<TextView>(R.id.singleAppError)?.text.isNullOrEmpty()) {
view?.findViewById<TextView>(R.id.singleAppError)?.layoutParams?.height = 0 view?.findViewById<TextView>(R.id.singleAppError)?.layoutParams?.height = 0
@@ -116,7 +127,7 @@ class SingleAppFragment : Fragment() {
circularProgressDrawable.centerRadius = 180f circularProgressDrawable.centerRadius = 180f
circularProgressDrawable.start() circularProgressDrawable.start()
val image : ImageView? = view?.findViewById<ImageView>(R.id.singleAppIcon) val image : ImageView? = view?.findViewById(R.id.singleAppIcon)
val iconURL = getImage(app.contentID!!) val iconURL = getImage(app.contentID!!)
if (iconURL != null) { if (iconURL != null) {
// TODO: make the options a requestOptions // TODO: make the options a requestOptions
@@ -137,7 +148,7 @@ class SingleAppFragment : Fragment() {
if (app.fileSize!!.toFloat() / 1024 > 1) { if (app.fileSize!!.toFloat() / 1024 > 1) {
return "%.1f KB".format(toKB(app.fileSize!!)) return "%.1f KB".format(toKB(app.fileSize!!))
} }
return "${app.fileSize!!} Bytes"; return "${app.fileSize!!} Bytes"
} }
private fun toKB(size: Number): Number { private fun toKB(size: Number): Number {
@@ -167,8 +178,12 @@ class SingleAppFragment : Fragment() {
return "$baseStoreURL/jp/ja/999/${contentID}/image" return "$baseStoreURL/jp/ja/999/${contentID}/image"
} }
"KP" -> { "KP" -> {
// korean(?) games // korean games
// TODO: do this return "$baseStoreURL/kr/ko/999/${contentID}/image"
}
"HP" -> {
// asia games
return "$baseStoreURL/HK/zh/999/${contentID}/image"
} }
} }
return null return null
@@ -25,6 +25,8 @@ import com.illusionware.npsbrowser.fragments.SingleAppFragment
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 java.io.InputStream import java.io.InputStream
import java.util.*
import kotlin.collections.ArrayList
class MainActivityFragment : Fragment() { class MainActivityFragment : Fragment() {
@@ -83,7 +85,7 @@ class MainActivityFragment : Fragment() {
recyclerView?.adapter = viewAdapter recyclerView?.adapter = viewAdapter
val orientation = resources.configuration.orientation val orientation = resources.configuration.orientation
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(requireContext())
val isViewAsList = prefs.getString("layout_type", "0") val isViewAsList = prefs.getString("layout_type", "0")
if (isViewAsList == "0") { if (isViewAsList == "0") {
viewAdapter?.toggleItemViewType(0) viewAdapter?.toggleItemViewType(0)
@@ -165,7 +167,7 @@ class MainActivityFragment : Fragment() {
viewAdapter = AppAdapter(requireContext()) viewAdapter = AppAdapter(requireContext())
viewAdapter?.edit()?.add(apps!!)?.commit() 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(requireContext())
val isViewAsList = prefs.getString("layout_type", "0") val isViewAsList = prefs.getString("layout_type", "0")
if (isViewAsList == "0") { if (isViewAsList == "0") {
@@ -234,7 +236,7 @@ class MainActivityFragment : Fragment() {
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
val orientation = newConfig.orientation val orientation = newConfig.orientation
val prefs = PreferenceManager.getDefaultSharedPreferences(context) val prefs = PreferenceManager.getDefaultSharedPreferences(requireContext())
val isViewAsList = prefs.getString("layout_type", "0") val isViewAsList = prefs.getString("layout_type", "0")
if (isViewAsList == "0") { if (isViewAsList == "0") {
val pos = (recyclerView?.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() val pos = (recyclerView?.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
@@ -267,11 +269,11 @@ class MainActivityFragment : Fragment() {
} }
private fun filter(models: List<AppData>, query: String): List<AppData>? { private fun filter(models: List<AppData>, query: String): List<AppData>? {
val lowerCaseQuery = query.toLowerCase() val lowerCaseQuery = query.lowercase(Locale.getDefault())
val filteredModelList: MutableList<AppData> = ArrayList() val filteredModelList: MutableList<AppData> = ArrayList()
for (model in models) { for (model in models) {
val title: String = model.title?.toLowerCase()!! val title: String = model.title?.lowercase(Locale.getDefault())!!
val id: String = model.titleID?.toLowerCase()!! val id: String = model.titleID?.lowercase(Locale.getDefault())!!
if (title.contains(lowerCaseQuery) || id.contains(lowerCaseQuery)) { if (title.contains(lowerCaseQuery) || id.contains(lowerCaseQuery)) {
filteredModelList.add(model) filteredModelList.add(model)
} }
+61 -47
View File
@@ -57,46 +57,59 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="Game Title" /> tools:text="Game Title" />
<TextView
android:id="@+id/singleAppContentIdTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginTop="19dp"
android:layout_marginEnd="48dp"
android:fontFamily="sans-serif-black"
android:text="Content ID"
android:textAlignment="center"
android:textSize="26sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/singleAppDownloadButton" />
<Button <Button
android:id="@+id/singleAppDownloadButton" android:id="@+id/singleAppDownloadButton"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="66dp" android:layout_height="66dp"
android:layout_marginStart="48dp" android:layout_marginStart="48dp"
android:layout_marginTop="9dp" android:layout_marginTop="12dp"
android:layout_marginEnd="48dp" android:layout_marginEnd="48dp"
android:text="Download" android:text="@string/download"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/singleAppTitle" /> app:layout_constraintTop_toBottomOf="@+id/singleAppTitle" />
<Button
android:id="@+id/singleAppCopyZRIFButton"
android:layout_width="0dp"
android:layout_height="66dp"
android:layout_marginStart="48dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="48dp"
android:text="@string/copy_zrif"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/singleAppDownloadButton" />
<TextView
android:id="@+id/singleAppContentIdTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="48dp"
android:fontFamily="sans-serif-black"
android:text="@string/content_id"
android:textAlignment="center"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/singleAppCopyZRIFButton" />
<TextView <TextView
android:id="@+id/singleAppContentId" android:id="@+id/singleAppContentId"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="48dp" android:layout_marginStart="48dp"
android:layout_marginTop="11dp" android:layout_marginTop="12dp"
android:layout_marginEnd="48dp" android:layout_marginEnd="48dp"
android:fontFamily="sans-serif-light" android:fontFamily="sans-serif-light"
android:textAlignment="center" android:textAlignment="center"
android:textSize="24sp" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
@@ -109,62 +122,62 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="48dp" android:layout_marginStart="48dp"
android:layout_marginTop="16dp" android:layout_marginTop="24dp"
android:layout_marginEnd="48dp" android:layout_marginEnd="48dp"
android:fontFamily="sans-serif-black" android:fontFamily="sans-serif-black"
android:text="Size" android:text="@string/size"
android:textAlignment="center" android:textAlignment="center"
android:textSize="26sp" android:textSize="24sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/singleAppContentId" /> app:layout_constraintTop_toBottomOf="@+id/singleAppContentId" />
<TextView
android:id="@+id/singleAppSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginTop="7dp"
android:layout_marginEnd="48dp"
android:fontFamily="sans-serif-light"
android:textAlignment="center"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/singleAppSizeTitle"
tools:text="Size" />
<TextView <TextView
android:id="@+id/singleAppFwVerTitle" android:id="@+id/singleAppFwVerTitle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="48dp" android:layout_marginStart="48dp"
android:layout_marginTop="12dp" android:layout_marginTop="24dp"
android:layout_marginEnd="48dp" android:layout_marginEnd="48dp"
android:fontFamily="sans-serif-black" android:fontFamily="sans-serif-black"
android:text="MinFW" android:text="@string/minfw"
android:textAlignment="center" android:textAlignment="center"
android:textSize="26sp" android:textSize="24sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/singleAppSize" /> app:layout_constraintTop_toBottomOf="@+id/singleAppSize" />
<TextView
android:id="@+id/singleAppSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="48dp"
android:fontFamily="sans-serif-light"
android:textAlignment="center"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/singleAppSizeTitle"
tools:text="Size" />
<TextView <TextView
android:id="@+id/singleAppFwVer" android:id="@+id/singleAppFwVer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="48dp" android:layout_marginStart="48dp"
android:layout_marginTop="8dp" android:layout_marginTop="12dp"
android:layout_marginEnd="48dp" android:layout_marginEnd="48dp"
android:fontFamily="sans-serif-light" android:fontFamily="sans-serif-light"
android:textAlignment="center" android:textAlignment="center"
android:textSize="24sp" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0" app:layout_constraintHorizontal_bias="1.0"
@@ -172,6 +185,7 @@
app:layout_constraintTop_toBottomOf="@+id/singleAppFwVerTitle" app:layout_constraintTop_toBottomOf="@+id/singleAppFwVerTitle"
tools:text="MinFW" /> tools:text="MinFW" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>
@@ -191,7 +205,7 @@
android:layout_marginStart="100dp" android:layout_marginStart="100dp"
android:layout_marginTop="0dp" android:layout_marginTop="0dp"
android:layout_marginEnd="100dp" android:layout_marginEnd="100dp"
android:contentDescription="Single app icon" android:contentDescription="@string/single_app_icon"
app:srcCompat="@drawable/ic_games_placeholder_24dp" /> app:srcCompat="@drawable/ic_games_placeholder_24dp" />
</LinearLayout> </LinearLayout>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">NPS Browser</string>
<string name="title_activity_settings">设置</string>
<string name="search">搜索</string>
<string name="download">下载</string>
<string name="copy_zrif">复制 zRIF</string>
<string name="content_id">内容ID</string>
<string name="size">大小</string>
<string name="minfw">最低固件</string>
<string name="single_app_icon">应用图标</string>
<string name="no_license">注意:这个内容没有提供授权</string>
<string name="cart_only">这个游戏只有实体卡</string>
<string name="no_download_link">注意:这个内容没有提供下载链接</string>
<string name="download_error">下载过程中发生错误,请重试</string>
<string name="pkg_url_copied">PKG 地址已复制到剪贴板</string>
<string name="zrif_copied">zRIF 已复制到剪贴板</string>
<string name="downloading">下载中...</string>
<string name="content_id_copied">内容ID 已复制到剪贴板</string>
</resources>
+14
View File
@@ -2,4 +2,18 @@
<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> <string name="search">Search</string>
<string name="download">Download</string>
<string name="copy_zrif">Copy zRIF</string>
<string name="content_id">Content ID</string>
<string name="size">Size</string>
<string name="minfw">MinFW</string>
<string name="single_app_icon">Single app icon</string>
<string name="no_license">Warning: No license was provided for this content.</string>
<string name="cart_only">CART ONLY GAME</string>
<string name="no_download_link">Warning: No download link was provided for this content.</string>
<string name="downloading">Downloading...</string>
<string name="download_error">An error occurred while downloading. please try again</string>
<string name="pkg_url_copied">PKG URL Copied to Clipboard</string>
<string name="zrif_copied">zRIF Copied to Clipboard</string>
<string name="content_id_copied">Content ID Copied to Clipboard</string>
</resources> </resources>
+4 -2
View File
@@ -1,14 +1,16 @@
// 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.4.10' ext {
kotlin_version = '1.8.10'
}
repositories { repositories {
google() google()
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.0' classpath 'com.android.tools.build:gradle:7.4.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
+1 -1
View File
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip