Blacklist*: Load PackageInfo instead of App
Allow people to access and blacklist apps without logging in Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -20,16 +20,18 @@
|
|||||||
package com.aurora.store.view.epoxy.views
|
package com.aurora.store.view.epoxy.views
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import com.airbnb.epoxy.CallbackProp
|
import com.airbnb.epoxy.CallbackProp
|
||||||
import com.airbnb.epoxy.ModelProp
|
import com.airbnb.epoxy.ModelProp
|
||||||
import com.airbnb.epoxy.ModelView
|
import com.airbnb.epoxy.ModelView
|
||||||
import com.aurora.gplayapi.data.models.App
|
|
||||||
import com.aurora.store.R
|
import com.aurora.store.R
|
||||||
import com.aurora.store.databinding.ViewBlackBinding
|
import com.aurora.store.databinding.ViewBlackBinding
|
||||||
|
import com.aurora.store.util.PackageUtil
|
||||||
|
|
||||||
@ModelView(
|
@ModelView(
|
||||||
autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT,
|
autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT,
|
||||||
@@ -41,16 +43,17 @@ class BlackListView @JvmOverloads constructor(
|
|||||||
defStyleAttr: Int = 0
|
defStyleAttr: Int = 0
|
||||||
) : BaseView<ViewBlackBinding>(context, attrs, defStyleAttr) {
|
) : BaseView<ViewBlackBinding>(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
@ModelProp
|
@ModelProp(options = [ModelProp.Option.IgnoreRequireHashCode])
|
||||||
fun app(app: App) {
|
fun packageInfo(packageInfo: PackageInfo) {
|
||||||
binding.imgIcon.load(app.iconArtwork.url) {
|
val appInfo = packageInfo.applicationInfo!!
|
||||||
|
binding.imgIcon.load(PackageUtil.getIconForPackage(context, appInfo.packageName)) {
|
||||||
placeholder(R.drawable.bg_placeholder)
|
placeholder(R.drawable.bg_placeholder)
|
||||||
transformations(RoundedCornersTransformation(25F))
|
transformations(RoundedCornersTransformation(25F))
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.txtLine1.text = app.displayName
|
binding.txtLine1.text = appInfo.loadLabel(context.packageManager)
|
||||||
binding.txtLine2.text = app.packageName
|
binding.txtLine2.text = appInfo.packageName
|
||||||
binding.txtLine3.text = ("${app.versionName}.${app.versionCode}")
|
binding.txtLine3.text = ("${packageInfo.versionName}.${PackageInfoCompat.getLongVersionCode(packageInfo)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ModelProp
|
@ModelProp
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package com.aurora.store.view.ui.commons
|
package com.aurora.store.view.ui.commons
|
||||||
|
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
@@ -26,7 +27,6 @@ import android.view.View
|
|||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.aurora.gplayapi.data.models.App
|
|
||||||
import com.aurora.store.AuroraApp
|
import com.aurora.store.AuroraApp
|
||||||
import com.aurora.store.data.event.BusEvent
|
import com.aurora.store.data.event.BusEvent
|
||||||
import com.aurora.store.databinding.FragmentGenericWithSearchBinding
|
import com.aurora.store.databinding.FragmentGenericWithSearchBinding
|
||||||
@@ -38,18 +38,15 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
|
class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
|
||||||
private val viewModel: BlacklistViewModel by viewModels()
|
|
||||||
|
|
||||||
private var blackList: List<App>? = emptyList()
|
private val viewModel: BlacklistViewModel by viewModels()
|
||||||
private var query: String = String()
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewModel.blackListedApps.collect {
|
viewModel.packages.collect {
|
||||||
blackList = it
|
updateController(it)
|
||||||
updateController(blackList)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,15 +63,12 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
|
|||||||
inputSearch.addTextChangedListener(object : TextWatcher {
|
inputSearch.addTextChangedListener(object : TextWatcher {
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||||
if (s.isNullOrEmpty()) {
|
if (s.isNullOrEmpty()) {
|
||||||
updateController(blackList)
|
updateController(viewModel.packages.value)
|
||||||
} else {
|
} else {
|
||||||
query = s.toString()
|
val filteredPackages = viewModel.packages.value?.filter {
|
||||||
|
it.applicationInfo!!.loadLabel(requireContext().packageManager).contains(s, true)
|
||||||
val filtered = blackList?.filter {
|
|
||||||
it.displayName.contains(query, true)
|
|
||||||
}
|
}
|
||||||
|
updateController(filteredPackages)
|
||||||
updateController(filtered)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +78,7 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
|
|||||||
start: Int,
|
start: Int,
|
||||||
count: Int,
|
count: Int,
|
||||||
after: Int
|
after: Int
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,10 +88,10 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
|
|||||||
viewModel.blacklistProvider.blacklist = viewModel.selected
|
viewModel.blacklistProvider.blacklist = viewModel.selected
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateController(blackList: List<App>?) {
|
private fun updateController(packages: List<PackageInfo>?) {
|
||||||
binding.recycler.withModels {
|
binding.recycler.withModels {
|
||||||
setFilterDuplicates(true)
|
setFilterDuplicates(true)
|
||||||
if (blackList == null) {
|
if (packages == null) {
|
||||||
for (i in 1..10) {
|
for (i in 1..10) {
|
||||||
add(
|
add(
|
||||||
AppListViewShimmerModel_()
|
AppListViewShimmerModel_()
|
||||||
@@ -106,7 +99,7 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blackList
|
packages
|
||||||
.sortedByDescending { app ->
|
.sortedByDescending { app ->
|
||||||
viewModel.blacklistProvider.isBlacklisted(app.packageName)
|
viewModel.blacklistProvider.isBlacklisted(app.packageName)
|
||||||
}
|
}
|
||||||
@@ -114,7 +107,7 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
|
|||||||
add(
|
add(
|
||||||
BlackListViewModel_()
|
BlackListViewModel_()
|
||||||
.id(it.packageName.hashCode())
|
.id(it.packageName.hashCode())
|
||||||
.app(it)
|
.packageInfo(it)
|
||||||
.markChecked(viewModel.selected.contains(it.packageName))
|
.markChecked(viewModel.selected.contains(it.packageName))
|
||||||
.checked { _, isChecked ->
|
.checked { _, isChecked ->
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
|
|||||||
@@ -20,41 +20,36 @@
|
|||||||
package com.aurora.store.viewmodel.all
|
package com.aurora.store.viewmodel.all
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
|
import android.util.Log
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.aurora.extensions.isValidApp
|
import com.aurora.extensions.isValidApp
|
||||||
import com.aurora.gplayapi.data.models.App
|
|
||||||
import com.aurora.gplayapi.helpers.AppDetailsHelper
|
|
||||||
import com.aurora.gplayapi.network.IHttpClient
|
|
||||||
import com.aurora.store.data.providers.AuthProvider
|
|
||||||
import com.aurora.store.data.providers.BlacklistProvider
|
import com.aurora.store.data.providers.BlacklistProvider
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import java.util.Locale
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.supervisorScope
|
import kotlinx.coroutines.supervisorScope
|
||||||
import java.util.Locale
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class BlacklistViewModel @Inject constructor(
|
class BlacklistViewModel @Inject constructor(
|
||||||
val blacklistProvider: BlacklistProvider,
|
val blacklistProvider: BlacklistProvider,
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context
|
||||||
private val httpClient: IHttpClient,
|
|
||||||
authProvider: AuthProvider
|
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val appDetailsHelper = AppDetailsHelper(authProvider.authData!!)
|
|
||||||
.using(httpClient)
|
|
||||||
|
|
||||||
private val _blacklistedApps = MutableStateFlow<List<App>?>(null)
|
private val TAG = BlacklistViewModel::class.java.simpleName
|
||||||
val blackListedApps = _blacklistedApps.asStateFlow()
|
|
||||||
|
|
||||||
var selected: MutableSet<String> = mutableSetOf()
|
private val _packages = MutableStateFlow<List<PackageInfo>?>(null)
|
||||||
|
val packages = _packages.asStateFlow()
|
||||||
|
|
||||||
|
var selected: MutableSet<String> = blacklistProvider.blacklist
|
||||||
|
|
||||||
init {
|
init {
|
||||||
selected = blacklistProvider.blacklist
|
|
||||||
fetchApps()
|
fetchApps()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,17 +57,18 @@ class BlacklistViewModel @Inject constructor(
|
|||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
supervisorScope {
|
supervisorScope {
|
||||||
try {
|
try {
|
||||||
val packageNames = context.packageManager.getInstalledPackages(0)
|
_packages.value = context.packageManager.getInstalledPackages(0)
|
||||||
.filter { it.isValidApp() }
|
.filter { it.isValidApp() }
|
||||||
.map { it.packageName }
|
.filter {
|
||||||
|
// Most core AOSP system apps use their package name as label
|
||||||
val apps = appDetailsHelper
|
it.applicationInfo!!.loadLabel(context.packageManager) != it.packageName
|
||||||
.getAppByPackageName(packageNames)
|
}
|
||||||
.filter { it.displayName.isNotBlank() }
|
.sortedBy {
|
||||||
|
it.applicationInfo!!.loadLabel(context.packageManager).toString()
|
||||||
_blacklistedApps.emit(apps.sortedBy { it.displayName.lowercase(Locale.getDefault()) })
|
.lowercase(Locale.getDefault())
|
||||||
} catch (e: Exception) {
|
}
|
||||||
e.printStackTrace()
|
} catch (exception: Exception) {
|
||||||
|
Log.e(TAG, "Failed to fetch apps", exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user