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:
Aayush Gupta
2024-10-16 20:50:23 +05:30
parent 3d6f4796e0
commit dfc223d8cb
3 changed files with 43 additions and 51 deletions

View File

@@ -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

View File

@@ -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) {

View File

@@ -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)
} }
} }
} }