-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
HistoryRepository.kt
107 lines (95 loc) 路 3.86 KB
/
HistoryRepository.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package openfoodfacts.github.scrachx.openfood.repositories
import android.content.Context
import android.util.Log
import androidx.core.content.edit
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.withContext
import logcat.LogPriority
import logcat.asLog
import logcat.logcat
import openfoodfacts.github.scrachx.openfood.images.IMAGE_URL
import openfoodfacts.github.scrachx.openfood.models.DaoSession
import openfoodfacts.github.scrachx.openfood.models.HistoryProduct
import openfoodfacts.github.scrachx.openfood.models.getSmallFrontImageUrl
import openfoodfacts.github.scrachx.openfood.network.ApiFields
import openfoodfacts.github.scrachx.openfood.utils.CoroutineDispatchers
import openfoodfacts.github.scrachx.openfood.utils.LocaleManager
import openfoodfacts.github.scrachx.openfood.utils.getAppPreferences
import java.io.IOException
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class HistoryRepository @Inject constructor(
@ApplicationContext private val context: Context,
private val daoSession: DaoSession,
private val productRepository: ProductRepository,
private val localeManager: LocaleManager,
private val dispatchers: CoroutineDispatchers,
) {
suspend fun syncOldHistory() = withContext(dispatchers.IO) {
val fieldsToRefresh = listOf(
ApiFields.Keys.IMAGE_SMALL_URL,
ApiFields.Keys.PRODUCT_NAME,
ApiFields.Keys.BRANDS,
ApiFields.Keys.QUANTITY,
IMAGE_URL,
ApiFields.Keys.NUTRITION_GRADE_FR,
ApiFields.Keys.BARCODE
)
val historyProducts = daoSession.historyProductDao.loadAll()
// Refresh each product in the history
val results = historyProducts.map { product ->
product to runCatching { refreshProduct(product, fieldsToRefresh) }
}
// If any product failed to sync, log the barcodes of the failed products
val failedProducts = results.filter { it.second.isFailure }
if (failedProducts.isNotEmpty()) {
val failedBarcodes = failedProducts.joinToString { it.first.barcode }
logcat(LogPriority.ERROR) {
"Could not sync history. Errors on products: $failedBarcodes"
}
// If debug logging is enabled, log the full stack traces of the errors
failedProducts.forEach {
logcat(LogPriority.DEBUG) {
"Error for product ${it.first.barcode}: " +
it.second.exceptionOrNull()?.asLog()
}
}
}
context.getAppPreferences().edit {
putBoolean("is_old_history_data_synced", true)
}
}
/**
* Refreshes the product in the database with the latest data from the server.
*
* @throws IOException if the product could not be refreshed
*/
private suspend fun refreshProduct(
historyProduct: HistoryProduct,
fieldsToRefresh: List<String>,
) {
val state = productRepository.getProductStateFull(
historyProduct.barcode,
fieldsToRefresh.joinToString(",")
)
// Products not found should be skipped
if (state.status <= 0L && state.statusVerbose?.contains("not found") != true) {
throw IOException("Could not sync history. Error with product ${state.code} ")
}
val product = state.product!!
val hp = HistoryProduct(
product.productName,
product.brands,
product.getSmallFrontImageUrl(localeManager.getLanguage()),
product.code,
product.quantity,
product.nutritionGradeFr,
product.ecoscore,
product.novaGroups
)
Log.d("syncOldHistory", hp.toString())
hp.lastSeen = historyProduct.lastSeen
daoSession.historyProductDao.insertOrReplace(hp)
}
}