CookDetailViewModel.kt 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. package com.develop.step.viewmodel
  2. import androidx.lifecycle.LiveData
  3. import androidx.lifecycle.MutableLiveData
  4. import androidx.lifecycle.scopeNetLife
  5. import com.blankj.utilcode.util.FileUtils
  6. import com.blankj.utilcode.util.GsonUtils
  7. import com.blankj.utilcode.util.ToastUtils
  8. import com.blankj.utilcode.util.ZipUtils
  9. import com.develop.base.ext.getSN
  10. import com.develop.base.ext.globalApp
  11. import com.develop.base.mvvm.BaseViewModel
  12. import com.develop.base.util.FileKit
  13. import com.develop.base.util.MMkvUtils
  14. import com.develop.base.util.ThreadUtils
  15. import com.develop.common.data_repo.FoodDataProvider
  16. import com.develop.common.data_repo.db.entity.DevAccessory
  17. import com.develop.common.data_repo.db.entity.DevRecipe
  18. import com.develop.common.data_repo.db.entity.DevRecipeCategory
  19. import com.develop.common.data_repo.db.entity.DevRecipeCookingStep
  20. import com.develop.common.data_repo.db.entity.DevRecipeFood
  21. import com.develop.common.data_repo.db.entity.DevRecipeNutrition
  22. import com.develop.common.data_repo.db.entity.DevRecipePortionSize
  23. import com.develop.common.data_repo.db.entity.UserOnLineRecipes
  24. import com.develop.common.data_repo.net.Api
  25. import com.develop.common.data_repo.net.model.response.RecipeDataConfig
  26. import com.develop.common.data_repo.net.model.response.RecipeDetailResult
  27. import com.develop.common.tag.CURRENT_LANGUAGE
  28. import com.develop.common.tag.CURRENT_USER_ID
  29. import com.develop.common.tuya_bean.RecipesBean
  30. import com.develop.common.utils.CommonUtils
  31. import com.develop.common.utils.Resource
  32. import com.develop.step.TuyaCookStepType
  33. import com.develop.step.ui.recipes_detail.model.CookDetailInfo
  34. import com.drake.net.Get
  35. import com.drake.net.component.Progress
  36. import com.drake.net.interfaces.ProgressListener
  37. import com.google.gson.Gson
  38. import java.io.File
  39. class CookDetailViewModel : BaseViewModel() {
  40. var sn = getSN()
  41. var recipeLiveData = MutableLiveData<CookDetailInfo>()
  42. private val errorLiveData = MutableLiveData<Int>()
  43. val starCountLiveData = MutableLiveData<Int>()
  44. val downloadResource = MutableLiveData<Resource<Int>>()
  45. var portionSizeLiveData = MutableLiveData<DevRecipePortionSize>()
  46. var addLikeLiveData = MutableLiveData<Boolean>()
  47. var deleteLikeLiveData = MutableLiveData<Boolean>()
  48. var stepLiveDataString = MutableLiveData<String>()
  49. var onfialLiveData = MutableLiveData<String>()
  50. var recipeNumber: String? = null
  51. private var mRecipeUrl: String? = null
  52. var tuyaRecipe = ""
  53. //是否线上菜谱
  54. var isRemote = false
  55. var isTuyaStep = false
  56. /**
  57. * 数据源: 食谱编号
  58. * 关联数据: [DevRecipe] 食谱基本数据
  59. * [DevRecipeAccessory] 食谱需要的配件
  60. * [DevAccessory] 单个配件数据
  61. * [DevRecipeFood] 食谱原料数据
  62. * [DevRecipeNutrition] 食谱营养数据
  63. * [DevRecipePortionSize] 食谱原料用量
  64. */
  65. fun queryRecipe(number: String, remote: Boolean, recipesEdition: String) {
  66. if (sn.startsWith("011")) {
  67. var lang = MMkvUtils.getString(CURRENT_LANGUAGE) ?: "en"
  68. var map = HashMap<String, Any>()
  69. map["lang"] = lang
  70. map["menuId"] = number
  71. var gson = Gson()
  72. var json = gson.toJson(map)
  73. CommonUtils.getTuyaBean<RecipesBean>("tuya.device.menu.get", "1.0",
  74. json, RecipesBean::class.java, object : CommonUtils.TuyaHttp<RecipesBean> {
  75. override fun bean(t: RecipesBean) {
  76. //处理涂鸦步骤
  77. isTuyaStep = true
  78. var devRecipeCookingStep = mutableListOf<DevRecipeCookingStep>()
  79. //步骤
  80. devRecipeCookingStep.addAll(getListStep(t.cookStepInfoVOList,number))
  81. //食谱
  82. val detailInfo = getTuyaRecipes(t,number, lang)
  83. tuyaRecipe = GsonUtils.toJson(detailInfo.recipe)
  84. stepLiveDataString.postValue(GsonUtils.toJson(devRecipeCookingStep))
  85. portionSizeLiveData.postValue(detailInfo.portionSize.firstOrNull())
  86. recipeLiveData.postValue(detailInfo)
  87. }
  88. override fun fail() {
  89. onfialLiveData.postValue("")
  90. }
  91. })
  92. } else {
  93. isRemote = remote
  94. this.recipeNumber = number
  95. if (remote) {
  96. scopeNetLife {
  97. Get<RecipeDetailResult>(Api.GET_RECIPES_DETAIL) {
  98. addQuery("recipeNumber", number)
  99. // addQuery("recipeEditon", recipesEdition)
  100. addQuery("lang", MMkvUtils.getString(CURRENT_LANGUAGE) ?: "EN")
  101. }.await().apply {
  102. mRecipeUrl = recipeUrl
  103. val detailInfo = CookDetailInfo(
  104. devRecipe,
  105. devAccessorys,
  106. devRecipeFoods,
  107. devRecipeNutritions,
  108. devRecipePortionSizes
  109. )
  110. portionSizeLiveData.postValue(detailInfo.portionSize.firstOrNull())
  111. recipeLiveData.postValue(detailInfo)
  112. }
  113. }.catch {
  114. ToastUtils.showShort(it.message)
  115. }
  116. if (FoodDataProvider.isResourceDownload(number)) {
  117. downloadResource.value = Resource(100, Resource.Status.SUCCESS)
  118. }
  119. } else {
  120. FoodDataProvider.getDatabase().runInTransaction {
  121. val recipeDao = FoodDataProvider.getDatabase().recipeDao()
  122. val recipeBean = recipeDao.queryRecipe(number)
  123. if (recipeBean == null) {
  124. // show toast
  125. errorLiveData.postValue(ERR_NO_RECIPE_MATCH)
  126. return@runInTransaction
  127. }
  128. val includeAccessory = mutableListOf<DevAccessory>()
  129. val accessoryIds = recipeDao.queryAccessoryIds(number)
  130. for (accessoryId in accessoryIds) {
  131. val accessory = recipeDao.queryAccessory(accessoryId.accessoryNumber ?: "")
  132. if (accessory != null) {
  133. includeAccessory.add(accessory)
  134. }
  135. }
  136. val includeMaterial = recipeDao.queryFood(number)
  137. val includeNutrition = recipeDao.queryNutrition(number)
  138. val includePortionSize = recipeDao.queryPortionSize(number)
  139. val detailInfo = CookDetailInfo(
  140. recipeBean,
  141. includeAccessory,
  142. includeMaterial,
  143. includeNutrition,
  144. includePortionSize
  145. )
  146. portionSizeLiveData.postValue(detailInfo.portionSize.firstOrNull())
  147. recipeLiveData.postValue(detailInfo)
  148. }
  149. }
  150. }
  151. }
  152. //涂鸦转换步骤
  153. fun getListStep(listStep: List<RecipesBean.CookStepInfoVOListBean>,number:String) :MutableList<DevRecipeCookingStep> {
  154. var devStepList = mutableListOf<DevRecipeCookingStep>()
  155. listStep.forEach {
  156. //判断有没有 有cookArgs是模式 ,没有就是描述
  157. var code = it.menuId + it.id
  158. var wordMode = ""
  159. var makeMode = ""
  160. var direction = "0"
  161. var description = ""
  162. var autoStart = "manual"
  163. var minute = 0
  164. var second = 0
  165. var rotateSpeed = 0
  166. var temperature = 0
  167. var updateTime = 0L
  168. var createTime = 0L
  169. var lang = ""
  170. var audioFileCode = ""
  171. var audioFilePath = ""
  172. var photoVideoFileCode = ""
  173. var photoVideoFilePath = ""
  174. var numbers = ""
  175. if (it.cookArgs==null) {
  176. wordMode = "DESCRIPTION"
  177. } else {
  178. it.cookArgs.forEach { cookArgs ->
  179. when (cookArgs.dpCode) {
  180. TuyaCookStepType.DIRECTION -> {
  181. if (cookArgs.dpValue == "true") {
  182. direction = "0"
  183. } else {
  184. direction = "1"
  185. }
  186. }
  187. TuyaCookStepType.GEAR -> {
  188. rotateSpeed = cookArgs.dpValue.toInt()
  189. }
  190. TuyaCookStepType.TEMPERATURE -> {
  191. temperature = cookArgs.dpValue.toInt()
  192. }
  193. TuyaCookStepType.TIME -> {
  194. var time = cookArgs.dpValue.toInt()
  195. val minutes: Int = time / 60 // 计算分钟
  196. val seconds: Int = time % 60
  197. minute = minutes
  198. second = seconds
  199. }
  200. TuyaCookStepType.MODE -> {
  201. when (cookArgs.dpValue) {
  202. TuyaCookStepType.DP_DIY -> {
  203. wordMode = TuyaCookStepType.ADAPTED_COOKING
  204. }
  205. TuyaCookStepType.DP_KNEAD -> {
  206. wordMode = TuyaCookStepType.KNEAD_TOUGH
  207. }
  208. TuyaCookStepType.DP_STEAM -> {
  209. wordMode = TuyaCookStepType.STEAM
  210. }
  211. TuyaCookStepType.DP_BOIL_WATER -> {
  212. wordMode = TuyaCookStepType.BOIL_WATER
  213. }
  214. TuyaCookStepType.DP_SOUS_VIDE -> {
  215. wordMode = TuyaCookStepType.SOVS_VIDE
  216. }
  217. TuyaCookStepType.DP_RICE -> {
  218. wordMode = TuyaCookStepType.COOK_RICE
  219. }
  220. TuyaCookStepType.DP_CHOP -> {
  221. wordMode = TuyaCookStepType.CHOP
  222. }
  223. TuyaCookStepType.DP_PULSE -> {
  224. wordMode = TuyaCookStepType.TURBO
  225. }
  226. TuyaCookStepType.DP_SMOOTHIE -> {
  227. wordMode = TuyaCookStepType.SMOOTHIE
  228. }
  229. TuyaCookStepType.DP_AUTO_CLEAN -> {
  230. wordMode = TuyaCookStepType.AUTO_CLEAN
  231. }
  232. TuyaCookStepType.DP_WEIGHT -> {
  233. wordMode = TuyaCookStepType.WIGHT
  234. }
  235. TuyaCookStepType.DP_DICE -> {
  236. wordMode = TuyaCookStepType.DICING
  237. }
  238. TuyaCookStepType.DP_CITRUS_FRUITS -> {
  239. wordMode = TuyaCookStepType.CITRUS_JUICER
  240. }
  241. TuyaCookStepType.DP_PEELING -> {
  242. wordMode = TuyaCookStepType.POTATO_PEELER
  243. }
  244. TuyaCookStepType.DP_PREHEATING -> {
  245. wordMode = TuyaCookStepType.SPECIAL_DIY_MODE
  246. }
  247. TuyaCookStepType.DP_TNTERMITTENT_STIR -> {
  248. wordMode = TuyaCookStepType.BROWN
  249. }
  250. TuyaCookStepType.DP_WARNING -> {
  251. wordMode = TuyaCookStepType.WARNING
  252. }
  253. }
  254. }
  255. }
  256. }
  257. }
  258. numbers = it.step.toString()
  259. it.langInfos.forEach { langInfosBean ->
  260. description = langInfosBean.desc
  261. lang = langInfosBean.lang
  262. }
  263. /**
  264. * val code: String,
  265. * val recipeNumber: String?,
  266. * val number: String?,
  267. * val workMode: String?,
  268. * val photoVideoFileCode: String?,
  269. * val photoVideoFilePath: String?,
  270. * val audioFileCode: String?,
  271. * val audioFilePath: String?,
  272. * val makeMode: String?,
  273. * val autoStart: String?,
  274. * val temperature: Int?,
  275. * val rotateDirection: String?,
  276. * val rotateSpeed: Int?,
  277. * val minute: Int?,
  278. * val second: Int?,
  279. * val description: String?,
  280. * val lang: String?,
  281. * val updateTime: Long?,
  282. * val createTime: Long?
  283. *
  284. * **/
  285. var dev = DevRecipeCookingStep(
  286. code.toString(),
  287. number,
  288. numbers,
  289. wordMode,
  290. photoVideoFileCode,
  291. photoVideoFilePath,
  292. audioFileCode,
  293. audioFilePath,
  294. makeMode,
  295. autoStart,
  296. temperature,
  297. direction,
  298. rotateSpeed,
  299. minute,
  300. second,
  301. description,
  302. lang,
  303. updateTime,
  304. createTime
  305. )
  306. devStepList.add(dev)
  307. }
  308. return devStepList
  309. }
  310. //涂鸦转换食谱
  311. fun getTuyaRecipes(t: RecipesBean, number: String, lang: String): CookDetailInfo {
  312. var cookTime = t.cookTime
  313. var makeHours = cookTime / 3600;
  314. var makeMinutes = (cookTime % 3600) / 60;
  315. var userNum = t.pv ?: 0
  316. var devRecipe = DevRecipe(
  317. t.id.toString(),
  318. t.id.toString(),
  319. "1.0",
  320. lang,
  321. "",
  322. t.mainImg,
  323. 0,
  324. 0,
  325. makeHours,
  326. makeMinutes,
  327. 0,
  328. 0,
  329. number,
  330. t.easyLevelDesc,
  331. "",
  332. t.name,
  333. t.desc,
  334. 0.0,
  335. userNum.toLong(),
  336. t.gmtModified,
  337. t.gmtCreate,
  338. "",
  339. ""
  340. )
  341. val includeAccessory = mutableListOf<DevAccessory>()
  342. var devRecipeFoodList = mutableListOf<DevRecipeFood>()
  343. var devRecipeNutritionList = mutableListOf<DevRecipeNutrition>()
  344. val includePortionSize = mutableListOf<DevRecipePortionSize>()
  345. //不add进去,那边会报错,直接随便新增一个
  346. includePortionSize.add(
  347. DevRecipePortionSize(
  348. "321654897",
  349. "2212zxc",
  350. "1542sqsc",
  351. "11wwss",
  352. lang,
  353. 1,
  354. 1
  355. )
  356. )
  357. var i = 1
  358. if (t.foodInfoVOList!=null){
  359. t.foodInfoVOList.forEach {
  360. var amout = 0.0
  361. var unit = ""
  362. if (it.menuFoodRelationVO.amount=="0"){
  363. amout = it.menuFoodRelationVO.secAmount.toDouble()
  364. if (it.menuFoodRelationVO.secUnitDesc==null){
  365. unit = "g"
  366. }else{
  367. unit = it.menuFoodRelationVO.secUnitDesc
  368. }
  369. }else{
  370. amout = it.menuFoodRelationVO.amount.toDouble()
  371. unit = "g"
  372. }
  373. devRecipeFoodList.add(
  374. DevRecipeFood(
  375. it.id.toString(),
  376. it.menuFoodRelationVO.foodId.toString(),
  377. amout,
  378. it.menuFoodRelationVO.menuId.toString(),
  379. lang,
  380. unit,
  381. it.name,
  382. "",
  383. it.gmtModified,
  384. it.gmtCreate
  385. )
  386. )
  387. it.foodNutritionVOList.forEach { food ->
  388. devRecipeNutritionList.add(
  389. DevRecipeNutrition(
  390. food.id.toString(),
  391. number,
  392. i.toString(),
  393. food.value.toDouble(),
  394. "g",
  395. "",
  396. lang,
  397. it.gmtModified,
  398. it.gmtCreate
  399. )
  400. )
  401. i++
  402. }
  403. }
  404. }
  405. return CookDetailInfo(
  406. devRecipe,
  407. includeAccessory,
  408. devRecipeFoodList,
  409. devRecipeNutritionList,
  410. includePortionSize
  411. )
  412. }
  413. fun addLikeRecipes(number: String) {
  414. var map = HashMap<String, Any>()
  415. map["menuId"] = number
  416. var gson = Gson()
  417. var json = gson.toJson(map)
  418. CommonUtils.getTuyaLike("tuya.device.menu.star.add", "1.0",
  419. json, object : CommonUtils.TuyaBooleanHttp {
  420. override fun bean(t: Boolean) {
  421. addLikeLiveData.postValue(t)
  422. }
  423. override fun fail() {
  424. onfialLiveData.postValue("")
  425. }
  426. })
  427. }
  428. fun deleteLikeRecipes(number: String) {
  429. var map = HashMap<String, Any>()
  430. map["menuId"] = number
  431. var gson = Gson()
  432. var json = gson.toJson(map)
  433. CommonUtils.getTuyaLike("tuya.device.menu.star.delete", "1.0",
  434. json, object : CommonUtils.TuyaBooleanHttp {
  435. override fun bean(t: Boolean) {
  436. deleteLikeLiveData.postValue(t)
  437. }
  438. override fun fail() {
  439. onfialLiveData.postValue("")
  440. }
  441. })
  442. }
  443. fun getRecipeLiveData(): LiveData<CookDetailInfo> {
  444. return recipeLiveData
  445. }
  446. fun getErrorCodeLiveData(): LiveData<Int> {
  447. return errorLiveData
  448. }
  449. fun getStarCount(recipesId: String) {
  450. FoodDataProvider.getUserDatabase().runInTransaction {
  451. val userTag = FoodDataProvider.getUserDatabase().userInfoDao().queryUserTag(
  452. CURRENT_USER_ID, recipesId
  453. )
  454. userTag?.apply {
  455. starCountLiveData.postValue(starCount)
  456. }
  457. }
  458. }
  459. fun isDownloading(): Boolean {
  460. return downloadResource.value?.status == Resource.Status.LOADING
  461. }
  462. fun isDownloadSuccess(): Boolean {
  463. return downloadResource.value?.status == Resource.Status.SUCCESS
  464. }
  465. fun getDownloadState(): LiveData<Resource<Int>> {
  466. return downloadResource
  467. }
  468. fun downloadRecipe() {
  469. if (mRecipeUrl.isNullOrEmpty()) {
  470. downloadResource.value = Resource(0, Resource.Status.FAILURE)
  471. return
  472. }
  473. downloadResource.value = Resource(0, Resource.Status.LOADING)
  474. val downloadDir = globalApp().externalCacheDir.toString()
  475. val downloadName = System.nanoTime().toString()
  476. scopeNetLife {
  477. mRecipeUrl?.apply {
  478. val result = Get<File>(this) {
  479. setDownloadFileName(downloadName)
  480. setDownloadDir(downloadDir)
  481. addDownloadListener(object : ProgressListener() {
  482. override fun onProgress(p: Progress) {
  483. ThreadUtils.runOnMainThread {
  484. downloadResource.value =
  485. Resource(p.progress(), Resource.Status.LOADING)
  486. }
  487. }
  488. })
  489. }.await()
  490. if (!result.exists()) {
  491. ThreadUtils.runOnMainThread {
  492. downloadResource.value = Resource(0, Resource.Status.FAILURE)
  493. }
  494. } else {
  495. prepareResource(result)
  496. }
  497. }
  498. }.catch {
  499. ThreadUtils.runOnMainThread {
  500. downloadResource.value = Resource(0, Resource.Status.FAILURE)
  501. }
  502. }
  503. }
  504. private fun prepareResource(file: File) {
  505. try {
  506. val dst = ZipUtils.unzipFile(file, FoodDataProvider.getExtRecipeResourceDir())
  507. FileUtils.delete(file)
  508. if (dst.isNullOrEmpty()) {
  509. ThreadUtils.runOnMainThread {
  510. downloadResource.value = Resource(0, Resource.Status.FAILURE)
  511. }
  512. return
  513. }
  514. val jsonFile = FoodDataProvider.getResourceConfigJsonPath(recipeNumber!!)
  515. if (!jsonFile.exists()) {
  516. ThreadUtils.runOnMainThread {
  517. downloadResource.value = Resource(0, Resource.Status.FAILURE)
  518. }
  519. return
  520. }
  521. val jsonContent = FileKit.readFileToStringB(jsonFile)
  522. val contentData = GsonUtils.fromJson(jsonContent, RecipeDataConfig::class.java)
  523. // contentData.resetAllCodes()
  524. FoodDataProvider.getDatabase().runInTransaction {
  525. FoodDataProvider.getDatabase().recipeDao().apply {
  526. val categorys = queryAllCategory()
  527. val categoryMap = HashMap<String, DevRecipeCategory>()
  528. for (category in categorys) {
  529. categoryMap[category.number + ":" + category.lang] = category
  530. }
  531. for (devRecipeCategory in contentData.devRecipeCategorys) {
  532. if (categoryMap.containsKey(devRecipeCategory.number + ":" + devRecipeCategory.lang)) {
  533. devRecipeCategory.code =
  534. categoryMap[devRecipeCategory.number + ":" + devRecipeCategory.lang]?.code.toString()
  535. }
  536. }
  537. /**
  538. * 如果本地食谱存在的情况下
  539. * 下载在线食谱,需要删除本地食谱
  540. * **/
  541. contentData.devRecipes.forEach {
  542. var number = it.number ?: ""
  543. var lang = it.lang ?: "EN"
  544. deleteNumAndLangRecipe(number, lang)
  545. }
  546. //删除步骤 和其他一些
  547. recipeNumber?.let {
  548. deleteDevRecipeAccessorys(it)
  549. deleteDevRecipeCookingSteps(it)
  550. deleteDevRecipeFoods(it)
  551. deleteDevRecipeNutritions(it)
  552. deleteDevRecipeRelTags(it)
  553. deleteDevRecipePortionSizes(it)
  554. }
  555. // deleteRecipe(recipeNumber)
  556. insertDevAccessorys(contentData.devAccessorys)
  557. insertHotTags(contentData.devHotTags)
  558. insertDevPortraits(contentData.devPortraits)
  559. insertDevRecipeAccessorys(contentData.devRecipeAccessorys)
  560. insertDevRecipeCategorys(contentData.devRecipeCategorys)
  561. insertDevRecipeCookingSteps(contentData.devRecipeCookingSteps)
  562. insertDevRecipeFoods(contentData.devRecipeFoods)
  563. insertDevRecipeNutritions(contentData.devRecipeNutritions)
  564. insertDevRecipePortionSizes(contentData.devRecipePortionSizes)
  565. insertDevRecipeRelTags(contentData.devRecipeRelTags)
  566. insertDevRecipeTags(contentData.devRecipeTags)
  567. insertDevRecipes(contentData.devRecipes)
  568. }
  569. ThreadUtils.runOnMainThread {
  570. downloadResource.value = Resource(100, Resource.Status.SUCCESS)
  571. }
  572. }
  573. FoodDataProvider.getUserDatabase().runInTransaction {
  574. contentData.devRecipes.getOrNull(0)?.also {
  575. FoodDataProvider.getUserDatabase().userInfoDao().insertOnlineRecipe(
  576. UserOnLineRecipes(CURRENT_USER_ID, it.number ?: "")
  577. )
  578. }
  579. }
  580. } catch (e: Exception) {
  581. e.printStackTrace()
  582. ThreadUtils.runOnMainThread {
  583. downloadResource.value = Resource(0, Resource.Status.FAILURE)
  584. }
  585. }
  586. }
  587. companion object {
  588. const val ERR_NO_RECIPE_MATCH = -1
  589. }
  590. }