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
import android.content.Context
import android.content.pm.PackageInfo
import android.util.AttributeSet
import android.widget.CompoundButton
import androidx.core.content.pm.PackageInfoCompat
import coil.load
import coil.transform.RoundedCornersTransformation
import com.airbnb.epoxy.CallbackProp
import com.airbnb.epoxy.ModelProp
import com.airbnb.epoxy.ModelView
import com.aurora.gplayapi.data.models.App
import com.aurora.store.R
import com.aurora.store.databinding.ViewBlackBinding
import com.aurora.store.util.PackageUtil
@ModelView(
autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT,
@@ -41,16 +43,17 @@ class BlackListView @JvmOverloads constructor(
defStyleAttr: Int = 0
) : BaseView<ViewBlackBinding>(context, attrs, defStyleAttr) {
@ModelProp
fun app(app: App) {
binding.imgIcon.load(app.iconArtwork.url) {
@ModelProp(options = [ModelProp.Option.IgnoreRequireHashCode])
fun packageInfo(packageInfo: PackageInfo) {
val appInfo = packageInfo.applicationInfo!!
binding.imgIcon.load(PackageUtil.getIconForPackage(context, appInfo.packageName)) {
placeholder(R.drawable.bg_placeholder)
transformations(RoundedCornersTransformation(25F))
}
binding.txtLine1.text = app.displayName
binding.txtLine2.text = app.packageName
binding.txtLine3.text = ("${app.versionName}.${app.versionCode}")
binding.txtLine1.text = appInfo.loadLabel(context.packageManager)
binding.txtLine2.text = appInfo.packageName
binding.txtLine3.text = ("${packageInfo.versionName}.${PackageInfoCompat.getLongVersionCode(packageInfo)}")
}
@ModelProp

View File

@@ -19,6 +19,7 @@
package com.aurora.store.view.ui.commons
import android.content.pm.PackageInfo
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
@@ -26,7 +27,6 @@ import android.view.View
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.aurora.gplayapi.data.models.App
import com.aurora.store.AuroraApp
import com.aurora.store.data.event.BusEvent
import com.aurora.store.databinding.FragmentGenericWithSearchBinding
@@ -38,18 +38,15 @@ import kotlinx.coroutines.launch
@AndroidEntryPoint
class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
private val viewModel: BlacklistViewModel by viewModels()
private var blackList: List<App>? = emptyList()
private var query: String = String()
private val viewModel: BlacklistViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
viewModel.blackListedApps.collect {
blackList = it
updateController(blackList)
viewModel.packages.collect {
updateController(it)
}
}
@@ -66,15 +63,12 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
inputSearch.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s.isNullOrEmpty()) {
updateController(blackList)
updateController(viewModel.packages.value)
} else {
query = s.toString()
val filtered = blackList?.filter {
it.displayName.contains(query, true)
val filteredPackages = viewModel.packages.value?.filter {
it.applicationInfo!!.loadLabel(requireContext().packageManager).contains(s, true)
}
updateController(filtered)
updateController(filteredPackages)
}
}
@@ -84,8 +78,7 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
start: Int,
count: Int,
after: Int
) {
}
) {}
})
}
}
@@ -95,10 +88,10 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
viewModel.blacklistProvider.blacklist = viewModel.selected
}
private fun updateController(blackList: List<App>?) {
private fun updateController(packages: List<PackageInfo>?) {
binding.recycler.withModels {
setFilterDuplicates(true)
if (blackList == null) {
if (packages == null) {
for (i in 1..10) {
add(
AppListViewShimmerModel_()
@@ -106,7 +99,7 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
)
}
} else {
blackList
packages
.sortedByDescending { app ->
viewModel.blacklistProvider.isBlacklisted(app.packageName)
}
@@ -114,7 +107,7 @@ class BlacklistFragment : BaseFragment<FragmentGenericWithSearchBinding>() {
add(
BlackListViewModel_()
.id(it.packageName.hashCode())
.app(it)
.packageInfo(it)
.markChecked(viewModel.selected.contains(it.packageName))
.checked { _, isChecked ->
if (isChecked) {

View File

@@ -20,41 +20,36 @@
package com.aurora.store.viewmodel.all
import android.content.Context
import android.content.pm.PackageInfo
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
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 dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import java.util.Locale
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope
import java.util.Locale
import javax.inject.Inject
@HiltViewModel
class BlacklistViewModel @Inject constructor(
val blacklistProvider: BlacklistProvider,
@ApplicationContext private val context: Context,
private val httpClient: IHttpClient,
authProvider: AuthProvider
@ApplicationContext private val context: Context
) : ViewModel() {
private val appDetailsHelper = AppDetailsHelper(authProvider.authData!!)
.using(httpClient)
private val _blacklistedApps = MutableStateFlow<List<App>?>(null)
val blackListedApps = _blacklistedApps.asStateFlow()
private val TAG = BlacklistViewModel::class.java.simpleName
var selected: MutableSet<String> = mutableSetOf()
private val _packages = MutableStateFlow<List<PackageInfo>?>(null)
val packages = _packages.asStateFlow()
var selected: MutableSet<String> = blacklistProvider.blacklist
init {
selected = blacklistProvider.blacklist
fetchApps()
}
@@ -62,17 +57,18 @@ class BlacklistViewModel @Inject constructor(
viewModelScope.launch(Dispatchers.IO) {
supervisorScope {
try {
val packageNames = context.packageManager.getInstalledPackages(0)
_packages.value = context.packageManager.getInstalledPackages(0)
.filter { it.isValidApp() }
.map { it.packageName }
val apps = appDetailsHelper
.getAppByPackageName(packageNames)
.filter { it.displayName.isNotBlank() }
_blacklistedApps.emit(apps.sortedBy { it.displayName.lowercase(Locale.getDefault()) })
} catch (e: Exception) {
e.printStackTrace()
.filter {
// Most core AOSP system apps use their package name as label
it.applicationInfo!!.loadLabel(context.packageManager) != it.packageName
}
.sortedBy {
it.applicationInfo!!.loadLabel(context.packageManager).toString()
.lowercase(Locale.getDefault())
}
} catch (exception: Exception) {
Log.e(TAG, "Failed to fetch apps", exception)
}
}
}