Skip to content

Commit

Permalink
fix: NPE in ProductCompareAdapter (#4631)
Browse files Browse the repository at this point in the history
* fix: NPE in ProductCompareAdapter

Closes #4614

* build: use 2G ram max for gradle build
  • Loading branch information
VaiTon committed Apr 7, 2022
1 parent c4eaba8 commit 7ef7b94
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 230 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package openfoodfacts.github.scrachx.openfood.features.compare

import android.Manifest.permission
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.os.Build
import android.view.LayoutInflater
Expand Down Expand Up @@ -219,68 +220,18 @@ class ProductCompareAdapter(
}

private fun getLevelItems(product: Product): List<NutrientLevelItem> {
val levelItems = mutableListOf<NutrientLevelItem>()

val nutriments = product.nutriments
val nutrientLevels = product.nutrientLevels

var fat: NutrimentLevel? = null
var saturatedFat: NutrimentLevel? = null
var sugars: NutrimentLevel? = null
var salt: NutrimentLevel? = null

if (nutrientLevels != null) {
fat = nutrientLevels.fat
saturatedFat = nutrientLevels.saturatedFat
sugars = nutrientLevels.sugars
salt = nutrientLevels.salt
}

if (fat != null || salt != null || saturatedFat != null || sugars != null) {
val fatNutriment = nutriments[Nutriment.FAT]
if (fat != null && fatNutriment != null) {
val fatNutrimentLevel = fat.getLocalize(activity)
levelItems += NutrientLevelItem(
activity.getString(R.string.compare_fat),
fatNutriment.getPer100gDisplayString(),
fatNutrimentLevel,
fat.getImgRes()
)
}
val saturatedFatNutriment = nutriments[Nutriment.SATURATED_FAT]
if (saturatedFat != null && saturatedFatNutriment != null) {
val saturatedFatLocalize = saturatedFat.getLocalize(activity)
levelItems += NutrientLevelItem(
activity.getString(R.string.compare_saturated_fat),
saturatedFatNutriment.getPer100gDisplayString(),
saturatedFatLocalize,
saturatedFat.getImgRes()
)
}
val sugarsNutriment = nutriments[Nutriment.SUGARS]
if (sugars != null && sugarsNutriment != null) {
val sugarsLocalize = sugars.getLocalize(activity)
levelItems += NutrientLevelItem(
activity.getString(R.string.compare_sugars),
sugarsNutriment.getPer100gDisplayString(),
sugarsLocalize,
sugars.getImgRes()
)
}
val saltNutriment = nutriments[Nutriment.SALT]
if (salt != null && saltNutriment != null) {
val saltLocalize = salt.getLocalize(activity)
levelItems += NutrientLevelItem(
activity.getString(R.string.compare_salt),
saltNutriment.getPer100gDisplayString(),
saltLocalize,
salt.getImgRes()
)
}
}
return levelItems
return listOfNotNull(
nutriments.buildLevelItem(activity, Nutriment.FAT, nutrientLevels?.fat),
nutriments.buildLevelItem(activity, Nutriment.SATURATED_FAT, nutrientLevels?.saturatedFat),
nutriments.buildLevelItem(activity, Nutriment.SUGARS, nutrientLevels?.sugars),
nutriments.buildLevelItem(activity, Nutriment.SALT, nutrientLevels?.salt)
)
}


fun onImageReturned(file: File) {
val pos = imageReturnedPosition
checkNotNull(pos) { "Position null." }
Expand Down Expand Up @@ -321,5 +272,9 @@ class ProductCompareAdapter(
binding.fullProductButton.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_fullscreen_blue_18dp, 0, 0, 0)
}
}

