mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-04-23 19:32:16 +00:00
Remove: AppDetailFragment
This commit is contained in:
parent
1477fba932
commit
c1e3d857f3
@ -1,604 +0,0 @@
|
|||||||
package com.looker.droidify.ui.fragments
|
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.pm.ApplicationInfo
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.provider.Settings
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.View
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.fragment.app.DialogFragment
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import com.looker.droidify.R
|
|
||||||
import com.looker.droidify.content.ProductPreferences
|
|
||||||
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.entity.ProductPreference
|
|
||||||
import com.looker.droidify.entity.Screenshot
|
|
||||||
import com.looker.droidify.installer.AppInstaller
|
|
||||||
import com.looker.droidify.screen.MessageDialog
|
|
||||||
import com.looker.droidify.screen.ScreenFragment
|
|
||||||
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.utility.RxUtils
|
|
||||||
import com.looker.droidify.utility.Utils
|
|
||||||
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.extension.text.trimAfter
|
|
||||||
import com.looker.droidify.utility.findSuggestedProduct
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|
||||||
import io.reactivex.rxjava3.core.Observable
|
|
||||||
import io.reactivex.rxjava3.disposables.Disposable
|
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.filter
|
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
|
|
||||||
private val screenActivity: MainActivityX
|
|
||||||
get() = requireActivity() as MainActivityX
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val EXTRA_PACKAGE_NAME = "packageName"
|
|
||||||
private const val STATE_LAYOUT_MANAGER = "layoutManager"
|
|
||||||
private const val STATE_ADAPTER = "adapter"
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(packageName: String) : this() {
|
|
||||||
arguments = Bundle().apply {
|
|
||||||
putString(EXTRA_PACKAGE_NAME, packageName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Nullable<T>(val value: T?)
|
|
||||||
|
|
||||||
private enum class Action(
|
|
||||||
val id: Int,
|
|
||||||
val adapterAction: AppDetailAdapter.Action,
|
|
||||||
) {
|
|
||||||
INSTALL(1, AppDetailAdapter.Action.INSTALL),
|
|
||||||
UPDATE(2, AppDetailAdapter.Action.UPDATE),
|
|
||||||
LAUNCH(3, AppDetailAdapter.Action.LAUNCH),
|
|
||||||
DETAILS(4, AppDetailAdapter.Action.DETAILS),
|
|
||||||
UNINSTALL(5, AppDetailAdapter.Action.UNINSTALL),
|
|
||||||
SHARE(6, AppDetailAdapter.Action.SHARE)
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Installed(
|
|
||||||
val data: com.looker.droidify.database.entity.Installed, val isSystem: Boolean,
|
|
||||||
val launcherActivities: List<Pair<String, String>>,
|
|
||||||
)
|
|
||||||
|
|
||||||
val packageName: String
|
|
||||||
get() = requireArguments().getString(EXTRA_PACKAGE_NAME)!!
|
|
||||||
|
|
||||||
private var layoutManagerState: LinearLayoutManager.SavedState? = null
|
|
||||||
|
|
||||||
private var actions = Pair(emptySet<Action>(), null as Action?)
|
|
||||||
private var products = emptyList<Pair<Product, Repository>>()
|
|
||||||
private var installed: Installed? = null
|
|
||||||
private var downloading = false
|
|
||||||
|
|
||||||
private var recyclerView: RecyclerView? = null
|
|
||||||
|
|
||||||
private var productDisposable: Disposable? = null
|
|
||||||
private val downloadConnection = Connection(DownloadService::class.java, onBind = { _, binder ->
|
|
||||||
binder.stateSubject
|
|
||||||
.filter { it.packageName == packageName }
|
|
||||||
.flowOn(Dispatchers.Default)
|
|
||||||
.onEach { updateDownloadState(it) }
|
|
||||||
.flowOn(Dispatchers.Main)
|
|
||||||
.launchIn(lifecycleScope)
|
|
||||||
})
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
toolbar.menu.apply {
|
|
||||||
for (action in Action.values()) {
|
|
||||||
add(0, action.id, 0, action.adapterAction.titleResId)
|
|
||||||
.setIcon(Utils.getToolbarIcon(toolbar.context, action.adapterAction.iconResId))
|
|
||||||
.setVisible(false)
|
|
||||||
.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
|
||||||
.setOnMenuItemClickListener {
|
|
||||||
onActionClick(action.adapterAction)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val content = fragmentBinding.fragmentContent
|
|
||||||
content.addView(RecyclerView(content.context).apply {
|
|
||||||
id = android.R.id.list
|
|
||||||
this.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
|
||||||
isMotionEventSplittingEnabled = false
|
|
||||||
isVerticalScrollBarEnabled = false
|
|
||||||
val adapter = AppDetailAdapter(this@AppDetailFragment)
|
|
||||||
this.adapter = adapter
|
|
||||||
addOnScrollListener(scrollListener)
|
|
||||||
savedInstanceState?.getParcelable<AppDetailAdapter.SavedState>(STATE_ADAPTER)
|
|
||||||
?.let(adapter::restoreState)
|
|
||||||
layoutManagerState = savedInstanceState?.getParcelable(STATE_LAYOUT_MANAGER)
|
|
||||||
recyclerView = this
|
|
||||||
})
|
|
||||||
|
|
||||||
var first = true
|
|
||||||
productDisposable = Observable.just(Unit)
|
|
||||||
//.concatWith(Database.observable(Database.Subject.Products)) // TODO have to be replaced like whole rxJava
|
|
||||||
.observeOn(Schedulers.io())
|
|
||||||
.flatMapSingle {
|
|
||||||
RxUtils.querySingle {
|
|
||||||
screenActivity.db.productDao.get(packageName).filterNotNull()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.flatMapSingle { products ->
|
|
||||||
RxUtils
|
|
||||||
.querySingle { screenActivity.db.repositoryDao.all }
|
|
||||||
.map { it ->
|
|
||||||
it.asSequence().map { Pair(it.id, it) }.toMap()
|
|
||||||
.let {
|
|
||||||
products.mapNotNull { product ->
|
|
||||||
it[product.repositoryId]?.let {
|
|
||||||
Pair(
|
|
||||||
product,
|
|
||||||
it
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.flatMapSingle { products ->
|
|
||||||
RxUtils
|
|
||||||
.querySingle { Nullable(screenActivity.db.installedDao.get(packageName)) }
|
|
||||||
.map { Pair(products, it) }
|
|
||||||
}
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe { it ->
|
|
||||||
val (products, installedItem) = it
|
|
||||||
val firstChanged = first
|
|
||||||
first = false
|
|
||||||
val productChanged = this.products != products
|
|
||||||
val installedItemChanged = this.installed?.data != installedItem.value
|
|
||||||
if (firstChanged || productChanged || installedItemChanged) {
|
|
||||||
layoutManagerState?.let {
|
|
||||||
recyclerView?.layoutManager!!.onRestoreInstanceState(
|
|
||||||
it
|
|
||||||
)
|
|
||||||
}
|
|
||||||
layoutManagerState = null
|
|
||||||
if (firstChanged || productChanged) {
|
|
||||||
this.products = products
|
|
||||||
}
|
|
||||||
if (firstChanged || installedItemChanged) {
|
|
||||||
installed = installedItem.value?.let {
|
|
||||||
val isSystem = try {
|
|
||||||
((requireContext().packageManager.getApplicationInfo(
|
|
||||||
packageName,
|
|
||||||
0
|
|
||||||
).flags)
|
|
||||||
and ApplicationInfo.FLAG_SYSTEM) != 0
|
|
||||||
} catch (e: Exception) {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
val launcherActivities =
|
|
||||||
if (packageName == requireContext().packageName) {
|
|
||||||
// Don't allow to launch self
|
|
||||||
emptyList()
|
|
||||||
} else {
|
|
||||||
val packageManager = requireContext().packageManager
|
|
||||||
packageManager
|
|
||||||
.queryIntentActivities(
|
|
||||||
Intent(Intent.ACTION_MAIN).addCategory(
|
|
||||||
Intent.CATEGORY_LAUNCHER
|
|
||||||
), 0
|
|
||||||
)
|
|
||||||
.asSequence()
|
|
||||||
.mapNotNull { resolveInfo -> resolveInfo.activityInfo }
|
|
||||||
.filter { activityInfo -> activityInfo.packageName == packageName }
|
|
||||||
.mapNotNull { activityInfo ->
|
|
||||||
val label = try {
|
|
||||||
activityInfo.loadLabel(packageManager).toString()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
label?.let { labelName ->
|
|
||||||
Pair(
|
|
||||||
activityInfo.name,
|
|
||||||
labelName
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.toList()
|
|
||||||
}
|
|
||||||
Installed(it, isSystem, launcherActivities)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val recyclerView = recyclerView!!
|
|
||||||
val adapter = recyclerView.adapter as AppDetailAdapter
|
|
||||||
if (firstChanged || productChanged || installedItemChanged) {
|
|
||||||
adapter.setProducts(
|
|
||||||
recyclerView.context,
|
|
||||||
packageName,
|
|
||||||
products,
|
|
||||||
installedItem.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
lifecycleScope.launch { updateButtons() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadConnection.bind(requireContext())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
super.onDestroyView()
|
|
||||||
recyclerView = null
|
|
||||||
|
|
||||||
productDisposable?.dispose()
|
|
||||||
productDisposable = null
|
|
||||||
downloadConnection.unbind(requireContext())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
|
||||||
super.onSaveInstanceState(outState)
|
|
||||||
|
|
||||||
val layoutManagerState =
|
|
||||||
layoutManagerState ?: recyclerView?.layoutManager?.onSaveInstanceState()
|
|
||||||
layoutManagerState?.let { outState.putParcelable(STATE_LAYOUT_MANAGER, it) }
|
|
||||||
val adapterState = (recyclerView?.adapter as? AppDetailAdapter)?.saveState()
|
|
||||||
adapterState?.let { outState.putParcelable(STATE_ADAPTER, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun updateButtons() {
|
|
||||||
updateButtons(ProductPreferences[packageName])
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun updateButtons(preference: ProductPreference) =
|
|
||||||
withContext(Dispatchers.Default) {
|
|
||||||
val installed = installed
|
|
||||||
val product = findSuggestedProduct(products, installed?.data) { 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?.data) &&
|
|
||||||
!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 && products[0].second.name == "F-Droid"
|
|
||||||
|
|
||||||
val actions = mutableSetOf<Action>()
|
|
||||||
launch {
|
|
||||||
if (canInstall) {
|
|
||||||
actions += Action.INSTALL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch {
|
|
||||||
if (canUpdate) {
|
|
||||||
actions += Action.UPDATE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch {
|
|
||||||
if (canLaunch) {
|
|
||||||
actions += Action.LAUNCH
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch {
|
|
||||||
if (installed != null) {
|
|
||||||
actions += Action.DETAILS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch {
|
|
||||||
if (canUninstall) {
|
|
||||||
actions += Action.UNINSTALL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch {
|
|
||||||
if (canShare) {
|
|
||||||
actions += Action.SHARE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val primaryAction = when {
|
|
||||||
canUpdate -> Action.UPDATE
|
|
||||||
canLaunch -> Action.LAUNCH
|
|
||||||
canInstall -> Action.INSTALL
|
|
||||||
installed != null -> Action.DETAILS
|
|
||||||
canShare -> Action.SHARE
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
|
||||||
val adapterAction =
|
|
||||||
if (downloading) AppDetailAdapter.Action.CANCEL else primaryAction?.adapterAction
|
|
||||||
(recyclerView?.adapter as? AppDetailAdapter)?.setAction(adapterAction)
|
|
||||||
for (action in sequenceOf(
|
|
||||||
Action.INSTALL,
|
|
||||||
Action.SHARE,
|
|
||||||
Action.UPDATE,
|
|
||||||
Action.UNINSTALL
|
|
||||||
)) {
|
|
||||||
toolbar.menu.findItem(action.id).isEnabled = !downloading
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch { this@AppDetailFragment.actions = Pair(actions, primaryAction) }
|
|
||||||
launch(Dispatchers.Main) { updateToolbarButtons() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun updateToolbarTitle() {
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
val showPackageName = recyclerView
|
|
||||||
?.let { (it.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() != 0 } == true
|
|
||||||
launch {
|
|
||||||
collapsingToolbar.title =
|
|
||||||
if (showPackageName) products[0].first.label.trimAfter(' ', 2)
|
|
||||||
else getString(R.string.application)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun updateToolbarButtons() {
|
|
||||||
withContext(Dispatchers.Default) {
|
|
||||||
val (actions, primaryAction) = actions
|
|
||||||
val showPrimaryAction = recyclerView
|
|
||||||
?.let { (it.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() != 0 } == true
|
|
||||||
val displayActions = actions.toMutableSet()
|
|
||||||
launch {
|
|
||||||
if (!showPrimaryAction && primaryAction != null) {
|
|
||||||
displayActions -= primaryAction
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch {
|
|
||||||
if (displayActions.size >= 4 && resources.configuration.screenWidthDp < 400) {
|
|
||||||
displayActions -= Action.DETAILS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
|
||||||
for (action in Action.values())
|
|
||||||
toolbar.menu.findItem(action.id).isVisible = action in displayActions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
|
||||||
state.read,
|
|
||||||
state.total
|
|
||||||
)
|
|
||||||
is DownloadService.State.Success, is DownloadService.State.Error, is DownloadService.State.Cancel, null -> null
|
|
||||||
}
|
|
||||||
val downloading = status != null
|
|
||||||
if (this.downloading != downloading) {
|
|
||||||
this.downloading = downloading
|
|
||||||
updateButtons()
|
|
||||||
}
|
|
||||||
(recyclerView?.adapter as? AppDetailAdapter)?.setStatus(status)
|
|
||||||
if (state is DownloadService.State.Success && isResumed && !rootInstallerEnabled) {
|
|
||||||
withContext(Dispatchers.Default) {
|
|
||||||
AppInstaller.getInstance(context)?.defaultInstaller?.install(state.release.cacheFileName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val scrollListener = object : RecyclerView.OnScrollListener() {
|
|
||||||
private var lastPosition = -1
|
|
||||||
|
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
|
||||||
val position =
|
|
||||||
(recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
|
|
||||||
val lastPosition = lastPosition
|
|
||||||
this.lastPosition = position
|
|
||||||
if ((lastPosition == 0) != (position == 0)) {
|
|
||||||
lifecycleScope.launch {
|
|
||||||
launch { updateToolbarTitle() }
|
|
||||||
launch { updateToolbarButtons() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActionClick(action: AppDetailAdapter.Action) {
|
|
||||||
when (action) {
|
|
||||||
AppDetailAdapter.Action.INSTALL,
|
|
||||||
AppDetailAdapter.Action.UPDATE,
|
|
||||||
-> {
|
|
||||||
val installedItem = installed?.data
|
|
||||||
lifecycleScope.launch {
|
|
||||||
startUpdate(
|
|
||||||
packageName,
|
|
||||||
installedItem,
|
|
||||||
products,
|
|
||||||
downloadConnection
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Unit
|
|
||||||
}
|
|
||||||
AppDetailAdapter.Action.LAUNCH -> {
|
|
||||||
val launcherActivities = installed?.launcherActivities.orEmpty()
|
|
||||||
if (launcherActivities.size >= 2) {
|
|
||||||
LaunchDialog(launcherActivities).show(
|
|
||||||
childFragmentManager,
|
|
||||||
LaunchDialog::class.java.name
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
launcherActivities.firstOrNull()?.let { startLauncherActivity(it.first) }
|
|
||||||
}
|
|
||||||
Unit
|
|
||||||
}
|
|
||||||
AppDetailAdapter.Action.DETAILS -> {
|
|
||||||
startActivity(
|
|
||||||
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
|
||||||
.setData(Uri.parse("package:$packageName"))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
AppDetailAdapter.Action.UNINSTALL -> {
|
|
||||||
lifecycleScope.launch {
|
|
||||||
AppInstaller.getInstance(context)?.defaultInstaller?.uninstall(packageName)
|
|
||||||
}
|
|
||||||
Unit
|
|
||||||
}
|
|
||||||
AppDetailAdapter.Action.CANCEL -> {
|
|
||||||
val binder = downloadConnection.binder
|
|
||||||
if (downloading && binder != null) {
|
|
||||||
binder.cancel(packageName)
|
|
||||||
} else Unit
|
|
||||||
}
|
|
||||||
AppDetailAdapter.Action.SHARE -> {
|
|
||||||
shareIntent(packageName, products[0].first.label)
|
|
||||||
}
|
|
||||||
}::class
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startLauncherActivity(name: String) {
|
|
||||||
try {
|
|
||||||
startActivity(
|
|
||||||
Intent(Intent.ACTION_MAIN)
|
|
||||||
.addCategory(Intent.CATEGORY_LAUNCHER)
|
|
||||||
.setComponent(ComponentName(packageName, name))
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun shareIntent(packageName: String, appName: String) {
|
|
||||||
val shareIntent = Intent(Intent.ACTION_SEND)
|
|
||||||
val extraText = if (Android.sdk(24)) {
|
|
||||||
"https://www.f-droid.org/${resources.configuration.locales[0].language}/packages/${packageName}/"
|
|
||||||
} else "https://www.f-droid.org/${resources.configuration.locale.language}/packages/${packageName}/"
|
|
||||||
|
|
||||||
|
|
||||||
shareIntent.type = "text/plain"
|
|
||||||
shareIntent.putExtra(Intent.EXTRA_TITLE, appName)
|
|
||||||
shareIntent.putExtra(Intent.EXTRA_SUBJECT, appName)
|
|
||||||
shareIntent.putExtra(Intent.EXTRA_TEXT, extraText)
|
|
||||||
|
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onScreenshotClick(screenshot: Screenshot) {
|
|
||||||
val pair = products.asSequence()
|
|
||||||
.map { it ->
|
|
||||||
Pair(
|
|
||||||
it.second,
|
|
||||||
it.first.screenshots.find { it === screenshot }?.identifier
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.filter { it.second != null }.firstOrNull()
|
|
||||||
if (pair != null) {
|
|
||||||
val (repository, identifier) = pair
|
|
||||||
if (identifier != null) {
|
|
||||||
ScreenshotsFragment(packageName, repository.id, identifier).show(
|
|
||||||
childFragmentManager
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReleaseClick(release: Release) {
|
|
||||||
val installedItem = installed?.data
|
|
||||||
when {
|
|
||||||
release.incompatibilities.isNotEmpty() -> {
|
|
||||||
MessageDialog(
|
|
||||||
MessageDialog.Message.ReleaseIncompatible(
|
|
||||||
release.incompatibilities,
|
|
||||||
release.platforms, release.minSdkVersion, release.maxSdkVersion
|
|
||||||
)
|
|
||||||
).show(childFragmentManager)
|
|
||||||
}
|
|
||||||
installedItem != null && installedItem.versionCode > release.versionCode -> {
|
|
||||||
MessageDialog(MessageDialog.Message.ReleaseOlder).show(childFragmentManager)
|
|
||||||
}
|
|
||||||
installedItem != null && installedItem.signature != release.signature -> {
|
|
||||||
MessageDialog(MessageDialog.Message.ReleaseSignatureMismatch).show(
|
|
||||||
childFragmentManager
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
val productRepository =
|
|
||||||
products.asSequence().filter { it -> it.first.releases.any { it === release } }
|
|
||||||
.firstOrNull()
|
|
||||||
if (productRepository != null) {
|
|
||||||
downloadConnection.binder?.enqueue(
|
|
||||||
packageName, productRepository.first.label,
|
|
||||||
productRepository.second, release
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onUriClick(uri: Uri, shouldConfirm: Boolean): Boolean {
|
|
||||||
return if (shouldConfirm && (uri.scheme == "http" || uri.scheme == "https")) {
|
|
||||||
MessageDialog(MessageDialog.Message.Link(uri)).show(childFragmentManager)
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
startActivity(Intent(Intent.ACTION_VIEW, uri))
|
|
||||||
true
|
|
||||||
} catch (e: ActivityNotFoundException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LaunchDialog() : DialogFragment() {
|
|
||||||
companion object {
|
|
||||||
private const val EXTRA_NAMES = "names"
|
|
||||||
private const val EXTRA_LABELS = "labels"
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(launcherActivities: List<Pair<String, String>>) : this() {
|
|
||||||
arguments = Bundle().apply {
|
|
||||||
putStringArrayList(EXTRA_NAMES, ArrayList(launcherActivities.map { it.first }))
|
|
||||||
putStringArrayList(EXTRA_LABELS, ArrayList(launcherActivities.map { it.second }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): AlertDialog {
|
|
||||||
val names = requireArguments().getStringArrayList(EXTRA_NAMES)!!
|
|
||||||
val labels = requireArguments().getStringArrayList(EXTRA_LABELS)!!
|
|
||||||
return MaterialAlertDialogBuilder(requireContext())
|
|
||||||
.setTitle(R.string.launch)
|
|
||||||
.setItems(labels.toTypedArray()) { _, position ->
|
|
||||||
(parentFragment as AppDetailFragment)
|
|
||||||
.startLauncherActivity(names[position])
|
|
||||||
}
|
|
||||||
.setNegativeButton(R.string.cancel, null)
|
|
||||||
.create()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user