mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-04-23 11:22:12 +00:00
Update: Migrate ignoring updates logic to Extras
This commit is contained in:
parent
bed6c203a1
commit
9941354bcb
@ -15,7 +15,6 @@ import coil.ImageLoader
|
||||
import coil.ImageLoaderFactory
|
||||
import com.looker.droidify.content.Cache
|
||||
import com.looker.droidify.content.Preferences
|
||||
import com.looker.droidify.content.ProductPreferences
|
||||
import com.looker.droidify.database.DatabaseX
|
||||
import com.looker.droidify.index.RepositoryUpdater
|
||||
import com.looker.droidify.network.CoilDownloader
|
||||
@ -45,7 +44,6 @@ class MainApplication : Application(), ImageLoaderFactory {
|
||||
|
||||
db = DatabaseX.getInstance(applicationContext)
|
||||
Preferences.init(this)
|
||||
ProductPreferences.init(this)
|
||||
RepositoryUpdater.init(this)
|
||||
listenApplications()
|
||||
listenPreferences()
|
||||
|
@ -38,8 +38,6 @@ import com.looker.droidify.ROW_UPDATED
|
||||
import com.looker.droidify.ROW_VERSION_CODE
|
||||
import com.looker.droidify.TABLE_CATEGORY
|
||||
import com.looker.droidify.TABLE_CATEGORY_NAME
|
||||
import com.looker.droidify.TABLE_IGNORED
|
||||
import com.looker.droidify.TABLE_IGNORED_NAME
|
||||
import com.looker.droidify.TABLE_EXTRAS
|
||||
import com.looker.droidify.TABLE_EXTRAS_NAME
|
||||
import com.looker.droidify.TABLE_INSTALLED
|
||||
@ -199,8 +197,8 @@ interface ProductDao : BaseDao<Product> {
|
||||
builder += """SELECT $TABLE_PRODUCT.rowid AS $ROW_ID, $TABLE_PRODUCT.$ROW_REPOSITORY_ID,
|
||||
$TABLE_PRODUCT.$ROW_PACKAGE_NAME, $TABLE_PRODUCT.$ROW_LABEL,
|
||||
$TABLE_PRODUCT.$ROW_SUMMARY, $TABLE_PRODUCT.$ROW_DESCRIPTION,
|
||||
(COALESCE($TABLE_IGNORED.$ROW_VERSION_CODE, -1) NOT IN (0, $TABLE_PRODUCT.$ROW_VERSION_CODE) AND
|
||||
$TABLE_PRODUCT.$ROW_COMPATIBLE != 0 AND
|
||||
(COALESCE($TABLE_EXTRAS.$ROW_IGNORED_VERSION, -1) != $TABLE_PRODUCT.$ROW_VERSION_CODE AND
|
||||
COALESCE($TABLE_EXTRAS.$ROW_IGNORE_UPDATES, 0) = 0 AND $TABLE_PRODUCT.$ROW_COMPATIBLE != 0 AND
|
||||
$TABLE_PRODUCT.$ROW_VERSION_CODE > COALESCE($TABLE_INSTALLED.$ROW_VERSION_CODE, 0xffffffff) AND
|
||||
$signatureMatches) AS $ROW_CAN_UPDATE, $TABLE_PRODUCT.$ROW_ICON,
|
||||
$TABLE_PRODUCT.$ROW_METADATA_ICON, $TABLE_PRODUCT.$ROW_RELEASES, $TABLE_PRODUCT.$ROW_CATEGORIES,
|
||||
@ -227,9 +225,9 @@ interface ProductDao : BaseDao<Product> {
|
||||
builder += """JOIN $TABLE_REPOSITORY_NAME AS $TABLE_REPOSITORY
|
||||
ON $TABLE_PRODUCT.$ROW_REPOSITORY_ID = $TABLE_REPOSITORY.$ROW_ID"""
|
||||
|
||||
// Merge the matching locks
|
||||
builder += """LEFT JOIN $TABLE_IGNORED_NAME AS $TABLE_IGNORED
|
||||
ON $TABLE_PRODUCT.$ROW_PACKAGE_NAME = $TABLE_IGNORED.$ROW_PACKAGE_NAME"""
|
||||
// Merge the matching extras
|
||||
builder += """LEFT JOIN $TABLE_EXTRAS_NAME AS $TABLE_EXTRAS
|
||||
ON $TABLE_PRODUCT.$ROW_PACKAGE_NAME = $TABLE_EXTRAS.$ROW_PACKAGE_NAME"""
|
||||
|
||||
// Merge the matching installed
|
||||
if (!installed && !updates) builder += "LEFT"
|
||||
|
@ -7,7 +7,7 @@ import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import com.looker.droidify.database.entity.Category
|
||||
import com.looker.droidify.database.entity.CategoryTemp
|
||||
import com.looker.droidify.database.entity.Ignored
|
||||
import com.looker.droidify.database.entity.Extras
|
||||
import com.looker.droidify.database.entity.Installed
|
||||
import com.looker.droidify.database.entity.Product
|
||||
import com.looker.droidify.database.entity.ProductTemp
|
||||
@ -27,8 +27,8 @@ import kotlinx.coroutines.launch
|
||||
Category::class,
|
||||
CategoryTemp::class,
|
||||
Installed::class,
|
||||
Ignored::class
|
||||
], version = 7
|
||||
Extras::class
|
||||
], version = 8
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class DatabaseX : RoomDatabase() {
|
||||
@ -39,7 +39,7 @@ abstract class DatabaseX : RoomDatabase() {
|
||||
abstract val categoryDao: CategoryDao
|
||||
abstract val categoryTempDao: CategoryTempDao
|
||||
abstract val installedDao: InstalledDao
|
||||
abstract val lockDao: LockDao
|
||||
abstract val extrasDao: ExtrasDao
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
|
@ -3,12 +3,10 @@ package com.looker.droidify.ui.compose.utils
|
||||
import android.net.Uri
|
||||
import com.looker.droidify.database.entity.Release
|
||||
import com.looker.droidify.entity.ActionState
|
||||
import com.looker.droidify.entity.ProductPreference
|
||||
import com.looker.droidify.entity.Screenshot
|
||||
|
||||
interface Callbacks {
|
||||
fun onActionClick(action: ActionState?)
|
||||
fun onPreferenceChanged(preference: ProductPreference)
|
||||
fun onPermissionsClick(group: String?, permissions: List<String>)
|
||||
fun onScreenshotClick(screenshot: Screenshot)
|
||||
fun onReleaseClick(release: Release)
|
||||
|
@ -41,13 +41,12 @@ import com.looker.droidify.RELEASE_STATE_INSTALLED
|
||||
import com.looker.droidify.RELEASE_STATE_NONE
|
||||
import com.looker.droidify.RELEASE_STATE_SUGGESTED
|
||||
import com.looker.droidify.content.Preferences
|
||||
import com.looker.droidify.content.ProductPreferences
|
||||
import com.looker.droidify.database.entity.Extras
|
||||
import com.looker.droidify.database.entity.Release
|
||||
import com.looker.droidify.entity.ActionState
|
||||
import com.looker.droidify.entity.AntiFeature
|
||||
import com.looker.droidify.entity.DonateType
|
||||
import com.looker.droidify.entity.DownloadState
|
||||
import com.looker.droidify.entity.ProductPreference
|
||||
import com.looker.droidify.entity.Screenshot
|
||||
import com.looker.droidify.installer.AppInstaller
|
||||
import com.looker.droidify.network.CoilDownloader
|
||||
@ -144,9 +143,7 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), Callbacks {
|
||||
|
||||
override fun setupLayout() {
|
||||
viewModel._productRepos.observe(this) {
|
||||
lifecycleScope.launch {
|
||||
updateButtons()
|
||||
}
|
||||
viewModel.updateActions()
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,86 +156,6 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), Callbacks {
|
||||
downloadConnection.unbind(requireContext())
|
||||
}
|
||||
|
||||
private suspend fun updateButtons() {
|
||||
updateButtons(ProductPreferences[packageName])
|
||||
}
|
||||
|
||||
// TODO rename to updateActions
|
||||
private suspend fun updateButtons(preference: ProductPreference) =
|
||||
withContext(Dispatchers.Default) {
|
||||
val installed = viewModel.installedItem.value
|
||||
val productRepos = viewModel.productRepos
|
||||
val product = findSuggestedProduct(productRepos, installed) { it.first }?.first
|
||||
val compatible = product != null && product.selectedReleases.firstOrNull()
|
||||
.let { it != null && it.incompatibilities.isEmpty() }
|
||||
val canInstall = product != null && installed == null && compatible
|
||||
val canUpdate =
|
||||
product != null && compatible && product.canUpdate(installed) &&
|
||||
!preference.shouldIgnoreUpdate(product.versionCode)
|
||||
val canUninstall = product != null && installed != null && !installed.isSystem
|
||||
val canLaunch =
|
||||
product != null && installed != null && installed.launcherActivities.isNotEmpty()
|
||||
val canShare = product != null && productRepos[0].second.name == "F-Droid"
|
||||
|
||||
val actions = mutableSetOf<ActionState>()
|
||||
launch {
|
||||
if (canInstall) {
|
||||
actions += ActionState.Install
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (canUpdate) {
|
||||
actions += ActionState.Update
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (canLaunch) {
|
||||
actions += ActionState.Launch
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (installed != null) {
|
||||
actions += ActionState.Details
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (canUninstall) {
|
||||
actions += ActionState.Uninstall
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (canShare) {
|
||||
actions += ActionState.Share
|
||||
}
|
||||
}
|
||||
// TODO prioritize actions set and choose the first for main others for extra actions
|
||||
val primaryAction = when {
|
||||
canUpdate -> ActionState.Update
|
||||
canLaunch -> ActionState.Launch
|
||||
canInstall -> ActionState.Install
|
||||
canShare -> ActionState.Share
|
||||
else -> null
|
||||
}
|
||||
val secondaryAction = when {
|
||||
primaryAction != ActionState.Share && canShare -> ActionState.Share
|
||||
primaryAction != ActionState.Launch && canLaunch -> ActionState.Launch
|
||||
installed != null && canUninstall -> ActionState.Uninstall
|
||||
else -> null
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
viewModel.actions.value = actions
|
||||
|
||||
if (viewModel.downloadState.value != null && viewModel.mainAction.value?.textId != viewModel.downloadState.value?.textId)
|
||||
viewModel.downloadState.value?.let {
|
||||
viewModel.mainAction.value = ActionState.Cancel(it.textId)
|
||||
}
|
||||
else if (viewModel.downloadState.value == null) // && viewModel.mainAction.value != primaryAction)
|
||||
viewModel.mainAction.value = primaryAction
|
||||
viewModel.secondaryAction.value = secondaryAction
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateDownloadState(downloadState: DownloadService.State?) {
|
||||
val state = when (downloadState) {
|
||||
is DownloadService.State.Pending -> DownloadState.Pending
|
||||
@ -250,8 +167,8 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), Callbacks {
|
||||
else -> null
|
||||
}
|
||||
viewModel.downloadState.value = state
|
||||
updateButtons()
|
||||
if (downloadState is DownloadService.State.Success && isResumed && !rootInstallerEnabled) {
|
||||
viewModel.updateActions()
|
||||
withContext(Dispatchers.Default) {
|
||||
AppInstaller.getInstance(context)?.defaultInstaller?.install(downloadState.release.cacheFileName)
|
||||
}
|
||||
@ -325,10 +242,6 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), Callbacks {
|
||||
startActivity(Intent.createChooser(shareIntent, "Where to Send?"))
|
||||
}
|
||||
|
||||
override fun onPreferenceChanged(preference: ProductPreference) {
|
||||
lifecycleScope.launch { updateButtons(preference) }
|
||||
}
|
||||
|
||||
override fun onPermissionsClick(group: String?, permissions: List<String>) {
|
||||
MessageDialog(MessageDialog.Message.Permissions(group, permissions)).show(
|
||||
childFragmentManager
|
||||
@ -422,6 +335,7 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), Callbacks {
|
||||
val mainAction by viewModel.mainAction.observeAsState(if (installed == null) ActionState.Install else ActionState.Launch)
|
||||
val actions by viewModel.actions.observeAsState() // TODO add rest actions to UI
|
||||
val secondaryAction by viewModel.secondaryAction.observeAsState()
|
||||
val extras by viewModel.extras.observeAsState(Extras(packageName))
|
||||
val productRepos = products?.mapNotNull { product ->
|
||||
repos?.firstOrNull { it.id == product.repositoryId }
|
||||
?.let { Pair(product, it) }
|
||||
@ -515,27 +429,23 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), Callbacks {
|
||||
item {
|
||||
AnimatedVisibility(visible = product.canUpdate(installed)) {
|
||||
SwitchPreference(text = stringResource(id = R.string.ignore_this_update),
|
||||
initSelected = ProductPreferences[product.packageName].ignoreVersionCode == product.versionCode,
|
||||
initSelected = extras?.ignoredVersion == product.versionCode,
|
||||
onCheckedChanged = {
|
||||
ProductPreferences[product.packageName].let {
|
||||
it.copy(
|
||||
ignoreVersionCode =
|
||||
if (it.ignoreVersionCode == product.versionCode) 0 else product.versionCode
|
||||
)
|
||||
}
|
||||
viewModel.setIgnoredVersion(
|
||||
product.packageName,
|
||||
if (it) product.versionCode else 0
|
||||
)
|
||||
viewModel.updateActions()
|
||||
})
|
||||
}
|
||||
}
|
||||
item {
|
||||
AnimatedVisibility(visible = installed != null) {
|
||||
SwitchPreference(text = stringResource(id = R.string.ignore_all_updates),
|
||||
initSelected = ProductPreferences[product.packageName].ignoreVersionCode == product.versionCode,
|
||||
initSelected = extras?.ignoreUpdates == true,
|
||||
onCheckedChanged = {
|
||||
ProductPreferences[product.packageName].let {
|
||||
it.copy(
|
||||
ignoreUpdates = !it.ignoreUpdates
|
||||
)
|
||||
}
|
||||
viewModel.setIgnoreUpdates(product.packageName, it)
|
||||
viewModel.updateActions()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,18 @@ import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.looker.droidify.database.DatabaseX
|
||||
import com.looker.droidify.database.entity.Extras
|
||||
import com.looker.droidify.database.entity.Installed
|
||||
import com.looker.droidify.database.entity.Product
|
||||
import com.looker.droidify.database.entity.Repository
|
||||
import com.looker.droidify.entity.ActionState
|
||||
import com.looker.droidify.entity.DownloadState
|
||||
import com.looker.droidify.utility.findSuggestedProduct
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class AppViewModelX(val db: DatabaseX, val packageName: String) : ViewModel() {
|
||||
|
||||
@ -26,11 +32,111 @@ class AppViewModelX(val db: DatabaseX, val packageName: String) : ViewModel() {
|
||||
val mainAction = MutableLiveData<ActionState>()
|
||||
val actions = MutableLiveData<Set<ActionState>>()
|
||||
val secondaryAction = MutableLiveData<ActionState>()
|
||||
val extras = MediatorLiveData<Extras>()
|
||||
|
||||
init {
|
||||
products.addSource(db.productDao.getLive(packageName)) { products.setValue(it.filterNotNull()) }
|
||||
repositories.addSource(db.repositoryDao.allLive, repositories::setValue)
|
||||
installedItem.addSource(db.installedDao.getLive(packageName), installedItem::setValue)
|
||||
extras.addSource(db.extrasDao.getLive(packageName), extras::setValue)
|
||||
}
|
||||
|
||||
fun updateActions() {
|
||||
viewModelScope.launch {
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateUI() {
|
||||
withContext(Dispatchers.IO) {
|
||||
val installed = installedItem.value
|
||||
val productRepos = productRepos
|
||||
val product = findSuggestedProduct(productRepos, installed) { it.first }?.first
|
||||
val compatible = product != null && product.selectedReleases.firstOrNull()
|
||||
.let { it != null && it.incompatibilities.isEmpty() }
|
||||
val canInstall = product != null && installed == null && compatible
|
||||
val canUpdate =
|
||||
product != null && compatible && product.canUpdate(installed) &&
|
||||
!shouldIgnore(product.versionCode)
|
||||
val canUninstall = product != null && installed != null && !installed.isSystem
|
||||
val canLaunch =
|
||||
product != null && installed != null && installed.launcherActivities.isNotEmpty()
|
||||
val canShare = product != null && productRepos[0].second.name == "F-Droid"
|
||||
val bookmarked = extras.value?.favorite
|
||||
|
||||
val actions = mutableSetOf<ActionState>()
|
||||
launch {
|
||||
if (canInstall) actions += ActionState.Install
|
||||
if (canUpdate) actions += ActionState.Update
|
||||
if (canLaunch) actions += ActionState.Launch
|
||||
if (installed != null) actions += ActionState.Details
|
||||
if (canUninstall) actions += ActionState.Uninstall
|
||||
if (canShare) actions += ActionState.Share
|
||||
if (bookmarked == true) actions += ActionState.Bookmarked
|
||||
else actions += ActionState.Bookmark
|
||||
}
|
||||
val primaryAction = when {
|
||||
canUpdate -> ActionState.Update
|
||||
canLaunch -> ActionState.Launch
|
||||
canInstall -> ActionState.Install
|
||||
canShare -> ActionState.Share
|
||||
else -> null
|
||||
}
|
||||
val secondaryAction = when {
|
||||
primaryAction != ActionState.Share && canShare -> ActionState.Share
|
||||
primaryAction != ActionState.Launch && canLaunch -> ActionState.Launch
|
||||
installed != null && canUninstall -> ActionState.Uninstall
|
||||
else -> null
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
this@AppViewModelX.actions.value = actions
|
||||
|
||||
if (downloadState.value != null && mainAction.value?.textId != downloadState.value?.textId)
|
||||
downloadState.value?.let {
|
||||
mainAction.value = ActionState.Cancel(it.textId)
|
||||
}
|
||||
else if (downloadState.value == null)
|
||||
mainAction.value = primaryAction
|
||||
this@AppViewModelX.secondaryAction.value = secondaryAction
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun shouldIgnore(appVersionCode: Long): Boolean =
|
||||
extras.value?.ignoredVersion == appVersionCode && extras.value?.ignoreUpdates != false
|
||||
|
||||
fun setIgnoredVersion(packageName: String, versionCode: Long) {
|
||||
viewModelScope.launch {
|
||||
saveIgnoredVersion(packageName, versionCode)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveIgnoredVersion(packageName: String, versionCode: Long) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val oldValue = db.extrasDao[packageName]
|
||||
if (oldValue != null) db.extrasDao
|
||||
.insertReplace(oldValue.copy(ignoredVersion = versionCode))
|
||||
else db.extrasDao
|
||||
.insertReplace(Extras(packageName, ignoredVersion = versionCode))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun setIgnoreUpdates(packageName: String, setBoolean: Boolean) {
|
||||
viewModelScope.launch {
|
||||
saveIgnoreUpdates(packageName, setBoolean)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveIgnoreUpdates(packageName: String, setBoolean: Boolean) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val oldValue = db.extrasDao[packageName]
|
||||
if (oldValue != null) db.extrasDao
|
||||
.insertReplace(oldValue.copy(ignoreUpdates = setBoolean))
|
||||
else db.extrasDao
|
||||
.insertReplace(Extras(packageName, ignoreUpdates = setBoolean))
|
||||
}
|
||||
}
|
||||
|
||||
class Factory(val db: DatabaseX, val packageName: String) : ViewModelProvider.Factory {
|
||||
|
Loading…
x
Reference in New Issue
Block a user