Merge remote-tracking branch 'abhijitvalluri/addons_search' into fork

pull/58/head
Adam Novak 4 years ago
commit 7b49b4ec30

@ -115,9 +115,6 @@ android {
// Need to replicate default debug config features // Need to replicate default debug config features
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
debuggable true debuggable true
// Use custom allowed addon list
buildConfigField "String", "AMO_ACCOUNT", "\"16201230\""
buildConfigField "String", "AMO_COLLECTION", "\"What-I-want-on-Fenix\""
} }
forkRelease releaseTemplate >> { forkRelease releaseTemplate >> {
buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true" buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
@ -127,9 +124,6 @@ android {
manifestPlaceholders = [ manifestPlaceholders = [
"deepLinkScheme": deepLinkSchemeValue "deepLinkScheme": deepLinkSchemeValue
] ]
// Use custom allowed addon list
buildConfigField "String", "AMO_ACCOUNT", "\"16201230\""
buildConfigField "String", "AMO_COLLECTION", "\"What-I-want-on-Fenix\""
} }
} }

@ -62,8 +62,8 @@ class PagedAddonCollectionProvider(
private val context: Context, private val context: Context,
private val client: Client, private val client: Client,
private val serverURL: String = DEFAULT_SERVER_URL, private val serverURL: String = DEFAULT_SERVER_URL,
private val collectionAccount: String = DEFAULT_COLLECTION_ACCOUNT, private var collectionAccount: String = DEFAULT_COLLECTION_ACCOUNT,
private val collectionName: String = DEFAULT_COLLECTION_NAME, private var collectionName: String = DEFAULT_COLLECTION_NAME,
private val maxCacheAgeInMinutes: Long = -1 private val maxCacheAgeInMinutes: Long = -1
) : AddonsProvider { ) : AddonsProvider {
@ -71,6 +71,14 @@ class PagedAddonCollectionProvider(
private val diskCacheLock = Any() private val diskCacheLock = Any()
fun setCollectionAccount(account: String) {
collectionAccount = account
}
fun setCollectionName(collection: String) {
collectionName = collection
}
/** /**
* Interacts with the collections endpoint to provide a list of available * Interacts with the collections endpoint to provide a list of available
* add-ons. May return a cached response, if available, not expired (see * add-ons. May return a cached response, if available, not expired (see
@ -216,6 +224,11 @@ class PagedAddonCollectionProvider(
private fun getBaseCacheFile(context: Context): File { private fun getBaseCacheFile(context: Context): File {
return File(context.filesDir, COLLECTION_FILE_NAME.format(collectionAccount, collectionName)) return File(context.filesDir, COLLECTION_FILE_NAME.format(collectionAccount, collectionName))
} }
fun deleteCacheFile(context: Context): Boolean {
val file = getBaseCacheFile(context)
return if (file.exists()) file.delete() else false
}
} }
internal fun JSONObject.getAddons(): List<Addon> { internal fun JSONObject.getAddons(): List<Addon> {

@ -6,9 +6,10 @@ package org.mozilla.fenix.addons
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.Gravity import android.view.*
import android.view.View
import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityEvent
import android.view.inputmethod.EditorInfo
import androidx.appcompat.widget.SearchView
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -23,8 +24,6 @@ import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import mozilla.components.feature.addons.Addon import mozilla.components.feature.addons.Addon
import mozilla.components.feature.addons.AddonManagerException import mozilla.components.feature.addons.AddonManagerException
import mozilla.components.feature.addons.ui.AddonInstallationDialogFragment
import mozilla.components.feature.addons.ui.AddonsManagerAdapter
import mozilla.components.feature.addons.ui.PermissionsDialogFragment import mozilla.components.feature.addons.ui.PermissionsDialogFragment
import mozilla.components.feature.addons.ui.translatedName import mozilla.components.feature.addons.ui.translatedName
import network.novak.fenix.components.PagedAddonsManagerAdapter import network.novak.fenix.components.PagedAddonsManagerAdapter
@ -37,6 +36,7 @@ import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.theme.ThemeManager
import java.util.Locale
import java.util.concurrent.CancellationException import java.util.concurrent.CancellationException
/** /**
@ -50,12 +50,76 @@ class AddonsManagementFragment : Fragment(R.layout.fragment_add_ons_management)
*/ */
private var isInstallationInProgress = false private var isInstallationInProgress = false
private var adapter: PagedAddonsManagerAdapter? = null private var adapter: PagedAddonsManagerAdapter? = null
private var addons: List<Addon>? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
setHasOptionsMenu(true)
return super.onCreateView(inflater, container, savedInstanceState)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
bindRecyclerView(view) bindRecyclerView(view)
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.addons_menu, menu)
val searchItem = menu.findItem(R.id.search)
val searchView: SearchView = searchItem.actionView as SearchView
searchView.imeOptions = EditorInfo.IME_ACTION_DONE
searchView.queryHint = getString(R.string.addons_search_hint)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
return searchAddons(query.trim())
}
override fun onQueryTextChange(newText: String): Boolean {
return searchAddons(newText.trim())
}
})
}
private fun searchAddons(addonNameSubStr: String): Boolean {
if (adapter == null) {
return false
}
val searchedAddons = arrayListOf<Addon>()
addons?.forEach { addon ->
val names = addon.translatableName
names["en-US"]?.let { name ->
if (name.toLowerCase(Locale.ENGLISH).contains(addonNameSubStr.toLowerCase(Locale.ENGLISH))) {
searchedAddons.add(addon)
}
}
}
updateUI(searchedAddons)
return true
}
private fun updateUI(searchedAddons: List<Addon>) {
adapter?.updateAddons(searchedAddons)
if (searchedAddons.isEmpty()) {
view?.let { view ->
view.add_ons_empty_message.visibility = View.VISIBLE
view.add_ons_list.visibility = View.GONE
}
} else {
view?.let { view ->
view.add_ons_empty_message.visibility = View.GONE
view.add_ons_list.visibility = View.VISIBLE
}
}
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
showToolbar(getString(R.string.preferences_addons)) showToolbar(getString(R.string.preferences_addons))
@ -85,14 +149,14 @@ class AddonsManagementFragment : Fragment(R.layout.fragment_add_ons_management)
val shouldRefresh = adapter != null val shouldRefresh = adapter != null
lifecycleScope.launch(IO) { lifecycleScope.launch(IO) {
try { try {
val addons = requireContext().components.addonManager.getAddons() addons = requireContext().components.addonManager.getAddons()
lifecycleScope.launch(Dispatchers.Main) { lifecycleScope.launch(Dispatchers.Main) {
runIfFragmentIsAttached { runIfFragmentIsAttached {
if (!shouldRefresh) { if (!shouldRefresh) {
adapter = PagedAddonsManagerAdapter( adapter = PagedAddonsManagerAdapter(
requireContext().components.addonCollectionProvider, requireContext().components.addonCollectionProvider,
managementView, managementView,
addons, addons!!,
style = createAddonStyle(requireContext()) style = createAddonStyle(requireContext())
) )
} }
@ -102,7 +166,7 @@ class AddonsManagementFragment : Fragment(R.layout.fragment_add_ons_management)
recyclerView.adapter = adapter recyclerView.adapter = adapter
if (shouldRefresh) { if (shouldRefresh) {
adapter?.updateAddons(addons) adapter?.updateAddons(addons!!)
} }
} }
} }

@ -9,8 +9,6 @@ import android.content.Intent
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.net.toUri import androidx.core.net.toUri
import mozilla.components.feature.addons.AddonManager import mozilla.components.feature.addons.AddonManager
import mozilla.components.feature.addons.AddonsProvider
import mozilla.components.feature.addons.amo.AddonCollectionProvider
import mozilla.components.feature.addons.migration.DefaultSupportedAddonsChecker import mozilla.components.feature.addons.migration.DefaultSupportedAddonsChecker
import mozilla.components.feature.addons.migration.SupportedAddonsChecker import mozilla.components.feature.addons.migration.SupportedAddonsChecker
import mozilla.components.feature.addons.update.AddonUpdater import mozilla.components.feature.addons.update.AddonUpdater
@ -18,9 +16,9 @@ import mozilla.components.feature.addons.update.DefaultAddonUpdater
import mozilla.components.lib.publicsuffixlist.PublicSuffixList import mozilla.components.lib.publicsuffixlist.PublicSuffixList
import mozilla.components.support.migration.state.MigrationStore import mozilla.components.support.migration.state.MigrationStore
import network.novak.fenix.components.PagedAddonCollectionProvider import network.novak.fenix.components.PagedAddonCollectionProvider
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.components.metrics.AppStartupTelemetry import org.mozilla.fenix.components.metrics.AppStartupTelemetry
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.utils.ClipboardHandler import org.mozilla.fenix.utils.ClipboardHandler
import org.mozilla.fenix.utils.Mockable import org.mozilla.fenix.utils.Mockable
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
@ -73,19 +71,18 @@ class Components(private val context: Context) {
} }
val addonCollectionProvider by lazy { val addonCollectionProvider by lazy {
if (!BuildConfig.AMO_COLLECTION.isNullOrEmpty()) { val addonsAccount = context.settings().customAddonsAccount
PagedAddonCollectionProvider( val addonsCollection = context.settings().customAddonsCollection
context, PagedAddonCollectionProvider(
core.client, context,
collectionAccount = BuildConfig.AMO_ACCOUNT, core.client,
collectionName = BuildConfig.AMO_COLLECTION, collectionAccount = addonsAccount,
maxCacheAgeInMinutes = DAY_IN_MINUTES collectionName = addonsCollection,
) maxCacheAgeInMinutes = DAY_IN_MINUTES
} else { )
PagedAddonCollectionProvider(context, core.client, maxCacheAgeInMinutes = DAY_IN_MINUTES)
}
} }
val appStartupTelemetry by lazy { AppStartupTelemetry(analytics.metrics) } val appStartupTelemetry by lazy { AppStartupTelemetry(analytics.metrics) }
@Suppress("MagicNumber") @Suppress("MagicNumber")
@ -108,6 +105,15 @@ class Components(private val context: Context) {
AddonManager(core.store, core.engine, addonCollectionProvider, addonUpdater) AddonManager(core.store, core.engine, addonCollectionProvider, addonUpdater)
} }
fun updateAddonManager() {
addonCollectionProvider.deleteCacheFile(context)
val addonsAccount = context.settings().customAddonsAccount
val addonsCollection = context.settings().customAddonsCollection
addonCollectionProvider.setCollectionAccount(addonsAccount)
addonCollectionProvider.setCollectionName(addonsCollection)
}
val analytics by lazy { Analytics(context) } val analytics by lazy { Analytics(context) }
val publicSuffixList by lazy { PublicSuffixList(context) } val publicSuffixList by lazy { PublicSuffixList(context) }
val clipboardHandler by lazy { ClipboardHandler(context) } val clipboardHandler by lazy { ClipboardHandler(context) }

@ -9,6 +9,7 @@ import android.os.Build
import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION.SDK_INT
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.EditTextPreference
import androidx.preference.PreferenceCategory import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference import androidx.preference.SwitchPreference
@ -57,6 +58,7 @@ class CustomizationFragment : PreferenceFragmentCompat() {
setupRadioGroups() setupRadioGroups()
setupToolbarCategory() setupToolbarCategory()
setupHomeCategory() setupHomeCategory()
setupAddonsCustomizationCategory()
} }
private fun setupRadioGroups() { private fun setupRadioGroups() {
@ -150,4 +152,17 @@ class CustomizationFragment : PreferenceFragmentCompat() {
onPreferenceChangeListener = SharedPreferenceUpdater() onPreferenceChangeListener = SharedPreferenceUpdater()
} }
} }
private fun setupAddonsCustomizationCategory() {
requirePreference<EditTextPreference>(R.string.pref_key_addons_custom_account).apply {
text = context.settings().customAddonsAccount
onPreferenceChangeListener = SharedPreferenceUpdater()
}
requirePreference<EditTextPreference>(R.string.pref_key_addons_custom_collection).apply {
text = context.settings().customAddonsCollection
onPreferenceChangeListener = SharedPreferenceUpdater()
}
}
} }

