mirror of
https://github.com/whyorean/AuroraStore.git
synced 2026-05-19 05:46:58 -04:00
SpoofProvider: Refactor and adjust a bit
* Show default device on top under different category * Remove spoof configuration when default is selected Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -36,22 +36,22 @@ class SpoofProviderTest {
|
||||
|
||||
@Test
|
||||
fun testSpoofingDeviceLocale() {
|
||||
assertThat(spoofProvider.isLocaleSpoofEnabled()).isFalse()
|
||||
assertThat(spoofProvider.isLocaleSpoofEnabled).isFalse()
|
||||
|
||||
spoofProvider.setSpoofLocale(Locale.JAPAN)
|
||||
assertThat(spoofProvider.isLocaleSpoofEnabled()).isTrue()
|
||||
assertThat(spoofProvider.getSpoofLocale() == Locale.JAPAN).isTrue()
|
||||
assertThat(spoofProvider.isLocaleSpoofEnabled).isTrue()
|
||||
assertThat(spoofProvider.locale == Locale.JAPAN).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSpoofingDeviceProperties() {
|
||||
assertThat(spoofProvider.isDeviceSpoofEnabled()).isFalse()
|
||||
assertThat(spoofProvider.isDeviceSpoofEnabled).isFalse()
|
||||
|
||||
val properties = Properties().apply {
|
||||
setProperty("UserReadableName", "Test")
|
||||
}
|
||||
spoofProvider.setSpoofDeviceProperties(properties)
|
||||
assertThat(spoofProvider.isDeviceSpoofEnabled()).isTrue()
|
||||
assertThat(spoofProvider.getSpoofDeviceProperties() == properties).isTrue()
|
||||
assertThat(spoofProvider.isDeviceSpoofEnabled).isTrue()
|
||||
assertThat(spoofProvider.deviceProperties == properties).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,13 +32,10 @@ import com.aurora.store.data.model.Auth
|
||||
import com.aurora.store.util.Preferences
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_AUTH_DATA
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_DISPENSER_URLS
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_VENDING_VERSION
|
||||
import com.google.gson.Gson
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.Locale
|
||||
import java.util.Properties
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -72,24 +69,6 @@ class AuthProvider @Inject constructor(
|
||||
val isAnonymous: Boolean
|
||||
get() = AccountProvider.getAccountType(context) == AccountType.ANONYMOUS
|
||||
|
||||
private val properties: Properties
|
||||
get() {
|
||||
val currentProperties = if (spoofProvider.isDeviceSpoofEnabled()) {
|
||||
spoofProvider.getSpoofDeviceProperties()
|
||||
} else {
|
||||
NativeDeviceInfoProvider(context).getNativeDeviceProperties()
|
||||
}
|
||||
setVendingVersion(currentProperties)
|
||||
return currentProperties
|
||||
}
|
||||
|
||||
private val locale: Locale
|
||||
get() = if (spoofProvider.isLocaleSpoofEnabled()) {
|
||||
spoofProvider.getSpoofLocale()
|
||||
} else {
|
||||
Locale.getDefault()
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether saved AuthData is valid or not
|
||||
*/
|
||||
@@ -124,8 +103,8 @@ class AuthProvider @Inject constructor(
|
||||
email = email,
|
||||
token = token,
|
||||
tokenType = tokenType,
|
||||
properties = properties,
|
||||
locale = locale,
|
||||
properties = spoofProvider.deviceProperties,
|
||||
locale = spoofProvider.locale,
|
||||
)
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
@@ -153,8 +132,8 @@ class AuthProvider @Inject constructor(
|
||||
token = auth.auth,
|
||||
tokenType = AuthHelper.Token.AUTH,
|
||||
isAnonymous = true,
|
||||
properties = properties,
|
||||
locale = locale
|
||||
properties = spoofProvider.deviceProperties,
|
||||
locale = spoofProvider.locale
|
||||
)
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
@@ -178,18 +157,6 @@ class AuthProvider @Inject constructor(
|
||||
Preferences.remove(context, PREFERENCE_AUTH_DATA)
|
||||
}
|
||||
|
||||
private fun setVendingVersion(currentProperties: Properties) {
|
||||
val vendingVersionIndex = Preferences.getInteger(context, PREFERENCE_VENDING_VERSION)
|
||||
if (vendingVersionIndex > 0) {
|
||||
val resources = context.resources
|
||||
val versionCodes = resources.getStringArray(R.array.pref_vending_version_codes)
|
||||
val versionStrings = resources.getStringArray(R.array.pref_vending_version)
|
||||
|
||||
currentProperties.setProperty("Vending.version", versionCodes[vendingVersionIndex])
|
||||
currentProperties.setProperty("Vending.versionString", versionStrings[vendingVersionIndex])
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
private fun throwError(playResponse: PlayResponse, context: Context) {
|
||||
when (playResponse.code) {
|
||||
|
||||
@@ -26,12 +26,12 @@ import androidx.core.content.getSystemService
|
||||
import com.aurora.extensions.isHuawei
|
||||
import java.util.Properties
|
||||
|
||||
class NativeDeviceInfoProvider(val context: Context) {
|
||||
object NativeDeviceInfoProvider {
|
||||
|
||||
fun getNativeDeviceProperties(isExport: Boolean = false): Properties {
|
||||
fun getNativeDeviceProperties(context: Context, isExport: Boolean = false): Properties {
|
||||
val properties = Properties().apply {
|
||||
//Build Props
|
||||
setProperty("UserReadableName", "${Build.DEVICE}-default")
|
||||
setProperty("UserReadableName", "${Build.MANUFACTURER} ${Build.MODEL}")
|
||||
setProperty("Build.HARDWARE", Build.HARDWARE)
|
||||
setProperty(
|
||||
"Build.RADIO",
|
||||
@@ -71,11 +71,11 @@ class NativeDeviceInfoProvider(val context: Context) {
|
||||
//Supported Platforms
|
||||
setProperty("Platforms", Build.SUPPORTED_ABIS.joinToString(separator = ","))
|
||||
//Supported Features
|
||||
setProperty("Features", getFeatures().joinToString(separator = ","))
|
||||
setProperty("Features", getFeatures(context).joinToString(separator = ","))
|
||||
//Shared Locales
|
||||
setProperty("Locales", getLocales().joinToString(separator = ","))
|
||||
setProperty("Locales", getLocales(context).joinToString(separator = ","))
|
||||
//Shared Libraries
|
||||
setProperty("SharedLibraries", getSharedLibraries().joinToString(separator = ","))
|
||||
setProperty("SharedLibraries", getSharedLibraries(context).joinToString(separator = ","))
|
||||
//GL Extensions
|
||||
val activityManager = context.getSystemService<ActivityManager>()
|
||||
setProperty(
|
||||
@@ -104,27 +104,25 @@ class NativeDeviceInfoProvider(val context: Context) {
|
||||
setProperty("SimOperator", "38")
|
||||
}
|
||||
|
||||
if (isHuawei && !isExport)
|
||||
stripHuaweiProperties(properties)
|
||||
|
||||
if (isHuawei && !isExport) stripHuaweiProperties(properties)
|
||||
return properties
|
||||
}
|
||||
|
||||
private fun getFeatures(): List<String> {
|
||||
private fun getFeatures(context: Context): List<String> {
|
||||
return context
|
||||
.packageManager
|
||||
.systemAvailableFeatures
|
||||
?.mapNotNull { it.name } ?: emptyList()
|
||||
.mapNotNull { it.name }
|
||||
}
|
||||
|
||||
private fun getLocales(): List<String> {
|
||||
private fun getLocales(context: Context): List<String> {
|
||||
return context
|
||||
.assets
|
||||
.locales
|
||||
.mapNotNull { it.replace("-", "_") }
|
||||
}
|
||||
|
||||
private fun getSharedLibraries(): List<String> {
|
||||
private fun getSharedLibraries(context: Context): List<String> {
|
||||
return context
|
||||
.packageManager
|
||||
.systemSharedLibraryNames
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.content.Context
|
||||
import android.util.Log
|
||||
import com.aurora.store.BuildConfig
|
||||
import com.aurora.store.util.PathUtil
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
@@ -31,22 +30,26 @@ import java.io.IOException
|
||||
import java.util.Properties
|
||||
import java.util.jar.JarEntry
|
||||
import java.util.jar.JarFile
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Provider class to work with device spoof configs imported by users & shipped by GPlayAPI library
|
||||
*
|
||||
* Do not use this class directly. Consider using [SpoofProvider] instead.
|
||||
*/
|
||||
@Singleton
|
||||
class SpoofDeviceProvider @Inject constructor(@ApplicationContext val context: Context) {
|
||||
open class SpoofDeviceProvider(private val context: Context) {
|
||||
|
||||
private val TAG = SpoofDeviceProvider::class.java.simpleName
|
||||
|
||||
private val SUFFIX = ".properties"
|
||||
|
||||
val availableDevice: List<Properties>
|
||||
val availableDeviceProperties: MutableList<Properties>
|
||||
get() {
|
||||
val propertiesList: MutableList<Properties> = ArrayList()
|
||||
propertiesList.add(0, NativeDeviceInfoProvider(context).getNativeDeviceProperties())
|
||||
propertiesList.addAll(spoofDevicesFromApk)
|
||||
propertiesList.addAll(spoofDevicesFromUser)
|
||||
propertiesList.sortBy { it.getProperty("UserReadableName") }
|
||||
return propertiesList
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
package com.aurora.store.data.providers
|
||||
|
||||
import android.content.Context
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.util.Preferences
|
||||
import com.aurora.store.util.Preferences.PREFERENCE_VENDING_VERSION
|
||||
import com.google.gson.Gson
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import java.util.Locale
|
||||
@@ -28,50 +30,65 @@ import java.util.Properties
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Provider class to work with device and locale spoofs
|
||||
*/
|
||||
@Singleton
|
||||
class SpoofProvider @Inject constructor(
|
||||
private val gson: Gson,
|
||||
@ApplicationContext val context: Context,
|
||||
private val gson: Gson
|
||||
) {
|
||||
) : SpoofDeviceProvider(context) {
|
||||
|
||||
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"
|
||||
private const val LOCALE_SPOOF_ENABLED = "LOCALE_SPOOF_ENABLED"
|
||||
private const val LOCALE_SPOOF_LANG = "LOCALE_SPOOF_LANG"
|
||||
private const val LOCALE_SPOOF_COUNTRY = "LOCALE_SPOOF_COUNTRY"
|
||||
|
||||
const val DEVICE_SPOOF_ENABLED = "DEVICE_SPOOF_ENABLED"
|
||||
const val DEVICE_SPOOF_PROPERTIES = "DEVICE_SPOOF_PROPERTIES"
|
||||
private const val DEVICE_SPOOF_ENABLED = "DEVICE_SPOOF_ENABLED"
|
||||
private const val DEVICE_SPOOF_PROPERTIES = "DEVICE_SPOOF_PROPERTIES"
|
||||
}
|
||||
|
||||
fun isLocaleSpoofEnabled(): Boolean {
|
||||
return Preferences.getBoolean(context, LOCALE_SPOOF_ENABLED)
|
||||
val availableSpoofDeviceProperties get() = availableDeviceProperties
|
||||
val availableSpoofLocales = Locale.getAvailableLocales().toMutableList().apply {
|
||||
remove(Locale.getDefault())
|
||||
sortBy { it.displayName }
|
||||
}
|
||||
|
||||
fun isDeviceSpoofEnabled(): Boolean {
|
||||
return Preferences.getBoolean(context, DEVICE_SPOOF_ENABLED)
|
||||
}
|
||||
val deviceProperties: Properties
|
||||
get() {
|
||||
val currentProperties = if (isDeviceSpoofEnabled) {
|
||||
spoofDeviceProperties
|
||||
} else {
|
||||
NativeDeviceInfoProvider.getNativeDeviceProperties(context)
|
||||
}
|
||||
setVendingVersion(currentProperties)
|
||||
return currentProperties
|
||||
}
|
||||
|
||||
fun getSpoofLocale(): Locale {
|
||||
return if (isLocaleSpoofEnabled()) {
|
||||
Locale(
|
||||
Preferences.getString(context, LOCALE_SPOOF_LANG),
|
||||
Preferences.getString(context, LOCALE_SPOOF_COUNTRY)
|
||||
)
|
||||
val locale: Locale
|
||||
get() = if (isLocaleSpoofEnabled) {
|
||||
spoofLocale
|
||||
} else {
|
||||
Locale.getDefault()
|
||||
}
|
||||
}
|
||||
|
||||
fun getSpoofDeviceProperties(): Properties {
|
||||
return if (isDeviceSpoofEnabled()) {
|
||||
return gson.fromJson(
|
||||
Preferences.getString(context, DEVICE_SPOOF_PROPERTIES),
|
||||
Properties::class.java
|
||||
)
|
||||
} else {
|
||||
Properties()
|
||||
}
|
||||
}
|
||||
val isLocaleSpoofEnabled: Boolean
|
||||
get() = Preferences.getBoolean(context, LOCALE_SPOOF_ENABLED)
|
||||
|
||||
val isDeviceSpoofEnabled: Boolean
|
||||
get() = Preferences.getBoolean(context, DEVICE_SPOOF_ENABLED)
|
||||
|
||||
private val spoofLocale: Locale
|
||||
get() = Locale(
|
||||
Preferences.getString(context, LOCALE_SPOOF_LANG),
|
||||
Preferences.getString(context, LOCALE_SPOOF_COUNTRY)
|
||||
)
|
||||
|
||||
private val spoofDeviceProperties: Properties
|
||||
get() = gson.fromJson(
|
||||
Preferences.getString(context, DEVICE_SPOOF_PROPERTIES),
|
||||
Properties::class.java
|
||||
)
|
||||
|
||||
fun setSpoofLocale(locale: Locale) {
|
||||
Preferences.putBoolean(context, LOCALE_SPOOF_ENABLED, true)
|
||||
@@ -94,4 +111,16 @@ class SpoofProvider @Inject constructor(
|
||||
Preferences.remove(context, DEVICE_SPOOF_ENABLED)
|
||||
Preferences.remove(context, DEVICE_SPOOF_PROPERTIES)
|
||||
}
|
||||
|
||||
private fun setVendingVersion(currentProperties: Properties) {
|
||||
val vendingVersionIndex = Preferences.getInteger(context, PREFERENCE_VENDING_VERSION)
|
||||
if (vendingVersionIndex > 0) {
|
||||
val resources = context.resources
|
||||
val versionCodes = resources.getStringArray(R.array.pref_vending_version_codes)
|
||||
val versionStrings = resources.getStringArray(R.array.pref_vending_version)
|
||||
|
||||
currentProperties.setProperty("Vending.version", versionCodes[vendingVersionIndex])
|
||||
currentProperties.setProperty("Vending.versionString", versionStrings[vendingVersionIndex])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ class DeviceView @JvmOverloads constructor(
|
||||
@ModelProp
|
||||
fun markChecked(isChecked: Boolean) {
|
||||
binding.checkbox.isChecked = isChecked
|
||||
binding.checkbox.isEnabled = !isChecked
|
||||
}
|
||||
|
||||
@CallbackProp
|
||||
|
||||
@@ -49,6 +49,7 @@ class LocaleView @JvmOverloads constructor(
|
||||
@ModelProp
|
||||
fun markChecked(isChecked: Boolean) {
|
||||
binding.checkbox.isChecked = isChecked
|
||||
binding.checkbox.isEnabled = !isChecked
|
||||
}
|
||||
|
||||
@CallbackProp
|
||||
|
||||
@@ -25,83 +25,85 @@ import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.data.providers.NativeDeviceInfoProvider
|
||||
import com.aurora.store.data.providers.SpoofProvider
|
||||
import com.aurora.store.databinding.FragmentGenericRecyclerBinding
|
||||
import com.aurora.store.view.epoxy.views.TextDividerViewModel_
|
||||
import com.aurora.store.view.epoxy.views.preference.DeviceViewModel_
|
||||
import com.aurora.store.view.ui.commons.BaseFragment
|
||||
import com.aurora.store.viewmodel.spoof.SpoofViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Properties
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class DeviceSpoofFragment : BaseFragment<FragmentGenericRecyclerBinding>() {
|
||||
|
||||
private val viewModel: SpoofViewModel by viewModels()
|
||||
|
||||
@Inject
|
||||
lateinit var spoofProvider: SpoofProvider
|
||||
|
||||
private lateinit var properties: Properties
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(): DeviceSpoofFragment {
|
||||
return DeviceSpoofFragment().apply {
|
||||
|
||||
}
|
||||
return DeviceSpoofFragment()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
properties = if (spoofProvider.isDeviceSpoofEnabled()) {
|
||||
spoofProvider.getSpoofDeviceProperties()
|
||||
} else {
|
||||
NativeDeviceInfoProvider(requireContext()).getNativeDeviceProperties()
|
||||
}
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.availableDevices.collect { updateController(it) }
|
||||
}
|
||||
}
|
||||
viewModel.fetchAvailableDevices()
|
||||
}
|
||||
|
||||
private fun updateController(locales: List<Properties>) {
|
||||
private fun updateController(devices: List<Properties>) {
|
||||
binding.recycler.withModels {
|
||||
setFilterDuplicates(true)
|
||||
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()
|
||||
}
|
||||
|
||||
add(
|
||||
TextDividerViewModel_()
|
||||
.id("default_divider")
|
||||
.title(getString(R.string.default_spoof))
|
||||
)
|
||||
|
||||
add(
|
||||
DeviceViewModel_()
|
||||
.id(viewModel.defaultProperties.hashCode())
|
||||
.markChecked(viewModel.isDeviceSelected(viewModel.defaultProperties))
|
||||
.checked { _, checked ->
|
||||
if (checked) {
|
||||
viewModel.onDeviceSelected(viewModel.defaultProperties)
|
||||
requestModelBuild()
|
||||
findNavController().navigate(R.id.forceRestartDialog)
|
||||
}
|
||||
}
|
||||
.properties(viewModel.defaultProperties)
|
||||
)
|
||||
|
||||
add(
|
||||
TextDividerViewModel_()
|
||||
.id("available_divider")
|
||||
.title(getString(R.string.available_spoof))
|
||||
)
|
||||
|
||||
devices.forEach {
|
||||
add(
|
||||
DeviceViewModel_()
|
||||
.id(it.hashCode())
|
||||
.markChecked(viewModel.isDeviceSelected(it))
|
||||
.checked { _, checked ->
|
||||
if (checked) {
|
||||
viewModel.onDeviceSelected(it)
|
||||
requestModelBuild()
|
||||
findNavController().navigate(R.id.forceRestartDialog)
|
||||
}
|
||||
.properties(it)
|
||||
)
|
||||
}
|
||||
}
|
||||
.properties(it)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveSelection(properties: Properties) {
|
||||
requireContext().toast(R.string.spoof_apply)
|
||||
spoofProvider.setSpoofDeviceProperties(properties)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,68 +20,83 @@
|
||||
package com.aurora.store.view.ui.spoof
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.data.providers.SpoofProvider
|
||||
import com.aurora.store.databinding.FragmentGenericRecyclerBinding
|
||||
import com.aurora.store.view.epoxy.views.TextDividerViewModel_
|
||||
import com.aurora.store.view.epoxy.views.preference.LocaleViewModel_
|
||||
import com.aurora.store.view.ui.commons.BaseFragment
|
||||
import com.aurora.store.viewmodel.spoof.SpoofViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class LocaleSpoofFragment : BaseFragment<FragmentGenericRecyclerBinding>() {
|
||||
|
||||
private val TAG = LocaleSpoofFragment::class.java.simpleName
|
||||
|
||||
@Inject
|
||||
lateinit var spoofProvider: SpoofProvider
|
||||
|
||||
private lateinit var locale: Locale
|
||||
private val viewModel: SpoofViewModel by viewModels()
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(): LocaleSpoofFragment {
|
||||
return LocaleSpoofFragment().apply {
|
||||
|
||||
}
|
||||
return LocaleSpoofFragment()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
locale = if (spoofProvider.isLocaleSpoofEnabled()) {
|
||||
spoofProvider.getSpoofLocale()
|
||||
} else {
|
||||
Locale.getDefault()
|
||||
}
|
||||
|
||||
try {
|
||||
updateController(fetchAvailableLocales())
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Could not get available locales", exception)
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewModel.availableLocales.collect {
|
||||
updateController(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateController(locales: List<Locale>) {
|
||||
binding.recycler.withModels {
|
||||
setFilterDuplicates(true)
|
||||
locales
|
||||
.sortedBy { it.displayName }
|
||||
.forEach {
|
||||
|
||||
add(
|
||||
TextDividerViewModel_()
|
||||
.id("default_divider")
|
||||
.title(getString(R.string.default_spoof))
|
||||
)
|
||||
|
||||
add(
|
||||
LocaleViewModel_()
|
||||
.id(viewModel.defaultLocale.language)
|
||||
.markChecked(viewModel.isLocaleSelected(viewModel.defaultLocale))
|
||||
.checked { _, checked ->
|
||||
if (checked) {
|
||||
viewModel.onLocaleSelected(viewModel.defaultLocale)
|
||||
requestModelBuild()
|
||||
findNavController().navigate(R.id.forceRestartDialog)
|
||||
}
|
||||
}
|
||||
.locale(viewModel.defaultLocale)
|
||||
)
|
||||
|
||||
add(
|
||||
TextDividerViewModel_()
|
||||
.id("available_divider")
|
||||
.title(getString(R.string.available_spoof))
|
||||
)
|
||||
|
||||
locales.forEach {
|
||||
add(
|
||||
LocaleViewModel_()
|
||||
.id(it.language)
|
||||
.markChecked(locale == it)
|
||||
.markChecked(viewModel.spoofProvider.locale == it)
|
||||
.checked { _, checked ->
|
||||
if (checked) {
|
||||
locale = it
|
||||
saveSelection(it)
|
||||
viewModel.onLocaleSelected(it)
|
||||
requestModelBuild()
|
||||
findNavController().navigate(R.id.forceRestartDialog)
|
||||
}
|
||||
}
|
||||
.locale(it)
|
||||
@@ -89,17 +104,4 @@ class LocaleSpoofFragment : BaseFragment<FragmentGenericRecyclerBinding>() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchAvailableLocales(): List<Locale> {
|
||||
val locales = Locale.getAvailableLocales()
|
||||
val localeList: MutableList<Locale> = ArrayList()
|
||||
localeList.addAll(locales)
|
||||
localeList.add(0, Locale.getDefault())
|
||||
return localeList
|
||||
}
|
||||
|
||||
private fun saveSelection(locale: Locale) {
|
||||
requireContext().toast(R.string.spoof_apply)
|
||||
spoofProvider.setSpoofLocale(locale)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,8 +123,7 @@ class SpoofFragment : BaseFragment<FragmentGenericWithPagerBinding>() {
|
||||
|
||||
private fun exportDeviceConfig(uri: Uri) {
|
||||
try {
|
||||
NativeDeviceInfoProvider(requireContext())
|
||||
.getNativeDeviceProperties(true)
|
||||
NativeDeviceInfoProvider.getNativeDeviceProperties(requireContext(), true)
|
||||
.store(requireContext().contentResolver?.openOutputStream(uri), "DEVICE_CONFIG")
|
||||
toast(R.string.toast_export_success)
|
||||
} catch (exception: Exception) {
|
||||
|
||||
@@ -1,27 +1,64 @@
|
||||
package com.aurora.store.viewmodel.spoof
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.aurora.store.data.providers.SpoofDeviceProvider
|
||||
import com.aurora.store.data.providers.NativeDeviceInfoProvider
|
||||
import com.aurora.store.data.providers.SpoofProvider
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Locale
|
||||
import java.util.Properties
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class SpoofViewModel @Inject constructor(
|
||||
private val spoofDeviceProvider: SpoofDeviceProvider
|
||||
val spoofProvider: SpoofProvider,
|
||||
@ApplicationContext private val context: Context
|
||||
): ViewModel() {
|
||||
|
||||
private val _availableDevices: MutableStateFlow<List<Properties>> = MutableStateFlow(emptyList())
|
||||
val defaultLocale: Locale = Locale.getDefault()
|
||||
val defaultProperties = NativeDeviceInfoProvider.getNativeDeviceProperties(context)
|
||||
|
||||
private var currentDevice = spoofProvider.deviceProperties.getProperty("UserReadableName")
|
||||
private var currentLocale = spoofProvider.locale
|
||||
|
||||
private val _availableLocales: MutableStateFlow<List<Locale>> = MutableStateFlow(
|
||||
spoofProvider.availableSpoofLocales
|
||||
)
|
||||
val availableLocales = _availableLocales.asStateFlow()
|
||||
|
||||
private val _availableDevices: MutableStateFlow<List<Properties>> = MutableStateFlow(
|
||||
spoofProvider.availableSpoofDeviceProperties
|
||||
)
|
||||
val availableDevices = _availableDevices.asStateFlow()
|
||||
|
||||
fun fetchAvailableDevices() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
_availableDevices.value = spoofDeviceProvider.availableDevice
|
||||
fun isDeviceSelected(properties: Properties): Boolean {
|
||||
return currentDevice == properties.getProperty("UserReadableName")
|
||||
}
|
||||
|
||||
fun onDeviceSelected(properties: Properties) {
|
||||
currentDevice = properties.getProperty("UserReadableName")
|
||||
|
||||
if (currentDevice == defaultProperties.getProperty("UserReadableName")) {
|
||||
spoofProvider.removeSpoofDeviceProperties()
|
||||
} else {
|
||||
spoofProvider.setSpoofDeviceProperties(properties)
|
||||
}
|
||||
}
|
||||
|
||||
fun isLocaleSelected(locale: Locale): Boolean {
|
||||
return currentLocale == locale
|
||||
}
|
||||
|
||||
fun onLocaleSelected(locale: Locale) {
|
||||
currentLocale = locale
|
||||
|
||||
if (currentLocale == defaultLocale) {
|
||||
spoofProvider.removeSpoofLocale()
|
||||
} else {
|
||||
spoofProvider.setSpoofLocale(locale)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,4 +467,8 @@
|
||||
<!-- UnarchivePackageReceiver -->
|
||||
<string name="authentication_required_title">Authentication required</string>
|
||||
<string name="authentication_required_unarchive">Please log in to your Google Play account to unarchive the app!</string>
|
||||
|
||||
<!-- SpoofFragment -->
|
||||
<string name="default_spoof">Default</string>
|
||||
<string name="available_spoof">Available</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user