Add edge cases to detect MIUI & Huawei devices to select correct installer and apply spoof
This commit is contained in:
@@ -3,14 +3,14 @@
|
||||
"id": "0",
|
||||
"title": "Session installer",
|
||||
"subtitle": "Session based installer for bundled/split APKs",
|
||||
"description": "Best suited for devices running Android 5.0+.",
|
||||
"description": "Best suited for devices running Android 5.0+",
|
||||
"url": "https://developer.android.com/reference/android/content/pm/PackageInstaller.Session"
|
||||
},
|
||||
{
|
||||
"id": "1",
|
||||
"title": "Native installer",
|
||||
"subtitle": "Intent based installer, available on all devices",
|
||||
"description": "Best suited for devices running below Android 4.4 or OEM modified ROMs like MIUI, One-UI.",
|
||||
"description": "Best suited for devices running below Android 4.4",
|
||||
"url": "https://developer.android.com/reference/android/content/Intent#setDataAndType"
|
||||
},
|
||||
{
|
||||
|
||||
63
app/src/main/java/com/aurora/extensions/Dialog.kt
Normal file
63
app/src/main/java/com/aurora/extensions/Dialog.kt
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.extensions
|
||||
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
fun Context.showDialog(@StringRes titleId: Int, @StringRes messageId: Int) {
|
||||
runOnUiThread {
|
||||
val backgroundColor: Int = getStyledAttributeColor(android.R.attr.colorBackground)
|
||||
val builder = MaterialAlertDialogBuilder(this).apply {
|
||||
setTitle(titleId)
|
||||
setMessage(messageId)
|
||||
setPositiveButton(android.R.string.ok) { dialog: DialogInterface, _ -> dialog.dismiss() }
|
||||
background = ColorDrawable(backgroundColor)
|
||||
}.create()
|
||||
|
||||
builder.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.showDialog(title: String, message: String) {
|
||||
runOnUiThread {
|
||||
val backgroundColor: Int = getStyledAttributeColor(android.R.attr.colorBackground)
|
||||
val builder = MaterialAlertDialogBuilder(this).apply {
|
||||
setTitle(title)
|
||||
setMessage(message)
|
||||
setPositiveButton(android.R.string.ok) { dialog: DialogInterface, _ -> dialog.dismiss() }
|
||||
background = ColorDrawable(backgroundColor)
|
||||
}.create()
|
||||
|
||||
builder.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun Fragment.showDialog(@StringRes titleId: Int, @StringRes messageId: Int) {
|
||||
requireContext().showDialog(titleId, messageId)
|
||||
}
|
||||
|
||||
fun Fragment.showDialog(title: String, message: String) {
|
||||
requireContext().showDialog(title, message)
|
||||
}
|
||||
@@ -19,7 +19,9 @@
|
||||
|
||||
package com.aurora.extensions
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import java.util.*
|
||||
|
||||
|
||||
fun isLAndAbove(): Boolean {
|
||||
@@ -48,4 +50,47 @@ fun isQAndAbove(): Boolean {
|
||||
|
||||
fun isRAndAbove(): Boolean {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
||||
}
|
||||
|
||||
fun isMIUI(): Boolean {
|
||||
return getSystemProperty("ro.miui.ui.version.name").isNotEmpty()
|
||||
}
|
||||
|
||||
fun isHuawei(): Boolean {
|
||||
return Build.MANUFACTURER.toLowerCase(Locale.getDefault()).contains("huawei")
|
||||
|| Build.HARDWARE.toLowerCase(Locale.getDefault()).contains("kirin")
|
||||
|| Build.HARDWARE.toLowerCase(Locale.getDefault()).contains("hi3")
|
||||
}
|
||||
|
||||
fun getMIUIVersion(): String {
|
||||
val version = getSystemProperty("ro.miui.ui.version.name")
|
||||
val versionCode = getSystemProperty("ro.miui.ui.version.code")
|
||||
return if (version.isNotEmpty() && versionCode.isNotEmpty())
|
||||
"$version.$versionCode"
|
||||
else
|
||||
"unknown"
|
||||
}
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
fun isMiuiOptimizationDisabled(): Boolean {
|
||||
if ("0" == getSystemProperty("persist.sys.miui_optimization")) {
|
||||
return true
|
||||
} else try {
|
||||
return Class.forName("android.miui.AppOpsUtils")
|
||||
.getDeclaredMethod("isXOptMode")
|
||||
.invoke(null) as Boolean
|
||||
} catch (e: java.lang.Exception) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
fun getSystemProperty(key: String): String {
|
||||
return try {
|
||||
Class.forName("android.os.SystemProperties")
|
||||
.getDeclaredMethod("get", String::class.java)
|
||||
.invoke(null, key) as String
|
||||
} catch (e: Exception) {
|
||||
""
|
||||
}
|
||||
}
|
||||
@@ -20,16 +20,15 @@
|
||||
package com.aurora.store.data.providers
|
||||
|
||||
import android.content.Context
|
||||
import com.aurora.store.data.SingletonHolder
|
||||
import com.aurora.store.util.Preferences
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.*
|
||||
|
||||
class SpoofProvider private constructor(var context: Context) {
|
||||
class SpoofProvider constructor(var context: Context) {
|
||||
|
||||
companion object : SingletonHolder<SpoofProvider, Context>(::SpoofProvider) {
|
||||
companion object {
|
||||
const val LOCALE_SPOOF_ENABLED = "LOCALE_SPOOF_ENABLED"
|
||||
const val LOCALE_SPOOF_LANG = "LOCALE_SPOOF_LANG"
|
||||
const val LOCALE_SPOOF_COUNTRY = "LOCALE_SPOOF_COUNTRY"
|
||||
|
||||
@@ -19,15 +19,13 @@
|
||||
|
||||
package com.aurora.store.view.ui.onboarding
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.StringRes
|
||||
import com.aurora.extensions.getStyledAttributeColor
|
||||
import com.aurora.extensions.runOnUiThread
|
||||
import com.aurora.extensions.isMIUI
|
||||
import com.aurora.extensions.isMiuiOptimizationDisabled
|
||||
import com.aurora.extensions.showDialog
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.data.installer.ServiceInstaller
|
||||
import com.aurora.store.data.model.Installer
|
||||
@@ -38,7 +36,7 @@ import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID
|
||||
import com.aurora.store.util.save
|
||||
import com.aurora.store.view.epoxy.views.preference.InstallerViewModel_
|
||||
import com.aurora.store.view.ui.commons.BaseFragment
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.aurora.store.view.ui.sheets.DeviceMiuiSheet
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import java.nio.charset.StandardCharsets
|
||||
@@ -94,10 +92,21 @@ class InstallerFragment : BaseFragment() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (isMIUI() && !isMiuiOptimizationDisabled()) {
|
||||
DeviceMiuiSheet.newInstance().show(childFragmentManager, DeviceMiuiSheet.TAG)
|
||||
}
|
||||
}
|
||||
|
||||
private fun save(installerId: Int) {
|
||||
when (installerId) {
|
||||
0 -> {
|
||||
if (isMIUI() && !isMiuiOptimizationDisabled()) {
|
||||
DeviceMiuiSheet.newInstance().show(childFragmentManager, DeviceMiuiSheet.TAG)
|
||||
}
|
||||
this.installerId = installerId
|
||||
save(PREFERENCE_INSTALLER_ID, installerId)
|
||||
}
|
||||
2 -> {
|
||||
if (checkRootAvailability()) {
|
||||
this.installerId = installerId
|
||||
@@ -150,20 +159,4 @@ class InstallerFragment : BaseFragment() {
|
||||
ServiceInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME
|
||||
)
|
||||
}
|
||||
|
||||
private fun showDialog(@StringRes titleId: Int, @StringRes messageId: Int) {
|
||||
runOnUiThread {
|
||||
val backgroundColor: Int =
|
||||
requireContext().getStyledAttributeColor(android.R.attr.colorBackground)
|
||||
|
||||
val builder = MaterialAlertDialogBuilder(requireContext()).apply {
|
||||
setTitle(titleId)
|
||||
setMessage(messageId)
|
||||
setPositiveButton(android.R.string.ok) { dialog: DialogInterface, _ -> dialog.dismiss() }
|
||||
background = ColorDrawable(backgroundColor)
|
||||
}.create()
|
||||
|
||||
builder.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,15 +19,12 @@
|
||||
|
||||
package com.aurora.store.view.ui.preferences
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.aurora.extensions.getStyledAttributeColor
|
||||
import com.aurora.extensions.runOnUiThread
|
||||
import com.aurora.extensions.showDialog
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.data.installer.ServiceInstaller
|
||||
@@ -36,7 +33,6 @@ import com.aurora.store.util.PackageUtil
|
||||
import com.aurora.store.util.Preferences
|
||||
import com.aurora.store.util.save
|
||||
import com.aurora.store.view.custom.preference.AuroraListPreference
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.topjohnwu.superuser.Shell
|
||||
|
||||
|
||||
@@ -109,20 +105,4 @@ class InstallationPreference : PreferenceFragmentCompat() {
|
||||
ServiceInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME
|
||||
)
|
||||
}
|
||||
|
||||
private fun showDialog(@StringRes titleId: Int, @StringRes messageId: Int) {
|
||||
runOnUiThread {
|
||||
val backgroundColor: Int =
|
||||
requireContext().getStyledAttributeColor(android.R.attr.colorBackground)
|
||||
|
||||
val builder = MaterialAlertDialogBuilder(requireContext()).apply {
|
||||
setTitle(titleId)
|
||||
setMessage(messageId)
|
||||
setPositiveButton(android.R.string.ok) { dialog: DialogInterface, _ -> dialog.dismiss() }
|
||||
background = ColorDrawable(backgroundColor)
|
||||
}.create()
|
||||
|
||||
builder.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.view.ui.sheets
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.aurora.extensions.load
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.gplayapi.DeviceManager
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.data.providers.SpoofProvider
|
||||
import com.aurora.store.databinding.SheetDeviceHuaweiBinding
|
||||
import com.bumptech.glide.load.resource.bitmap.CircleCrop
|
||||
import java.util.*
|
||||
|
||||
class DeviceHuaweiSheet : BaseBottomSheet() {
|
||||
|
||||
private lateinit var B: SheetDeviceHuaweiBinding
|
||||
|
||||
companion object {
|
||||
|
||||
const val TAG = "DeviceHuaweiSheet"
|
||||
|
||||
@JvmStatic
|
||||
fun newInstance(): DeviceHuaweiSheet {
|
||||
return DeviceHuaweiSheet().apply {
|
||||
arguments = Bundle().apply {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateContentView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
B = SheetDeviceHuaweiBinding.inflate(inflater, container, false)
|
||||
|
||||
inflateData()
|
||||
attachAction()
|
||||
|
||||
return B.root
|
||||
}
|
||||
|
||||
override fun onContentViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
||||
}
|
||||
|
||||
private fun inflateData() {
|
||||
B.imgIcon.load(R.drawable.ic_huawei_logo) {
|
||||
transform(CircleCrop())
|
||||
}
|
||||
}
|
||||
|
||||
private fun attachAction() {
|
||||
B.btnPrimary.setOnClickListener {
|
||||
applySpoof()
|
||||
}
|
||||
|
||||
B.btnSecondary.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun applySpoof() {
|
||||
val properties: Properties? = when (Build.VERSION.SDK_INT) {
|
||||
30, 29 -> DeviceManager.loadProperties("op_8_pro.properties")
|
||||
28 -> DeviceManager.loadProperties("nk_9.properties")
|
||||
27 -> DeviceManager.loadProperties("mi_8_se.properties")
|
||||
26 -> DeviceManager.loadProperties("op_3.properties")
|
||||
else -> DeviceManager.loadProperties("op_x.properties")
|
||||
}
|
||||
|
||||
properties?.let {
|
||||
SpoofProvider(requireContext()).setSpoofDeviceProperties(it)
|
||||
toast(R.string.toast_spoof_applied)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Aurora Store
|
||||
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
*
|
||||
* Aurora Store is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Aurora Store is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.aurora.store.view.ui.sheets
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.aurora.extensions.load
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.databinding.SheetDeviceMiuiBinding
|
||||
import com.bumptech.glide.load.resource.bitmap.CircleCrop
|
||||
|
||||
class DeviceMiuiSheet : BaseBottomSheet() {
|
||||
|
||||
private lateinit var B: SheetDeviceMiuiBinding
|
||||
|
||||
companion object {
|
||||
|
||||
const val TAG = "DeviceMiuiSheet"
|
||||
|
||||
@JvmStatic
|
||||
fun newInstance(): DeviceMiuiSheet {
|
||||
return DeviceMiuiSheet().apply {
|
||||
arguments = Bundle().apply {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateContentView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
B = SheetDeviceMiuiBinding.inflate(inflater, container, false)
|
||||
|
||||
inflateData()
|
||||
attachAction()
|
||||
|
||||
return B.root
|
||||
}
|
||||
|
||||
override fun onContentViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
||||
}
|
||||
|
||||
private fun inflateData() {
|
||||
B.imgIcon.load(R.drawable.ic_xiaomi_logo) {
|
||||
transform(CircleCrop())
|
||||
}
|
||||
}
|
||||
|
||||
private fun attachAction() {
|
||||
B.btnPrimary.setOnClickListener {
|
||||
openDeveloperSettings()
|
||||
}
|
||||
|
||||
B.btnSecondary.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun openDeveloperSettings() {
|
||||
try {
|
||||
startActivity(Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS))
|
||||
} catch (e: Exception) {
|
||||
toast(R.string.toast_developer_setting_failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,17 +23,15 @@ import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.aurora.extensions.*
|
||||
import com.aurora.store.MainActivity
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.data.AuthState
|
||||
import com.aurora.store.data.event.BusEvent
|
||||
import com.aurora.store.databinding.ActivitySplashBinding
|
||||
import com.aurora.extensions.hide
|
||||
import com.aurora.extensions.load
|
||||
import com.aurora.extensions.open
|
||||
import com.aurora.extensions.show
|
||||
import com.aurora.store.view.ui.commons.BaseActivity
|
||||
import com.aurora.store.view.ui.commons.BlacklistActivity
|
||||
import com.aurora.store.view.ui.sheets.DeviceHuaweiSheet
|
||||
import com.aurora.store.view.ui.spoof.SpoofActivity
|
||||
import com.aurora.store.viewmodel.auth.AuthViewModel
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||
@@ -91,6 +89,13 @@ class SplashActivity : BaseActivity() {
|
||||
AuthState.Unavailable -> {
|
||||
updateStatus("You need to login first")
|
||||
updateActionLayout(true)
|
||||
|
||||
if (isHuawei()) {
|
||||
runOnUiThread {
|
||||
DeviceHuaweiSheet.newInstance()
|
||||
.show(supportFragmentManager, DeviceHuaweiSheet.TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AuthState.SignedIn -> {
|
||||
|
||||
@@ -23,13 +23,13 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.data.providers.NativeDeviceInfoProvider
|
||||
import com.aurora.store.data.providers.SpoofDeviceProvider
|
||||
import com.aurora.store.data.providers.SpoofProvider
|
||||
import com.aurora.store.databinding.FragmentGenericRecyclerBinding
|
||||
import com.aurora.store.util.Log
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.store.view.epoxy.views.preference.DeviceViewModel_
|
||||
import com.aurora.store.view.ui.commons.BaseFragment
|
||||
import nl.komponents.kovenant.task
|
||||
@@ -68,7 +68,7 @@ class DeviceSpoofFragment : BaseFragment() {
|
||||
)
|
||||
|
||||
properties = NativeDeviceInfoProvider(requireContext()).getNativeDeviceProperties()
|
||||
spoofProvider = SpoofProvider.with(requireContext())
|
||||
spoofProvider = SpoofProvider(requireContext())
|
||||
|
||||
return B.root
|
||||
}
|
||||
@@ -91,21 +91,27 @@ class DeviceSpoofFragment : BaseFragment() {
|
||||
private fun updateController(locales: List<Properties>) {
|
||||
B.recycler.withModels {
|
||||
setFilterDuplicates(true)
|
||||
locales.forEach {
|
||||
add(
|
||||
DeviceViewModel_()
|
||||
.id(it.hashCode())
|
||||
.markChecked(properties == it)
|
||||
.checked { _, checked ->
|
||||
if (checked) {
|
||||
properties = it
|
||||
saveSelection(it)
|
||||
requestModelBuild()
|
||||
locales
|
||||
.sortedBy { it.getProperty("UserReadableName") }
|
||||
.forEach {
|
||||
add(
|
||||
DeviceViewModel_()
|
||||
.id(it.hashCode())
|
||||
.markChecked(
|
||||
properties.getProperty("UserReadableName") == it.getProperty(
|
||||
"UserReadableName"
|
||||
)
|
||||
)
|
||||
.checked { _, checked ->
|
||||
if (checked) {
|
||||
properties = it
|
||||
saveSelection(it)
|
||||
requestModelBuild()
|
||||
}
|
||||
}
|
||||
}
|
||||
.properties(it)
|
||||
)
|
||||
}
|
||||
.properties(it)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class LocaleSpoofFragment : BaseFragment() {
|
||||
)
|
||||
)
|
||||
|
||||
spoofProvider = SpoofProvider.with(requireContext())
|
||||
spoofProvider = SpoofProvider(requireContext())
|
||||
|
||||
return B.root
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ import java.net.UnknownHostException
|
||||
|
||||
class AuthViewModel(application: Application) : BaseAndroidViewModel(application) {
|
||||
|
||||
private val spoofProvider = SpoofProvider.with(getApplication())
|
||||
private val spoofProvider = SpoofProvider(getApplication())
|
||||
|
||||
val liveData: MutableLiveData<AuthState> = MutableLiveData()
|
||||
|
||||
|
||||
33
app/src/main/res/drawable/ic_huawei_logo.xml
Normal file
33
app/src/main/res/drawable/ic_huawei_logo.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<!--
|
||||
~ Aurora Store
|
||||
~ Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
~
|
||||
~ Aurora Store is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 2 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ Aurora Store is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="35.625"
|
||||
android:viewportHeight="36.227">
|
||||
<group>
|
||||
<clip-path android:pathData="m164.0107,-53.6458c0,-0 -20.3828,10.8985 -30.9205,17.9848L133.0903,-35.6573L132.9687,-35.3111 133.2155,-35.1343L133.2155,-35.1306c3.7716,0.0074 18.0551,0.0221 18.416,-0.0442 0,-0 1.8453,-0.07 4.1289,-0.9429 0,-0 5.0791,-1.6095 7.7126,-7.3626 0,-0 2.3573,-4.6887 0.5377,-10.1655" />
|
||||
</group>
|
||||
<path
|
||||
android:fillColor="#CF0A2C"
|
||||
android:pathData="m15.2113,-0.0002c-0.476,0.0421 -1.7622,0.3349 -1.7622,0.3349h-0.0005c-2.8991,0.7493 -3.5843,3.3802 -3.5843,3.3802 -0.1416,0.4424 -0.2059,0.8958 -0.2248,1.3229v0.5814c0.0385,0.8982 0.2382,1.5689 0.2382,1.5689 0.9684,4.294 5.7298,11.3496 6.7531,12.8318 0.0726,0.072 0.1307,0.046 0.1307,0.046 0.1104,-0.0305 0.1018,-0.1364 0.1018,-0.1364l0.0021,0.0005C18.4416,4.1757 15.2113,-0.0002 15.2113,-0.0002ZM20.4192,-0.0002c0,0 -3.2444,4.1781 -1.6671,19.9414h0.0021c0.0122,0.1001 0.0832,0.1209 0.0832,0.1209 0.1056,0.0409 0.1597,-0.0605 0.1597,-0.0605l0.0005,0.001c1.0496,-1.52 5.7838,-8.5372 6.7479,-12.8147 0,0 0.5227,-2.0703 0.0181,-3.4732 0,0 -0.7167,-2.6716 -3.6194,-3.3776 0,0 -0.8365,-0.2124 -1.725,-0.3374zM5.4542,4.7292c0,0 -2.7623,2.6218 -2.8996,5.4012h0.0011v0.4212c0.0021,0.0317 0.0037,0.0638 0.0057,0.0961 0.119,2.2413 1.8051,3.5677 1.8051,3.5677 2.7166,2.6477 9.2946,5.9905 10.8231,6.7489 0.0214,0.008 0.1004,0.0338 0.1468,-0.0248 0,0 0.0241,-0.0183 0.0351,-0.0512v-0.0698c-0.0011,-0.004 -0.0032,-0.008 -0.0052,-0.0124h0.0005c-4.186,-9.1445 -9.9126,-16.0771 -9.9126,-16.0771zM30.1695,4.7292c0,0 -5.7093,6.9108 -9.8935,16.0368l0.0016,-0.0005c0,0 -0.0494,0.1058 0.0305,0.1742 0,0 0.0238,0.018 0.0568,0.0253h0.0579c0.0104,-0.003 0.0216,-0.007 0.0326,-0.0145v0.001c1.57,-0.7792 8.0971,-4.1001 10.8009,-6.7355 0,0 1.7123,-1.375 1.802,-3.5827 0.1977,-3.0663 -2.8887,-5.904 -2.8887,-5.904zM35.3082,13.8078c0,0 -9.3079,4.9951 -14.1206,8.2414l0.0005,0.0005 0.0011,0.001c0,0 -0.0873,0.0572 -0.0569,0.1597 0,0 0.0457,0.0827 0.1121,0.0827v0.0005c1.7238,0.003 8.2468,0.0103 8.4103,-0.0202 0,0 0.8435,-0.0337 1.8857,-0.4341 0,0 2.3202,-0.7376 3.5254,-3.3719 0,0 0.5507,-1.1015 0.5586,-2.6489v-0.0656c-0.004,-0.5968 -0.0881,-1.2574 -0.3163,-1.9451zM0.3129,13.8311c-0.8469,2.6217 0.2932,4.7343 0.2951,4.7377 1.1881,2.5105 3.4561,3.2711 3.4561,3.2711 1.0471,0.4302 2.0944,0.4599 2.0944,0.4599 0.1635,0.0299 6.5127,0.003 8.214,-0.005 0.072,-0.0005 0.1116,-0.0729 0.1116,-0.0729 0.005,-0.008 0.0094,-0.016 0.0114,-0.0233v-0.0656c-0.0141,-0.0439 -0.0517,-0.0749 -0.0517,-0.0749l0.0011,-0.0005C9.6347,18.8124 0.313,13.8312 0.313,13.8312ZM14.1782,23.1008 L3.2285,23.4847c1.1875,2.1168 3.1873,3.7619 5.2705,3.2566 1.4376,-0.3594 4.6945,-2.6311 5.7697,-3.3988l-0.0036,-0.003c0.0836,-0.0751 0.0537,-0.1354 0.0537,-0.1354 -0.0275,-0.0983 -0.1406,-0.0982 -0.1406,-0.0982zM21.4305,23.1088 L21.4294,23.1128c0,0 -0.0961,0.0122 -0.123,0.0842 0,0 -0.0234,0.0984 0.0413,0.1473l-0.0011,0.001c1.0483,0.7518 4.2263,2.9736 5.7573,3.405 0,0 0.2319,0.0789 0.6206,0.093h0.2336c1.0258,-0.036 2.8127,-0.5629 4.4364,-3.3528z"
|
||||
android:strokeWidth="0.61020029"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
29
app/src/main/res/drawable/ic_xiaomi_logo.xml
Normal file
29
app/src/main/res/drawable/ic_xiaomi_logo.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<!--
|
||||
~ Aurora Store
|
||||
~ Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
~
|
||||
~ Aurora Store is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 2 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ Aurora Store is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<vector android:height="24dp" android:viewportHeight="52.917"
|
||||
android:viewportWidth="52.917" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<group>
|
||||
<clip-path android:pathData="M-196.1159,-54.5529L100.8861,-54.5529L100.8861,155.45L-196.1159,155.45Z"/>
|
||||
<path android:fillColor="#ff6700" android:fillType="evenOdd" android:pathData="m50.9016,52.9132l-48.8976,-0c-1.1095,-0 -2.0088,-0.8994 -2.0088,-2.009l0,-48.901c0,-1.1096 0.8993,-2.0084 2.0088,-2.0084l48.8976,-0c1.1095,-0 2.0088,0.8989 2.0088,2.0084l0,48.901c0,1.1096 -0.8993,2.009 -2.0088,2.009"/>
|
||||
<path android:fillColor="#fff" android:pathData="m41.488,16.6386l-4.163,-0c-0.1782,-0 -0.3226,0.1418 -0.3226,0.3165l0,18.9951c0,0.1732 0.1443,0.315 0.3226,0.315l4.163,-0c0.1767,-0 0.3231,-0.1418 0.3231,-0.315l0,-18.9951c0,-0.1747 -0.1463,-0.3165 -0.3231,-0.3165"/>
|
||||
<path android:fillColor="#fff" android:pathData="m27.2739,16.6386l-15.8573,-0c-0.1782,-0 -0.3216,0.1418 -0.3216,0.3165l0,18.9951c0,0.1732 0.1433,0.315 0.3216,0.315l4.164,-0c0.1772,-0 0.3241,-0.1418 0.3241,-0.315l0,-14.9084c0,-0.1722 0.1433,-0.315 0.3216,-0.315l8.9695,-0c2.5223,-0 3.2383,1.932 3.2383,3.1783l0,12.0451c0,0.1732 0.1448,0.315 0.3231,0.315l4.1614,-0c0.1772,-0 0.3226,-0.1418 0.3226,-0.315l0,-13.4752c0,-1.1116 -0.1337,-2.7098 -1.5678,-4.1167 -1.5004,-1.4686 -2.8692,-1.7198 -4.3994,-1.7198"/>
|
||||
<path android:fillColor="#fff" android:pathData="m24.3571,24.2045l-4.3716,-0c-0.1782,-0 -0.3246,0.1418 -0.3246,0.3155l0,11.4318c0,0.1727 0.1463,0.3145 0.3246,0.3145l4.3716,-0c0.1767,-0 0.3216,-0.1418 0.3216,-0.3145l0,-11.4318c0,-0.1737 -0.1448,-0.3155 -0.3216,-0.3155"/>
|
||||
</group>
|
||||
</vector>
|
||||
110
app/src/main/res/layout/sheet_device_huawei.xml
Normal file
110
app/src/main/res/layout/sheet_device_huawei.xml
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Aurora Store
|
||||
~ Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
~
|
||||
~ Aurora Store is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 2 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ Aurora Store is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="@drawable/divider"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding_large"
|
||||
android:showDividers="middle">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/img_icon"
|
||||
android:layout_width="@dimen/icon_size_category"
|
||||
android:layout_height="@dimen/icon_size_category"
|
||||
android:layout_centerVertical="true"
|
||||
tools:src="@drawable/ic_huawei_logo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="@dimen/margin_normal"
|
||||
android:layout_marginBottom="@dimen/margin_normal"
|
||||
android:layout_toEndOf="@id/img_icon"
|
||||
android:maxLines="1"
|
||||
android:text="@string/title_spoof_manager"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Aurora.SubTitle" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_line1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="3"
|
||||
android:text="@string/device_huawei_title"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Aurora.Line1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_line2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="10"
|
||||
android:text="@string/device_huawei_subtitle"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Aurora.Line2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_line3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_changelog"
|
||||
android:maxLines="10"
|
||||
android:text="@string/device_huawei_description"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Aurora.Line2" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="2">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_secondary"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/height_button"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/action_ignore" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_primary"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/height_button"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/action_apply" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
120
app/src/main/res/layout/sheet_device_miui.xml
Normal file
120
app/src/main/res/layout/sheet_device_miui.xml
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Aurora Store
|
||||
~ Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
||||
~
|
||||
~ Aurora Store is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 2 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ Aurora Store is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
||||
~
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="@drawable/divider"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding_large"
|
||||
android:showDividers="middle">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/img_icon"
|
||||
android:layout_width="@dimen/icon_size_category"
|
||||
android:layout_height="@dimen/icon_size_category"
|
||||
android:layout_centerVertical="true"
|
||||
tools:src="@drawable/ic_xiaomi_logo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="@dimen/margin_normal"
|
||||
android:layout_marginBottom="@dimen/margin_normal"
|
||||
android:layout_toEndOf="@id/img_icon"
|
||||
android:maxLines="1"
|
||||
android:text="@string/title_installer"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Aurora.SubTitle" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_line1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="3"
|
||||
android:text="@string/device_miui_title"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Aurora.Line1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_line2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="10"
|
||||
android:text="@string/device_miui_subtitle"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Aurora.Line2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_line3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_changelog"
|
||||
android:maxLines="10"
|
||||
android:text="@string/device_miui_description"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Aurora.Line2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_line4"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="10"
|
||||
android:text="@string/device_miui_extra"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Aurora.Line2"
|
||||
android:textColor="@color/colorRed" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="2">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_secondary"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/height_button"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/action_ignore" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_primary"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/height_button"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/action_disable" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -47,6 +47,7 @@
|
||||
|
||||
<string name="action_accounts">"Accounts"</string>
|
||||
<string name="action_all_reviews">"All reviews"</string>
|
||||
<string name="action_apply">"Apply"</string>
|
||||
<string name="action_ask">"Ask"</string>
|
||||
<string name="action_back">"Back"</string>
|
||||
<string name="action_blacklist">"Blacklist"</string>
|
||||
@@ -223,6 +224,15 @@
|
||||
<string name="menu_license">"License"</string>
|
||||
<string name="menu_terms">"Terms of service"</string>
|
||||
|
||||
<string name="device_huawei_title">"Huawei detected!"</string>
|
||||
<string name="device_huawei_subtitle">"You seem to be using a Huawei device, due to recent bans by Google you may not be able to login."</string>
|
||||
<string name="device_huawei_description">"We suggest you to use device spoof in case you have a recent Huawei device. Do you wish to apply spoof now?"</string>
|
||||
|
||||
<string name="device_miui_title">"MIUI detected!"</string>
|
||||
<string name="device_miui_subtitle">"Session installer can not install apps due to MIUI Optimizations."</string>
|
||||
<string name="device_miui_description">"Please, disable MIUI optimizations to allow installations, otherwise you can choose Root or Services installer."</string>
|
||||
<string name="device_miui_extra">"Optionally you can choose Native installer, but then you can not install bundled (split) APKs, so choice is yours."</string>
|
||||
|
||||
<string name="notification_channel_alert">"Quick notification"</string>
|
||||
<string name="notification_channel_general">"General notification"</string>
|
||||
<string name="notification_installation_auto">"Click to install"</string>
|
||||
@@ -312,4 +322,6 @@
|
||||
<string name="toast_apk_copy_success">"APK exported successfully"</string>
|
||||
<string name="toast_apk_whitelisted">"Whitelisted"</string>
|
||||
<string name="toast_clipboard_copied">"Copied to clipboard"</string>
|
||||
<string name="toast_developer_setting_failed">"Failed to open developer settings, make sure it is enabled from device settings."</string>
|
||||
<string name="toast_spoof_applied">"Device spoof applied successfully."</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user