mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-04-23 19:32:16 +00:00
Remove: Using AppDetailAdapter in AppSheet
This commit is contained in:
parent
31d988ed2e
commit
1920820f1d
@ -1,6 +1,9 @@
|
||||
package com.looker.droidify.ui.fragments
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
@ -8,32 +11,44 @@ import android.provider.Settings
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.looker.droidify.R
|
||||
import com.looker.droidify.content.Preferences
|
||||
import com.looker.droidify.content.ProductPreferences
|
||||
import com.looker.droidify.database.entity.Installed
|
||||
import com.looker.droidify.database.entity.Product
|
||||
import com.looker.droidify.database.entity.Release
|
||||
import com.looker.droidify.database.entity.Repository
|
||||
import com.looker.droidify.databinding.SheetAppXBinding
|
||||
import com.looker.droidify.entity.Action
|
||||
import com.looker.droidify.entity.Cancelable
|
||||
import com.looker.droidify.entity.Connecting
|
||||
import com.looker.droidify.entity.Details
|
||||
import com.looker.droidify.entity.Install
|
||||
import com.looker.droidify.entity.Launch
|
||||
import com.looker.droidify.entity.PackageState
|
||||
import com.looker.droidify.entity.Pending
|
||||
import com.looker.droidify.entity.ProductPreference
|
||||
import com.looker.droidify.entity.Screenshot
|
||||
import com.looker.droidify.entity.Share
|
||||
import com.looker.droidify.entity.Uninstall
|
||||
import com.looker.droidify.entity.Update
|
||||
import com.looker.droidify.installer.AppInstaller
|
||||
import com.looker.droidify.screen.MessageDialog
|
||||
import com.looker.droidify.screen.ScreenshotsFragment
|
||||
import com.looker.droidify.service.Connection
|
||||
import com.looker.droidify.service.DownloadService
|
||||
import com.looker.droidify.ui.activities.MainActivityX
|
||||
import com.looker.droidify.ui.adapters.AppDetailAdapter
|
||||
import com.looker.droidify.ui.compose.theme.AppTheme
|
||||
import com.looker.droidify.ui.compose.utils.Callbacks
|
||||
import com.looker.droidify.ui.viewmodels.AppViewModelX
|
||||
import com.looker.droidify.utility.Utils.rootInstallerEnabled
|
||||
import com.looker.droidify.utility.Utils.startUpdate
|
||||
import com.looker.droidify.utility.extension.android.Android
|
||||
import com.looker.droidify.utility.findSuggestedProduct
|
||||
import com.looker.droidify.utility.isDarkTheme
|
||||
import com.looker.droidify.utility.onLaunchClick
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
@ -43,10 +58,9 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
// TODO clean up and replace dropped functions from AppDetailFragment
|
||||
class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Callbacks {
|
||||
class AppSheetX() : FullscreenBottomSheetDialogFragment(), Callbacks {
|
||||
companion object {
|
||||
private const val EXTRA_PACKAGE_NAME = "packageName"
|
||||
private const val STATE_ADAPTER = "adapter"
|
||||
}
|
||||
|
||||
constructor(packageName: String) : this() {
|
||||
@ -55,7 +69,6 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var binding: SheetAppXBinding
|
||||
val viewModel: AppViewModelX by viewModels {
|
||||
AppViewModelX.Factory(mainActivityX.db, packageName)
|
||||
}
|
||||
@ -65,13 +78,7 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
val packageName: String
|
||||
get() = requireArguments().getString(EXTRA_PACKAGE_NAME)!!
|
||||
|
||||
private var actions = Pair(emptySet<Action>(), null as Action?)
|
||||
private var productRepos = emptyList<Pair<Product, Repository>>()
|
||||
private var products = emptyList<Product>()
|
||||
private var installed: Installed? = null
|
||||
private var downloading = false
|
||||
|
||||
private var productDisposable: Disposable? = null
|
||||
private val downloadConnection = Connection(DownloadService::class.java, onBind = { _, binder ->
|
||||
binder.stateSubject
|
||||
.filter { it.packageName == packageName }
|
||||
@ -86,83 +93,53 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = SheetAppXBinding.inflate(layoutInflater)
|
||||
binding.lifecycleOwner = this
|
||||
super.onCreate(savedInstanceState)
|
||||
setupAdapters()
|
||||
return binding.root
|
||||
}
|
||||
|
||||
private fun setupAdapters() {
|
||||
downloadConnection.bind(requireContext())
|
||||
|
||||
binding.recyclerView.apply {
|
||||
id = android.R.id.list
|
||||
this.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
||||
this.adapter = AppDetailAdapter(this@AppSheetX)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setupLayout() {
|
||||
// TODO simplify observing and updating
|
||||
viewModel.installedItem.observe(viewLifecycleOwner) {
|
||||
installed = it
|
||||
updateSheet()
|
||||
}
|
||||
|
||||
viewModel.repositories.observe(viewLifecycleOwner) {
|
||||
if (it.isNotEmpty() && products.isNotEmpty()) updateSheet()
|
||||
}
|
||||
viewModel.products.observe(viewLifecycleOwner) {
|
||||
products = it.filterNotNull()
|
||||
viewModel.repositories.value?.let { repos ->
|
||||
if (repos.isNotEmpty() && products.isNotEmpty()) updateSheet()
|
||||
return ComposeView(requireContext()).apply {
|
||||
setContent {
|
||||
AppTheme(
|
||||
darkTheme = when (Preferences[Preferences.Key.Theme]) {
|
||||
is Preferences.Theme.System -> isSystemInDarkTheme()
|
||||
is Preferences.Theme.AmoledSystem -> isSystemInDarkTheme()
|
||||
else -> isDarkTheme
|
||||
}
|
||||
) {
|
||||
AppSheet()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateSheet() {
|
||||
products.mapNotNull { product ->
|
||||
viewModel.repositories.value
|
||||
?.firstOrNull { it.id == product.repositoryId }
|
||||
?.let { Pair(product, it) }
|
||||
}.apply {
|
||||
productRepos = this
|
||||
private fun setupAdapters() {
|
||||
downloadConnection.bind(requireContext())
|
||||
}
|
||||
|
||||
val adapter = binding.recyclerView.adapter as AppDetailAdapter
|
||||
adapter.setProducts(
|
||||
binding.recyclerView.context,
|
||||
packageName,
|
||||
this,
|
||||
installed
|
||||
)
|
||||
override fun setupLayout() {
|
||||
viewModel._productRepos.observe(this) {
|
||||
lifecycleScope.launch {
|
||||
updateButtons()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateSheet() {
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
|
||||
productDisposable?.dispose()
|
||||
productDisposable = null
|
||||
downloadConnection.unbind(requireContext())
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
|
||||
val adapterState = (binding.recyclerView.adapter as? AppDetailAdapter)?.saveState()
|
||||
adapterState?.let { outState.putParcelable(STATE_ADAPTER, it) }
|
||||
}
|
||||
|
||||
private suspend fun updateButtons() {
|
||||
updateButtons(ProductPreferences[packageName])
|
||||
}
|
||||
|
||||
// TODO rename to updateActions
|
||||
private suspend fun updateButtons(preference: ProductPreference) =
|
||||
withContext(Dispatchers.Default) {
|
||||
val installed = installed
|
||||
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() }
|
||||
@ -175,80 +152,76 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
product != null && installed != null && installed.launcherActivities.isNotEmpty()
|
||||
val canShare = product != null && productRepos[0].second.name == "F-Droid"
|
||||
|
||||
val actions = mutableSetOf<Action>()
|
||||
val actions = mutableSetOf<PackageState>()
|
||||
launch {
|
||||
if (canInstall) {
|
||||
actions += Action.INSTALL
|
||||
actions += Install
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (canUpdate) {
|
||||
actions += Action.UPDATE
|
||||
actions += Update
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (canLaunch) {
|
||||
actions += Action.LAUNCH
|
||||
actions += Launch
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (installed != null) {
|
||||
actions += Action.DETAILS
|
||||
actions += Details
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (canUninstall) {
|
||||
actions += Action.UNINSTALL
|
||||
actions += Uninstall
|
||||
}
|
||||
}
|
||||
launch {
|
||||
if (canShare) {
|
||||
actions += Action.SHARE
|
||||
actions += Share
|
||||
}
|
||||
}
|
||||
val primaryAction = when {
|
||||
canUpdate -> Action.UPDATE
|
||||
canLaunch -> Action.LAUNCH
|
||||
canInstall -> Action.INSTALL
|
||||
canShare -> Action.SHARE
|
||||
canUpdate -> Update
|
||||
canLaunch -> Launch
|
||||
canInstall -> Install
|
||||
canShare -> Share
|
||||
else -> null
|
||||
}
|
||||
val secondaryAction = when {
|
||||
primaryAction != Action.SHARE && canShare -> Action.SHARE
|
||||
primaryAction != Action.LAUNCH && canLaunch -> Action.LAUNCH
|
||||
installed != null && canUninstall -> Action.UNINSTALL
|
||||
primaryAction != Share && canShare -> Share
|
||||
primaryAction != Launch && canLaunch -> Launch
|
||||
installed != null && canUninstall -> Uninstall
|
||||
else -> null
|
||||
}
|
||||
|
||||
launch(Dispatchers.Main) {
|
||||
val adapterAction =
|
||||
if (downloading) Action.CANCEL else primaryAction
|
||||
val adapterSecondaryAction =
|
||||
if (downloading) null else secondaryAction
|
||||
(binding.recyclerView.adapter as? AppDetailAdapter)
|
||||
?.setAction(adapterAction)
|
||||
(binding.recyclerView.adapter as? AppDetailAdapter)
|
||||
?.setSecondaryAction(adapterSecondaryAction)
|
||||
withContext(Dispatchers.Main) {
|
||||
viewModel.actions.value = actions
|
||||
if (!downloading) {
|
||||
viewModel.state.value = primaryAction
|
||||
viewModel.secondaryAction.value = secondaryAction
|
||||
} else {
|
||||
viewModel.secondaryAction.value = null
|
||||
}
|
||||
}
|
||||
launch { this@AppSheetX.actions = Pair(actions, primaryAction) }
|
||||
}
|
||||
|
||||
private suspend fun updateDownloadState(state: DownloadService.State?) {
|
||||
val status = when (state) {
|
||||
is DownloadService.State.Pending -> AppDetailAdapter.Status.Pending
|
||||
is DownloadService.State.Connecting -> AppDetailAdapter.Status.Connecting
|
||||
is DownloadService.State.Downloading -> AppDetailAdapter.Status.Downloading(
|
||||
is DownloadService.State.Pending -> Pending
|
||||
is DownloadService.State.Connecting -> Connecting
|
||||
is DownloadService.State.Downloading -> com.looker.droidify.entity.Downloading(
|
||||
state.read,
|
||||
state.total
|
||||
)
|
||||
is DownloadService.State.Success, is DownloadService.State.Error, is DownloadService.State.Cancel, null -> null
|
||||
else -> null
|
||||
}
|
||||
val downloading = status != null
|
||||
if (this.downloading != downloading) {
|
||||
this.downloading = downloading
|
||||
updateButtons()
|
||||
}
|
||||
(binding.recyclerView.adapter as? AppDetailAdapter)?.setStatus(status)
|
||||
val downloading = status is Cancelable
|
||||
this.downloading = downloading
|
||||
updateButtons()
|
||||
viewModel.state.value = status
|
||||
if (state is DownloadService.State.Success && isResumed && !rootInstallerEnabled) {
|
||||
withContext(Dispatchers.Default) {
|
||||
AppInstaller.getInstance(context)?.defaultInstaller?.install(state.release.cacheFileName)
|
||||
@ -256,12 +229,13 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActionClick(action: Action) {
|
||||
override fun onActionClick(action: PackageState?) {
|
||||
val productRepos = viewModel.productRepos
|
||||
when (action) {
|
||||
Action.INSTALL,
|
||||
Action.UPDATE,
|
||||
Install,
|
||||
Update,
|
||||
-> {
|
||||
val installedItem = installed
|
||||
val installedItem = viewModel.installedItem.value
|
||||
lifecycleScope.launch {
|
||||
startUpdate(
|
||||
packageName,
|
||||
@ -272,31 +246,37 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
}
|
||||
Unit
|
||||
}
|
||||
Action.LAUNCH -> {
|
||||
installed?.let { requireContext().onLaunchClick(it, childFragmentManager) }
|
||||
Launch -> {
|
||||
viewModel.installedItem.value?.let {
|
||||
requireContext().onLaunchClick(
|
||||
it,
|
||||
childFragmentManager
|
||||
)
|
||||
}
|
||||
Unit
|
||||
}
|
||||
Action.DETAILS -> {
|
||||
Details -> {
|
||||
startActivity(
|
||||
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
.setData(Uri.parse("package:$packageName"))
|
||||
)
|
||||
}
|
||||
Action.UNINSTALL -> {
|
||||
Uninstall -> {
|
||||
lifecycleScope.launch {
|
||||
AppInstaller.getInstance(context)?.defaultInstaller?.uninstall(packageName)
|
||||
}
|
||||
Unit
|
||||
}
|
||||
Action.CANCEL -> {
|
||||
is Cancelable -> {
|
||||
val binder = downloadConnection.binder
|
||||
if (downloading && binder != null) {
|
||||
binder.cancel(packageName)
|
||||
} else Unit
|
||||
}
|
||||
Action.SHARE -> {
|
||||
Share -> {
|
||||
shareIntent(packageName, productRepos[0].first.label)
|
||||
}
|
||||
else -> Unit
|
||||
}::class
|
||||
}
|
||||
|
||||
@ -325,8 +305,9 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
)
|
||||
}
|
||||
|
||||
// TODO fix in compose implementation
|
||||
override fun onScreenshotClick(screenshot: Screenshot) {
|
||||
val pair = productRepos.asSequence()
|
||||
val pair = viewModel.productRepos.asSequence()
|
||||
.map { it ->
|
||||
Pair(
|
||||
it.second,
|
||||
@ -345,7 +326,7 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
}
|
||||
|
||||
override fun onReleaseClick(release: Release) {
|
||||
val installedItem = installed
|
||||
val installedItem = viewModel.installedItem.value
|
||||
when {
|
||||
release.incompatibilities.isNotEmpty() -> {
|
||||
MessageDialog(
|
||||
@ -365,7 +346,7 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
}
|
||||
else -> {
|
||||
val productRepository =
|
||||
productRepos.asSequence()
|
||||
viewModel.productRepos.asSequence()
|
||||
.filter { it -> it.first.releases.any { it === release } }
|
||||
.firstOrNull()
|
||||
if (productRepository != null) {
|
||||
@ -392,4 +373,17 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyLinkToClipboard(view: View, link: String) {
|
||||
val clipboardManager =
|
||||
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clipboardManager.setPrimaryClip(ClipData.newPlainText(null, link))
|
||||
Snackbar.make(view, R.string.link_copied_to_clipboard, Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AppSheet() {
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user