CookDetailViewModel.kt 29 KB

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