Revision control
Copy as Markdown
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
package org.mozilla.reference.browser.addons
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import mozilla.components.feature.addons.Addon
import mozilla.components.feature.addons.AddonManagerException
import mozilla.components.feature.addons.ui.AddonsManagerAdapter
import mozilla.components.feature.addons.ui.AddonsManagerAdapterDelegate
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.reference.browser.R
import org.mozilla.reference.browser.ext.components
/**
* Fragment use for managing add-ons.
*/
class AddonsFragment : Fragment(), AddonsManagerAdapterDelegate {
private val webExtensionPromptFeature = ViewBoundFeatureWrapper<WebExtensionPromptFeature>()
private lateinit var recyclerView: RecyclerView
private val scope = CoroutineScope(Dispatchers.IO)
private lateinit var addons: List<Addon>
private var adapter: AddonsManagerAdapter? = null
private val addonProgressOverlay: View
get() = requireView().findViewById(R.id.addonProgressOverlay)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
return inflater.inflate(R.layout.fragment_add_ons, container, false)
}
override fun onViewCreated(rootView: View, savedInstanceState: Bundle?) {
super.onViewCreated(rootView, savedInstanceState)
bindRecyclerView(rootView)
webExtensionPromptFeature.set(
feature = WebExtensionPromptFeature(
store = requireContext().components.core.store,
context = requireContext(),
fragmentManager = parentFragmentManager,
),
owner = this,
view = rootView,
)
}
override fun onStart() {
super.onStart()
this@AddonsFragment.view?.let { view ->
bindRecyclerView(view)
}
addonProgressOverlay.visibility = View.GONE
}
private fun bindRecyclerView(rootView: View) {
recyclerView = rootView.findViewById(R.id.add_ons_list)
recyclerView.layoutManager = LinearLayoutManager(requireContext())
scope.launch {
try {
addons = requireContext().components.core.addonManager.getAddons()
scope.launch(Dispatchers.Main) {
adapter = AddonsManagerAdapter(
this@AddonsFragment,
addons,
store = requireContext().components.core.store,
)
recyclerView.adapter = adapter
}
} catch (e: AddonManagerException) {
scope.launch(Dispatchers.Main) {
Toast.makeText(
activity,
R.string.mozac_feature_addons_failed_to_query_extensions,
Toast.LENGTH_SHORT,
).show()
}
}
}
}
override fun onAddonItemClicked(addon: Addon) {
if (addon.isInstalled()) {
val intent = Intent(context, InstalledAddonDetailsActivity::class.java)
intent.putExtra("add_on", addon)
startActivity(intent)
} else {
val intent = Intent(context, AddonDetailsActivity::class.java)
intent.putExtra("add_on", addon)
startActivity(intent)
}
}
override fun onInstallAddonButtonClicked(addon: Addon) {
if (isInstallationInProgress) {
return
}
installAddon(addon)
}
private val installAddon: ((Addon) -> Unit) = { addon ->
addonProgressOverlay.visibility = View.VISIBLE
isInstallationInProgress = true
requireContext().components.core.addonManager.installAddon(
url = addon.downloadUrl,
onSuccess = {
runIfFragmentIsAttached {
isInstallationInProgress = false
this@AddonsFragment.view?.let { view ->
bindRecyclerView(view)
}
addonProgressOverlay.visibility = View.GONE
}
},
onError = { _ ->
runIfFragmentIsAttached {
addonProgressOverlay.visibility = View.GONE
isInstallationInProgress = false
}
},
)
}
/**
* Whether or not an add-on installation is in progress.
*/
private var isInstallationInProgress = false
}