companion object {

}
}

Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ class ProductEditNutritionFactsFragment : ProductEditFragment() {
oldUnit = oldProductNutriment.unit
oldMod = oldProductNutriment.modifier
oldValue = if (isDataPer100g)
oldProductNutriment.per100gInUnit.value
oldProductNutriment.per100gInUnit!!.value
else
oldProductNutriment.perServingInUnit!!.value
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class CalculateDetailsActivity : BaseActivity() {
if (energyKcal != null) {
nutrimentListItems += NutrimentListItem(
getString(R.string.nutrition_energy_short_name),
calculateCalories(portion).value,
calculateCalories(portion)?.value,
energyKcal.perServingInUnit?.value,
MeasurementUnit.ENERGY_KCAL,
energyKcal.modifier,
Expand All @@ -82,7 +82,7 @@ class CalculateDetailsActivity : BaseActivity() {
if (energyKj != null) {
nutrimentListItems += NutrimentListItem(
getString(R.string.nutrition_energy_short_name),
calculateKj(portion).value,
calculateKj(portion)?.value,
energyKj.perServingInUnit?.value,
MeasurementUnit.ENERGY_KJ,
energyKj.modifier,
Expand All @@ -94,7 +94,7 @@ class CalculateDetailsActivity : BaseActivity() {
if (fat != null) {
nutrimentListItems += NutrimentListItem(
getString(R.string.nutrition_fat),
fat.getForPortion(portion).value,
fat.getForPortion(portion)?.value,
fat.perServingInUnit?.value,
fat.unit,
fat.modifier
Expand All @@ -107,7 +107,7 @@ class CalculateDetailsActivity : BaseActivity() {
if (carbohydrates != null) {
nutrimentListItems += NutrimentListItem(
getString(R.string.nutrition_carbohydrate),
carbohydrates.getForPortion(portion).value,
carbohydrates.getForPortion(portion)?.value,
carbohydrates.perServingInUnit?.value,
carbohydrates.unit,
carbohydrates.modifier
Expand All @@ -123,7 +123,7 @@ class CalculateDetailsActivity : BaseActivity() {
if (proteins != null) {
nutrimentListItems += NutrimentListItem(
getString(R.string.nutrition_proteins),
proteins.getForPortion(portion).value,
proteins.getForPortion(portion)?.value,
proteins.perServingInUnit?.value,
proteins.unit,
proteins.modifier
Expand Down Expand Up @@ -155,27 +155,29 @@ class CalculateDetailsActivity : BaseActivity() {
}

private fun getNutrimentItems(nutriments: ProductNutriments, nutrimentMap: Map<Nutriment, Int>): List<NutrimentListItem> {
val portion = measure(weight, unitOfMeasurement)

return nutrimentMap.mapNotNull { (name, stringRes) ->
val nutriment = nutriments[name] ?: return@mapNotNull null

NutrimentListItem(
getString(stringRes),
nutriment.getForPortion(measure(weight, unitOfMeasurement)).value,
nutriment.getForPortion(portion)?.value,
nutriment.perServingInUnit?.value,
nutriment.unit,
nutriment.modifier
)
}
}

private fun calculateCalories(portion: Measurement): Measurement {
val energy100gCal = product.nutriments[Nutriment.ENERGY_KCAL]!!.per100gInG
private fun calculateCalories(portion: Measurement): Measurement? {
val energy100gCal = product.nutriments[Nutriment.ENERGY_KCAL]?.per100gInG ?: return null
val portionGrams = portion.grams.value
return Measurement(energy100gCal.value / 100 * portionGrams, energy100gCal.unit)
}

private fun calculateKj(portion: Measurement): Measurement {
val energy100gKj = product.nutriments[Nutriment.ENERGY_KJ]!!.per100gInG
private fun calculateKj(portion: Measurement): Measurement? {
val energy100gKj = product.nutriments[Nutriment.ENERGY_KJ]?.per100gInG ?: return null
val weightGrams = portion.grams.value
return Measurement(energy100gKj.value / 100 * weightGrams, energy100gKj.unit)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,11 @@ class EnvironmentProductFragment : BaseFragment() {
}

val carbonFootprintNutriment = nutriments[Nutriment.CARBON_FOOTPRINT]
if (carbonFootprintNutriment != null) {
val carbonFootprintMeasure = carbonFootprintNutriment?.per100gInUnit
if (carbonFootprintMeasure != null) {
binding.textCarbonFootprint.text = buildSpannedString {
bold { append(getString(R.string.textCarbonFootprint)) }
append(getRoundNumber(carbonFootprintNutriment.per100gInUnit))
append(getRoundNumber(carbonFootprintMeasure))
append(carbonFootprintNutriment.unit.sym)
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.core.net.toUri
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.text.inSpans
import androidx.core.view.isGone
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DividerItemDecoration
Expand All @@ -59,8 +60,8 @@ import openfoodfacts.github.scrachx.openfood.customtabs.CustomTabsHelper
import openfoodfacts.github.scrachx.openfood.customtabs.WebViewFallback
import openfoodfacts.github.scrachx.openfood.databinding.FragmentNutritionProductBinding
import openfoodfacts.github.scrachx.openfood.features.FullScreenActivityOpener
import openfoodfacts.github.scrachx.openfood.features.images.manage.ImagesManageActivity
import openfoodfacts.github.scrachx.openfood.features.adapters.NutrimentsGridAdapter
import openfoodfacts.github.scrachx.openfood.features.images.manage.ImagesManageActivity
import openfoodfacts.github.scrachx.openfood.features.login.LoginActivity
import openfoodfacts.github.scrachx.openfood.features.product.edit.ProductEditActivity
import openfoodfacts.github.scrachx.openfood.features.product.edit.ProductEditActivity.Companion.KEY_STATE
Expand All @@ -70,9 +71,10 @@ import openfoodfacts.github.scrachx.openfood.features.shared.BaseFragment
import openfoodfacts.github.scrachx.openfood.features.shared.adapters.NutrientLevelListAdapter
import openfoodfacts.github.scrachx.openfood.images.ProductImage
import openfoodfacts.github.scrachx.openfood.models.*
import openfoodfacts.github.scrachx.openfood.models.MeasurementUnit.*
import openfoodfacts.github.scrachx.openfood.models.MeasurementUnit.ENERGY_KCAL
import openfoodfacts.github.scrachx.openfood.models.MeasurementUnit.ENERGY_KJ
import openfoodfacts.github.scrachx.openfood.models.entities.SendProduct
import openfoodfacts.github.scrachx.openfood.network.ApiFields
import openfoodfacts.github.scrachx.openfood.network.ApiFields.StateTags
import openfoodfacts.github.scrachx.openfood.repositories.ProductRepository
import openfoodfacts.github.scrachx.openfood.utils.*
import pl.aprilapps.easyphotopicker.EasyImage
Expand Down Expand Up @@ -370,85 +372,54 @@ class NutritionProductFragment : BaseFragment(), CustomTabActivityHelper.Connect
private fun setupNutrientItems(nutriments: ProductNutriments) {
val levelItemList = mutableListOf<NutrientLevelItem>()
val nutrientLevels = product.nutrientLevels
var fat: NutrimentLevel? = null
var saturatedFat: NutrimentLevel? = null
var sugars: NutrimentLevel? = null
var salt: NutrimentLevel? = null

if (nutrientLevels != null) {
fat = nutrientLevels.fat
saturatedFat = nutrientLevels.saturatedFat
sugars = nutrientLevels.sugars
salt = nutrientLevels.salt
}

val fat = nutrientLevels?.fat
val saturatedFat = nutrientLevels?.saturatedFat
val sugars = nutrientLevels?.sugars
val salt = nutrientLevels?.salt

if (fat == null && salt == null && saturatedFat == null && sugars == null) {
binding.nutrientLevelsCardView.visibility = GONE
levelItemList += NutrientLevelItem("", "", "", NO_ID)
binding.imageGrade.visibility = GONE
binding.nutrientLevelsCardView.visibility = GONE
updateNutritionGradeImg(false)
} else {
// prefetch the uri
customTabActivityHelper = CustomTabActivityHelper()
customTabActivityHelper!!.connectionCallback = this
nutritionScoreUri = getString(R.string.nutriscore_uri).toUri()
customTabActivityHelper!!.mayLaunchUrl(nutritionScoreUri, null, null)

val fatNutriment = nutriments[Nutriment.FAT]
if (fat != null && fatNutriment != null) {
val fatNutrimentLevel = fat.getLocalize(requireActivity())
levelItemList += NutrientLevelItem(
getString(R.string.txtFat),
fatNutriment.getPer100gDisplayString(),
fatNutrimentLevel,
fat.getImgRes(),
)
}

val saturatedFatNutriment = nutriments[Nutriment.SATURATED_FAT]
if (saturatedFat != null && saturatedFatNutriment != null) {
val saturatedFatLocalize = saturatedFat.getLocalize(requireActivity())
levelItemList += NutrientLevelItem(
getString(R.string.txtSaturatedFat),
saturatedFatNutriment.getPer100gDisplayString(),
saturatedFatLocalize,
saturatedFat.getImgRes(),
)
}

val sugarsNutriment = nutriments[Nutriment.SUGARS]
if (sugars != null && sugarsNutriment != null) {
val sugarsLocalize = sugars.getLocalize(requireActivity())
levelItemList += NutrientLevelItem(
getString(R.string.txtSugars),
sugarsNutriment.getPer100gDisplayString(),
sugarsLocalize,
sugars.getImgRes(),
)
}

val saltNutriment = nutriments[Nutriment.SALT]
if (salt != null && saltNutriment != null) {
levelItemList += NutrientLevelItem(
getString(R.string.txtSalt),
saltNutriment.getPer100gDisplayString(),
salt.getLocalize(requireActivity()),
salt.getImgRes()
)
}
drawNutritionGrade()
levelItemList += listOfNotNull(
nutriments.buildLevelItem(requireContext(), Nutriment.FAT, fat),
nutriments.buildLevelItem(requireContext(), Nutriment.SATURATED_FAT, saturatedFat),
nutriments.buildLevelItem(requireContext(), Nutriment.SUGARS, sugars),
nutriments.buildLevelItem(requireContext(), Nutriment.SALT, salt)
)
updateNutritionGradeImg(true)
}

binding.listNutrientLevels.adapter = NutrientLevelListAdapter(requireActivity(), levelItemList)
binding.listNutrientLevels.layoutManager = LinearLayoutManager(requireActivity())
binding.listNutrientLevels.apply {
adapter = NutrientLevelListAdapter(requireActivity(), levelItemList)
layoutManager = LinearLayoutManager(requireActivity())
}
}

private fun drawNutritionGrade() {
binding.imageGradeLayout.visibility = VISIBLE
private fun updateNutritionGradeImg(show: Boolean) {
if (!show) {
binding.imageGradeLayout.isGone = true
return
}

binding.imageGradeLayout.isGone = false
binding.imageGrade.setImageResource(product.getNutriScoreResource())

binding.imageGrade.setOnClickListener {
val customTabsIntent = CustomTabsHelper.getCustomTabsIntent(requireContext(), customTabActivityHelper!!.session)
CustomTabActivityHelper.openCustomTab(requireActivity(), customTabsIntent, nutritionScoreUri!!, WebViewFallback())
CustomTabActivityHelper.openCustomTab(
requireActivity(),
CustomTabsHelper.getCustomTabsIntent(requireContext(), customTabActivityHelper!!.session),
nutritionScoreUri!!,
WebViewFallback()
)
}
}

Expand All @@ -457,13 +428,16 @@ class NutritionProductFragment : BaseFragment(), CustomTabActivityHelper.Connect
* Checks the product states_tags to determine which prompt to be shown
*/
private fun checkPrompts() {
if (product.statesTags.contains(ApiFields.StateTags.CATEGORIES_TO_BE_COMPLETED)) {
// Category
if (StateTags.CATEGORIES_TO_BE_COMPLETED in product.statesTags) {
showCategoryPrompt = true
}
if (product.noNutritionData == "on") {

// Nutrition
if (product.isNoNutrition()) {
showNutritionPrompt = false
showNutritionData = false
} else if (product.statesTags.contains(ApiFields.StateTags.NUTRITION_FACTS_TO_BE_COMPLETED)) {
} else if (StateTags.NUTRITION_FACTS_TO_BE_COMPLETED in product.statesTags) {
showNutritionPrompt = true
}
}
Expand Down
Loading

0 comments on commit 7ef7b94

Please sign in to comment.