Skip to content

Commit

Permalink
ref: use URI instead of File. Minors
Browse files Browse the repository at this point in the history
  • Loading branch information
VaiTon committed Apr 29, 2021
1 parent c2c358c commit e7f0886
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 52 deletions.
Expand Up @@ -19,6 +19,7 @@ import android.Manifest
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.View
Expand All @@ -32,7 +33,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.core.net.toUri
import androidx.core.net.toFile
import com.github.chrisbanes.photoview.PhotoViewAttacher
import com.squareup.picasso.Callback
import com.squareup.picasso.Picasso
Expand Down Expand Up @@ -468,18 +469,20 @@ class ImagesManageActivity : BaseActivity() {
private fun editPhoto(field: ProductImageField, transformation: ImageTransformation) {
if (transformation.isEmpty()) return

download(this, transformation.imageUrl!!, productsApi)
download(this, transformation.imageUrl!!, client)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { file ->
.subscribe { fileUri ->
//to delete the file after:
lastViewedImage = file
cropRotateExistingImageOnServer(file, getString(getResourceIdForEditAction(field)), transformation)
lastViewedImage = fileUri.toFile()
cropRotateExistingImageOnServer(fileUri,
getString(getResourceIdForEditAction(field)),
transformation)
}.addTo(disp)
}

private fun getProduct() = intent.getSerializableExtra(PRODUCT) as Product?

private fun requireProduct() = getProduct() ?: error("Cannot start ${this::class} without product.")
private fun requireProduct() = getProduct() ?: error("Cannot start $LOG_TAG without product.")

private fun onLanguageChanged() {
val data = binding.comboLanguages.selectedItem as LanguageData
Expand All @@ -494,7 +497,7 @@ class ImagesManageActivity : BaseActivity() {
}

private fun getSelectedType(): ProductImageField = intent.getSerializableExtra(IMAGE_TYPE) as ProductImageField?
?: error("Cannot initialize ${this::class.simpleName} without IMAGE_TYPE")
?: error("Cannot initialize $LOG_TAG without IMAGE_TYPE")

private fun onImageTypeChanged() {
getProduct()?.let {
Expand All @@ -511,10 +514,9 @@ class ImagesManageActivity : BaseActivity() {
}
}

private fun cropRotateExistingImageOnServer(imageFile: File, title: String, transformation: ImageTransformation) {
val uri = imageFile.toUri()
private fun cropRotateExistingImageOnServer(fileUri: Uri, title: String, transformation: ImageTransformation) {

val activityBuilder = CropImage.activity(uri)
val activityBuilder = CropImage.activity(fileUri)
.setCropMenuCropButtonIcon(R.drawable.ic_check_white_24dp)
.setAllowFlipping(false) //we just want crop size/rotation
.setNoOutputImage(true)
Expand Down Expand Up @@ -655,5 +657,7 @@ class ImagesManageActivity : BaseActivity() {

fun isImageModified(requestCode: Int, resultCode: Int) =
requestCode == REQUEST_EDIT_IMAGE && resultCode == RESULTCODE_MODIFIED

private val LOG_TAG = ImagesManageActivity::class.simpleName
}
}
Expand Up @@ -4,14 +4,14 @@ import android.content.Context
import android.widget.ArrayAdapter
import android.widget.Filter
import android.widget.Filterable
import openfoodfacts.github.scrachx.openfood.network.services.ProductsAPI
import openfoodfacts.github.scrachx.openfood.network.OpenFoodAPIClient
import org.apache.commons.lang3.StringUtils
import java.util.*

class EmbCodeAutoCompleteAdapter(
context: Context,
textViewResourceId: Int,
private val productsAPI: ProductsAPI
private val client: OpenFoodAPIClient
) : ArrayAdapter<String>(context, textViewResourceId), Filterable {
private val codeList: MutableList<String> = arrayListOf()

Expand All @@ -28,7 +28,7 @@ class EmbCodeAutoCompleteAdapter(
if (constraint == null) return FilterResults().apply { count = 0 }

// Retrieve the autocomplete results from server.
val list = productsAPI.getEMBCodeSuggestions(constraint.toString()).blockingGet()
val list = client.getEMBCodeSuggestions(constraint.toString()).blockingGet()

// Assign the data to the FilterResults
return FilterResults().apply {
Expand Down
Expand Up @@ -4,15 +4,15 @@ import android.content.Context
import android.widget.ArrayAdapter
import android.widget.Filter
import android.widget.Filterable
import openfoodfacts.github.scrachx.openfood.network.services.ProductsAPI
import openfoodfacts.github.scrachx.openfood.network.OpenFoodAPIClient
import org.apache.commons.lang3.StringUtils
import java.util.*

class PeriodAfterOpeningAutoCompleteAdapter(
context: Context?,
context: Context,
textViewResourceId: Int,
private val productsApi: ProductsAPI
) : ArrayAdapter<String>(context!!, textViewResourceId), Filterable {
private val client: OpenFoodAPIClient
) : ArrayAdapter<String>(context, textViewResourceId), Filterable {
private val periodsList = mutableListOf<String>()

override fun getCount() = periodsList.size
Expand All @@ -26,7 +26,7 @@ class PeriodAfterOpeningAutoCompleteAdapter(
if (constraint == null) return FilterResults().apply { count = 0 }

// Retrieve the autocomplete results from server.
val list = productsApi.getPeriodAfterOpeningSuggestions(constraint.toString()).blockingGet()
val list = client.getPeriodAfterOpeningSuggestions(constraint.toString()).blockingGet()

// Assign the data to the FilterResults
return FilterResults().apply {
Expand Down
Expand Up @@ -30,7 +30,6 @@ import com.squareup.picasso.Callback
import com.squareup.picasso.Picasso
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.rxkotlin.addTo
import openfoodfacts.github.scrachx.openfood.R
import openfoodfacts.github.scrachx.openfood.analytics.AnalyticsEvent
import openfoodfacts.github.scrachx.openfood.analytics.AnalyticsView
Expand Down
Expand Up @@ -36,7 +36,6 @@ import com.squareup.picasso.Callback
import com.squareup.picasso.Picasso
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.rxkotlin.addTo
import openfoodfacts.github.scrachx.openfood.R
import openfoodfacts.github.scrachx.openfood.analytics.AnalyticsView
import openfoodfacts.github.scrachx.openfood.analytics.MatomoAnalytics
Expand Down
Expand Up @@ -72,7 +72,6 @@ import openfoodfacts.github.scrachx.openfood.models.entities.tag.TagDao
import openfoodfacts.github.scrachx.openfood.network.ApiFields
import openfoodfacts.github.scrachx.openfood.network.ApiFields.Keys.lcProductNameKey
import openfoodfacts.github.scrachx.openfood.network.OpenFoodAPIClient
import openfoodfacts.github.scrachx.openfood.network.services.ProductsAPI
import openfoodfacts.github.scrachx.openfood.utils.*
import openfoodfacts.github.scrachx.openfood.utils.FileDownloader.download
import org.apache.commons.lang3.StringUtils
Expand All @@ -96,9 +95,6 @@ class ProductEditOverviewFragment : ProductEditFragment() {
@Inject
lateinit var client: OpenFoodAPIClient

@Inject
lateinit var productsApi: ProductsAPI

@Inject
lateinit var matomoAnalytics: MatomoAnalytics

Expand Down Expand Up @@ -535,7 +531,7 @@ class ProductEditOverviewFragment : ProductEditFragment() {
(operation.result as List<CountryName>).mapTo(countries) { it.name }

val adapter = ArrayAdapter(requireActivity(), android.R.layout.simple_dropdown_item_1line, countries)
val embAdapter = EmbCodeAutoCompleteAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, productsApi)
val embAdapter = EmbCodeAutoCompleteAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, client)

binding.originOfIngredients.setAdapter(adapter)
binding.countryWherePurchased.setAdapter(adapter)
Expand Down Expand Up @@ -582,9 +578,9 @@ class ProductEditOverviewFragment : ProductEditFragment() {
if (isFlavors(OBF)) {
binding.periodOfTimeAfterOpeningTil.visibility = View.VISIBLE
val customAdapter = PeriodAfterOpeningAutoCompleteAdapter(
activity,
requireContext(),
android.R.layout.simple_dropdown_item_1line,
productsApi
client
)
binding.periodOfTimeAfterOpening.setAdapter(customAdapter)
}
Expand Down Expand Up @@ -659,7 +655,7 @@ class ProductEditOverviewFragment : ProductEditFragment() {
// Image found, download it if necessary and edit it
isFrontImagePresent = true
if (photoFile == null) {
download(requireContext(), frontImageUrl!!, productsApi)
download(requireContext(), frontImageUrl!!, client)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { file: File? ->
photoFile = file
Expand Down
Expand Up @@ -161,6 +161,9 @@ object ApiFields {
const val STORES = "stores"
const val STATUS = "status"
const val NUTRITION_GRADE = "nutrition_grades_tags"

const val SEARCH_TERMS = "search_terms"

val TYPE_IMAGE = arrayOf(
ProductImageField.FRONT,
ProductImageField.INGREDIENTS,
Expand Down
Expand Up @@ -50,7 +50,7 @@ import openfoodfacts.github.scrachx.openfood.features.product.view.ProductViewAc
class OpenFoodAPIClient @Inject constructor(
@ApplicationContext private val context: Context,
private val daoSession: DaoSession,
private val rawApi: ProductsAPI,
internal val rawApi: ProductsAPI,
private val sentryAnalytics: SentryAnalytics,
private val localeManager: LocaleManager
) {
Expand Down Expand Up @@ -505,4 +505,8 @@ class OpenFoodAPIClient @Inject constructor(
get() = Keys.PRODUCT_SEARCH_FIELDS.toMutableList().apply {
add(localeProductNameField)
}.joinToString(",")

fun getEMBCodeSuggestions(term: String) = rawApi.getSuggestions("emb_codes", term)

fun getPeriodAfterOpeningSuggestions(term: String) = rawApi.getSuggestions("periods_after_opening", term)
}
Expand Up @@ -74,7 +74,7 @@ interface ProductsAPI {

@GET("cgi/search.pl?search_simple=1&json=1&action=process")
fun searchProductByName(
@Query("search_terms") name: String,
@Query(ApiFields.Keys.SEARCH_TERMS) name: String,
@Query("fields") fields: String,
@Query("page") page: Int
): Single<Search>
Expand Down Expand Up @@ -108,11 +108,12 @@ interface ProductsAPI {
@Query("id") imgId: String
): Single<JsonNode>

@GET("cgi/suggest.pl?tagtype=emb_codes")
fun getEMBCodeSuggestions(@Query("term") term: String?): Single<ArrayList<String>>
@GET("cgi/suggest.pl")
fun getSuggestions(
@Query("tagtype") tagType: String,
@Query("term") term: String
): Single<List<String>>

@GET("/cgi/suggest.pl?tagtype=periods_after_opening")
fun getPeriodAfterOpeningSuggestions(@Query("term") term: String?): Single<ArrayList<String>>

@GET("brand/{brand}/{page}.json")
fun getProductByBrands(
Expand Down
@@ -1,15 +1,15 @@
package openfoodfacts.github.scrachx.openfood.utils

import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.core.net.toUri
import io.reactivex.Maybe
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import openfoodfacts.github.scrachx.openfood.network.services.ProductsAPI
import openfoodfacts.github.scrachx.openfood.network.OpenFoodAPIClient
import openfoodfacts.github.scrachx.openfood.utils.Utils.makeOrGetPictureDirectory
import java.io.File
import java.io.FileOutputStream
import java.io.IOException

/**
Expand All @@ -31,17 +31,15 @@ object FileDownloader {
* @param fileUrl provides the URL of the file to download.
* @return [Maybe]
*/
fun download(context: Context, fileUrl: String, productsAPI: ProductsAPI) = productsAPI
fun download(context: Context, fileUrl: String, client: OpenFoodAPIClient) = client.rawApi
.downloadFile(fileUrl)
.flatMapMaybe { responseBody ->
Log.d(LOG_TAG, "server contacted and has file")
val writtenToDisk = writeResponseBodyToDiskSync(context, responseBody, fileUrl)
.flatMapMaybe { body ->
Log.d(LOG_TAG, "Server contacted and has file")
val writtenToDisk = writeResponseBodyToDiskSync(context, body, fileUrl)
if (writtenToDisk != null) {
Log.d(LOG_TAG, "file download was a success $writtenToDisk")
Log.d(LOG_TAG, "Downloaded file $writtenToDisk")
Maybe.just(writtenToDisk)
} else {
Maybe.empty()
}
} else Maybe.empty()
}
.doOnError { Log.e(LOG_TAG, "error", it) }
.subscribeOn(Schedulers.io()) // IO operation -> Schedulers.io()
Expand All @@ -54,20 +52,20 @@ object FileDownloader {
* @param request: url of the downloaded file.
* @return [File] that has been written to the disk.
*/
private fun writeResponseBodyToDiskSync(context: Context, body: ResponseBody, request: String): File? {
private fun writeResponseBodyToDiskSync(context: Context, body: ResponseBody, request: String): Uri? {
val requestUri = request.toUri()
val writtenFile = File(makeOrGetPictureDirectory(context), "${System.currentTimeMillis()}-${requestUri.lastPathSegment}")
try {
body.byteStream().use { inputStream ->
FileOutputStream(writtenFile).use { outputStream ->
inputStream.copyTo(outputStream, 4 * 1024)
outputStream.flush()
return writtenFile
return try {
body.byteStream().use { stream ->
writtenFile.outputStream().use { out ->
stream.copyTo(out)
out.flush()
}
}
writtenFile.toUri()
} catch (e: IOException) {
Log.w(LOG_TAG, "Could not write file $writtenFile to disk.", e)
return null
null
}
}
}

0 comments on commit e7f0886

Please sign in to comment.