@ -6,6 +6,8 @@ package org.mozilla.fenix.settings
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.Preference import androidx.preference.Preference
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
/** /**
@ -15,10 +17,21 @@ import org.mozilla.fenix.ext.settings
open class SharedPreferenceUpdater : Preference.OnPreferenceChangeListener { open class SharedPreferenceUpdater : Preference.OnPreferenceChangeListener {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean { override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
val newBooleanValue = newValue as? Boolean ?: return false if (newValue is Boolean) {
preference.context.settings().preferences.edit { preference.context.settings().preferences.edit {
putBoolean(preference.key, newBooleanValue) putBoolean(preference.key, newValue)
}
} else if (newValue is String) {
preference.context.settings().preferences.edit {
putString(preference.key, newValue)
}
if (preference.key == preference.context.getString(R.string.pref_key_addons_custom_account) ||
preference.key == preference.context.getString(R.string.pref_key_addons_custom_collection)) {
preference.context.components.updateAddonManager()
}
} }
return true return true
} }
} }

@ -15,6 +15,7 @@ import android.view.accessibility.AccessibilityManager
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.annotation.VisibleForTesting.PRIVATE import androidx.annotation.VisibleForTesting.PRIVATE
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.preference.EditTextPreference
import mozilla.components.feature.sitepermissions.SitePermissionsRules import mozilla.components.feature.sitepermissions.SitePermissionsRules
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action
import mozilla.components.feature.sitepermissions.SitePermissionsRules.AutoplayAction import mozilla.components.feature.sitepermissions.SitePermissionsRules.AutoplayAction
@ -864,6 +865,16 @@ class Settings(private val appContext: Context) : PreferencesHolder {
0 0
) )
val customAddonsAccount by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_addons_custom_account),
"16201230"
)
val customAddonsCollection by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_addons_custom_collection),
"What-I-want-on-Fenix"
)
private var savedLoginsSortingStrategyString by stringPreference( private var savedLoginsSortingStrategyString by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_saved_logins_sorting_strategy), appContext.getPreferenceKey(R.string.pref_key_saved_logins_sorting_strategy),
default = SavedLoginsSortingStrategyMenu.Item.AlphabeticallySort.strategyString default = SavedLoginsSortingStrategyMenu.Item.AlphabeticallySort.strategyString

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?><!-- 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
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/search"
android:icon="@drawable/ic_search"
android:title="@string/addons_search_hint"
app:iconTint="?primaryText"
app:actionViewClass="androidx.appcompat.widget.SearchView"
android:contentDescription="@string/addons_search_hint"
app:showAsAction="ifRoom|collapseActionView" />
</menu>

@ -126,6 +126,11 @@
<!-- Customization Settings --> <!-- Customization Settings -->
<string name="pref_home_category" translatable="false">pref_home_category</string> <string name="pref_home_category" translatable="false">pref_home_category</string>
<!-- Add-ons Source Customization Settings -->
<string name="pref_addons_settings_category" translatable="false">pref_addons_settings_category</string>
<string name="pref_key_addons_custom_account" translatable="false">pref_key_addons_custom_account</string>
<string name="pref_key_addons_custom_collection" translatable="false">pref_key_addons_custom_collection</string>
<!-- Tracking Protection Settings --> <!-- Tracking Protection Settings -->
<string name="pref_key_etp_learn_more" translatable="false">pref_key_etp_learn_more</string> <string name="pref_key_etp_learn_more" translatable="false">pref_key_etp_learn_more</string>
<string name="pref_key_tracking_protection_settings" translatable="false">pref_key_tracking_protection_settings</string> <string name="pref_key_tracking_protection_settings" translatable="false">pref_key_tracking_protection_settings</string>

@ -324,6 +324,10 @@
<string name="preferences_external_download_manager">External download manager</string> <string name="preferences_external_download_manager">External download manager</string>
<!-- Preference for add_ons --> <!-- Preference for add_ons -->
<string name="preferences_addons">Add-ons</string> <string name="preferences_addons">Add-ons</string>
<!-- Preference for add-ons custom source -->
<string name="preferences_addons_customization">Configure custom add-ons source</string>
<!-- Placeholder text shown in the search bar before a user enters text -->
<string name="addons_search_hint">Search add-ons</string>
<!-- Preference for notifications --> <!-- Preference for notifications -->
<string name="preferences_notifications">Notifications</string> <string name="preferences_notifications">Notifications</string>
@ -1526,6 +1530,11 @@
<!-- Label for the show most visited sites preference --> <!-- Label for the show most visited sites preference -->
<string name="top_sites_toggle_top_frecent_sites">Show most visited sites</string> <string name="top_sites_toggle_top_frecent_sites">Show most visited sites</string>
<!-- Label for add-ons custom source account -->
<string name="addons_custom_source_account">Set custom add-ons account</string>
<!-- Label for add-ons custom source collection -->
<string name="addons_custom_source_collection">Set custom add-ons collection</string>
<!-- Content description for close button in collection placeholder. --> <!-- Content description for close button in collection placeholder. -->
<string name="remove_home_collection_placeholder_content_description">Remove</string> <string name="remove_home_collection_placeholder_content_description">Remove</string>

@ -61,4 +61,18 @@
android:key="@string/pref_key_enable_top_frecent_sites" android:key="@string/pref_key_enable_top_frecent_sites"
android:title="@string/top_sites_toggle_top_frecent_sites" /> android:title="@string/top_sites_toggle_top_frecent_sites" />
</androidx.preference.PreferenceCategory> </androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:key="@string/pref_addons_settings_category"
android:layout="@layout/preference_cat_style"
android:title="@string/preferences_addons_customization"
app:allowDividerAbove="false"
app:iconSpaceReserved="false">
<androidx.preference.EditTextPreference
android:key="@string/pref_key_addons_custom_account"
android:title="@string/addons_custom_source_account" />
<androidx.preference.EditTextPreference
android:key="@string/pref_key_addons_custom_collection"
android:title="@string/addons_custom_source_collection" />
</androidx.preference.PreferenceCategory>
</androidx.preference.PreferenceScreen> </androidx.preference.PreferenceScreen>

Loading…
Cancel
Save