123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- package com.develop.step.viewmodel
- import android.text.TextUtils
- import android.util.Log
- import androidx.lifecycle.LiveData
- import androidx.lifecycle.MutableLiveData
- import androidx.lifecycle.scopeNetLife
- import com.blankj.utilcode.util.FileUtils
- import com.blankj.utilcode.util.GsonUtils
- import com.blankj.utilcode.util.ToastUtils
- import com.blankj.utilcode.util.ZipUtils
- import com.develop.base.ext.globalApp
- import com.develop.base.mvvm.BaseViewModel
- import com.develop.base.util.FileKit
- import com.develop.base.util.MMkvUtils
- import com.develop.base.util.ThreadUtils
- import com.develop.common.bean.TranslateBean
- import com.develop.common.data_repo.FoodDataProvider
- import com.develop.common.data_repo.db.entity.DevAccessory
- import com.develop.common.data_repo.db.entity.DevRecipeCategory
- import com.develop.common.data_repo.db.entity.DevRecipeCookingStep
- import com.develop.common.data_repo.db.entity.DevRecipePortionSize
- import com.develop.common.data_repo.db.entity.UserOnLineRecipes
- import com.develop.common.data_repo.net.Api
- import com.develop.common.data_repo.net.model.response.RecipeDataConfig
- import com.develop.common.data_repo.net.model.response.RecipeDetailResult
- import com.develop.common.tag.CURRENT_LANGUAGE
- import com.develop.common.tag.CURRENT_USER_ID
- import com.develop.common.utils.Resource
- import com.develop.step.ui.recipes_detail.model.CookDetailInfo
- import com.develop.step.ui.recipes_detail.model.CookDetailTranslateBean
- import com.drake.net.Get
- import com.drake.net.Post
- import com.drake.net.component.Progress
- import com.drake.net.interfaces.ProgressListener
- import org.json.JSONObject
- import java.io.File
- class CookDetailViewModel : BaseViewModel() {
- var recipeLiveData = MutableLiveData<CookDetailInfo>()
- private val errorLiveData = MutableLiveData<Int>()
- val starCountLiveData = MutableLiveData<Int>()
- val downloadResource = MutableLiveData<Resource<Int>>()
- var portionSizeLiveData = MutableLiveData<DevRecipePortionSize>()
- var recipeNumber: String? = null
- private var mRecipeUrl: String? = null
- var cookDetailInfo :CookDetailInfo? = null
- //原始数据,用于做翻译功能
- var translateInfoInit : CookDetailTranslateBean? = null
- var cookingStep = mutableListOf<DevRecipeCookingStep>()
- var translateCookingStep = mutableListOf<DevRecipeCookingStep>()
- //是否线上菜谱
- var isRemote = false
- var language = MMkvUtils.getString(CURRENT_LANGUAGE) ?: "en"
- /**
- * 数据源: 食谱编号
- * 关联数据: [DevRecipe] 食谱基本数据
- * [DevRecipeAccessory] 食谱需要的配件
- * [DevAccessory] 单个配件数据
- * [DevRecipeFood] 食谱原料数据
- * [DevRecipeNutrition] 食谱营养数据
- * [DevRecipePortionSize] 食谱原料用量
- */
- fun queryRecipe(number: String, remote: Boolean, recipesEdition: String) {
- isRemote = remote
- this.recipeNumber = number
- if (remote) {
- scopeNetLife {
- Get<RecipeDetailResult>(Api.GET_RECIPES_DETAIL) {
- addQuery("recipeNumber", number)
- // addQuery("recipeEditon", recipesEdition)
- addQuery("lang", MMkvUtils.getString(CURRENT_LANGUAGE) ?: "EN")
- }.await().apply {
- mRecipeUrl = recipeUrl
- cookDetailInfo = CookDetailInfo(
- devRecipe,
- devAccessorys,
- devRecipeFoods,
- devRecipeNutritions,
- devRecipePortionSizes
- )
- //由于对象赋值问题,对象内存地址共用,估现在先转json,在重新赋值给初始实体
- var json = GsonUtils.toJson(cookDetailInfo)
- translateInfoInit = GsonUtils.fromJson(json,CookDetailTranslateBean::class.java)
- portionSizeLiveData.postValue(cookDetailInfo?.portionSize?.firstOrNull())
- recipeLiveData.postValue(cookDetailInfo)
- }
- }.catch {
- ToastUtils.showShort(it.message)
- }
- if (FoodDataProvider.isResourceDownload(number)) {
- downloadResource.value = Resource(100, Resource.Status.SUCCESS)
- }
- } else {
- FoodDataProvider.getDatabase().runInTransaction {
- var recipeDao = FoodDataProvider.getDatabase().recipeDao()
- var recipeBean = recipeDao.queryRecipe(number)
- if (recipeBean == null) {
- // show toast
- errorLiveData.postValue(ERR_NO_RECIPE_MATCH)
- return@runInTransaction
- }
- var includeAccessory = mutableListOf<DevAccessory>()
- var accessoryIds = recipeDao.queryAccessoryIds(number)
- for (accessoryId in accessoryIds) {
- val accessory = recipeDao.queryAccessory(accessoryId.accessoryNumber ?: "")
- if (accessory != null) {
- includeAccessory.add(accessory)
- }
- }
- var includeMaterial = recipeDao.queryFood(number)
- var includeNutrition = recipeDao.queryNutrition(number)
- var includePortionSize = recipeDao.queryPortionSize(number)
- cookDetailInfo = CookDetailInfo(
- recipeBean,
- includeAccessory,
- includeMaterial,
- includeNutrition,
- includePortionSize
- )
- //由于对象赋值问题,对象内存地址共用,估现在先转json,在重新赋值给初始实体
- var json = GsonUtils.toJson(cookDetailInfo)
- translateInfoInit = GsonUtils.fromJson(json,CookDetailTranslateBean::class.java)
- portionSizeLiveData.postValue(cookDetailInfo?.portionSize?.firstOrNull())
- recipeLiveData.postValue(cookDetailInfo)
- }
- }
- }
- fun getTranslateDetail(jsons :String,value: String){
- scopeNetLife {
- Post<String>(Api.TRANSLATE) {
- json(jsons)
- }.await().apply {
- //由于后端返回不规则key ,需特殊处理
- jsonTranslate( this,value)
- }
- }.catch {
- Log.e("TAG message",it.message.toString())
- ToastUtils.showShort(it.message)
- }
- }
- fun jsonTranslate (jsons: String,value: String){
- language = value
- var jsonObject = JSONObject(jsons)
- var jsonArray = jsonObject.getJSONArray(value)
- var size = jsonArray.length()-1
- for (i in 0 .. size){
- var jsonObject = jsonArray.getJSONObject(i)
- var id = jsonObject.getString("id")
- var valueList = jsonObject.getJSONArray("value")
- var value = valueList.getString(0)
- if (id=="name"){
- cookDetailInfo?.recipe?.name = value
- }
- if (id=="introduction"){
- cookDetailInfo?.recipe?.introduction = value
- }
- if (id=="difficulty"){
- cookDetailInfo?.recipe?.difficultyLevel = value
- }
- if (id.contains("foodname")){
- var ids = id
- var list = ids.split("_")
- var index = list[1].toInt()
- cookDetailInfo?.material?.get(index)?.foodName = value
- }
- if (id.contains("cookstep")){
- var ids = id
- var list = ids.split("_")
- var index = list[1].toInt()
- translateCookingStep[index].description = value
- }
- }
- portionSizeLiveData.postValue(cookDetailInfo?.portionSize?.firstOrNull())
- recipeLiveData.postValue(cookDetailInfo)
- }
- fun setTranslateDate(value :String):String{
- //需要添加步骤到翻译,由于菜谱详情没有获取,估在这重新获取
- //只获取一次,避免多次获取
- if (cookingStep.size<=0){
- cookingStep = FoodDataProvider
- .getDatabase()
- .recipeDao()
- .queryCookingStep(recipeNumber?:"").toMutableList()
- translateCookingStep = FoodDataProvider
- .getDatabase()
- .recipeDao()
- .queryCookingStep(recipeNumber?:"").toMutableList()
- }
- language = MMkvUtils.getString(CURRENT_LANGUAGE) ?:"en"
- var listLanguage = mutableListOf<String>()
- listLanguage.add(value)
- var translateList = mutableListOf<TranslateBean>()
- translateList.add(TranslateBean("name",translateInfoInit?.recipe?.name))
- translateList.add(TranslateBean("introduction",translateInfoInit?.recipe?.introduction))
- translateList.add(TranslateBean("difficulty",translateInfoInit?.recipe?.difficultyLevel))
- var size = translateInfoInit?.material?.size?:0
- if (size>0){
- size--
- }
- for (i in 0..size){
- // DevRecipeFood
- var material = translateInfoInit?.material?.get(i)
- material?.let {
- translateList.add(TranslateBean("foodname_"+i, it.foodName ?: ""))
- }
- }
- var sizeStep = cookingStep.size
- if (sizeStep>0){
- sizeStep--
- }
- for (i in 0..sizeStep){
- var cookingStep = cookingStep[i]
- cookingStep?.let {
- if (!TextUtils.isEmpty(it.description)){
- translateList.add(TranslateBean("cookstep_"+i, it.description ?: ""))
- }
- }
- }
- var map = HashMap<String,Any>()
- map["from"] = language.lowercase()
- map["tos"] = listLanguage
- map["translateList"] = translateList
- var json = GsonUtils.toJson(map)
- return json
- }
- fun getRecipeLiveData(): LiveData<CookDetailInfo> {
- return recipeLiveData
- }
- fun getErrorCodeLiveData(): LiveData<Int> {
- return errorLiveData
- }
- fun getStarCount(recipesId: String) {
- FoodDataProvider.getUserDatabase().runInTransaction {
- val userTag = FoodDataProvider.getUserDatabase().userInfoDao().queryUserTag(
- CURRENT_USER_ID, recipesId
- )
- userTag?.apply {
- starCountLiveData.postValue(starCount)
- }
- }
- }
- fun isDownloading(): Boolean {
- return downloadResource.value?.status == Resource.Status.LOADING
- }
- fun isDownloadSuccess(): Boolean {
- return downloadResource.value?.status == Resource.Status.SUCCESS
- }
- fun getDownloadState(): LiveData<Resource<Int>> {
- return downloadResource
- }
- fun downloadRecipe() {
- if (mRecipeUrl.isNullOrEmpty()) {
- downloadResource.value = Resource(0, Resource.Status.FAILURE)
- return
- }
- downloadResource.value = Resource(0, Resource.Status.LOADING)
- val downloadDir = globalApp().externalCacheDir.toString()
- val downloadName = System.nanoTime().toString()
- scopeNetLife {
- mRecipeUrl?.apply {
- val result = Get<File>(this) {
- setDownloadFileName(downloadName)
- setDownloadDir(downloadDir)
- addDownloadListener(object : ProgressListener() {
- override fun onProgress(p: Progress) {
- ThreadUtils.runOnMainThread {
- downloadResource.value =
- Resource(p.progress(), Resource.Status.LOADING)
- }
- }
- })
- }.await()
- if (!result.exists()) {
- ThreadUtils.runOnMainThread {
- downloadResource.value = Resource(0, Resource.Status.FAILURE)
- }
- } else {
- prepareResource(result)
- }
- }
- }.catch {
- ThreadUtils.runOnMainThread {
- downloadResource.value = Resource(0, Resource.Status.FAILURE)
- }
- }
- }
- private fun prepareResource(file: File) {
- try {
- val dst = ZipUtils.unzipFile(file, FoodDataProvider.getExtRecipeResourceDir())
- FileUtils.delete(file)
- if (dst.isNullOrEmpty()) {
- ThreadUtils.runOnMainThread {
- downloadResource.value = Resource(0, Resource.Status.FAILURE)
- }
- return
- }
- val jsonFile = FoodDataProvider.getResourceConfigJsonPath(recipeNumber!!)
- if (!jsonFile.exists()) {
- ThreadUtils.runOnMainThread {
- downloadResource.value = Resource(0, Resource.Status.FAILURE)
- }
- return
- }
- val jsonContent = FileKit.readFileToStringB(jsonFile)
- val contentData = GsonUtils.fromJson(jsonContent, RecipeDataConfig::class.java)
- // contentData.resetAllCodes()
- FoodDataProvider.getDatabase().runInTransaction {
- FoodDataProvider.getDatabase().recipeDao().apply {
- val categorys = queryAllCategory()
- val categoryMap = HashMap<String, DevRecipeCategory>()
- for (category in categorys) {
- categoryMap[category.number + ":" + category.lang] = category
- }
- for (devRecipeCategory in contentData.devRecipeCategorys) {
- if (categoryMap.containsKey(devRecipeCategory.number + ":" + devRecipeCategory.lang)) {
- devRecipeCategory.code =
- categoryMap[devRecipeCategory.number + ":" + devRecipeCategory.lang]?.code.toString()
- }
- }
- /**
- * 如果本地食谱存在的情况下
- * 下载在线食谱,需要删除本地食谱
- * **/
- contentData.devRecipes.forEach {
- var number = it.number ?: ""
- var lang = it.lang ?:"EN"
- deleteNumAndLangRecipe(number,lang)
- }
- //删除步骤 和其他一些
- recipeNumber?.let {
- deleteDevRecipeAccessorys(it)
- deleteDevRecipeCookingSteps(it)
- deleteDevRecipeFoods(it)
- deleteDevRecipeNutritions(it)
- deleteDevRecipeRelTags(it)
- deleteDevRecipePortionSizes(it)
- }
- // deleteRecipe(recipeNumber)
- insertDevAccessorys(contentData.devAccessorys)
- insertHotTags(contentData.devHotTags)
- insertDevPortraits(contentData.devPortraits)
- insertDevRecipeAccessorys(contentData.devRecipeAccessorys)
- insertDevRecipeCategorys(contentData.devRecipeCategorys)
- insertDevRecipeCookingSteps(contentData.devRecipeCookingSteps)
- insertDevRecipeFoods(contentData.devRecipeFoods)
- insertDevRecipeNutritions(contentData.devRecipeNutritions)
- insertDevRecipePortionSizes(contentData.devRecipePortionSizes)
- insertDevRecipeRelTags(contentData.devRecipeRelTags)
- insertDevRecipeTags(contentData.devRecipeTags)
- insertDevRecipes(contentData.devRecipes)
- }
- ThreadUtils.runOnMainThread {
- downloadResource.value = Resource(100, Resource.Status.SUCCESS)
- }
- }
- FoodDataProvider.getUserDatabase().runInTransaction {
- contentData.devRecipes.getOrNull(0)?.also {
- FoodDataProvider.getUserDatabase().userInfoDao().insertOnlineRecipe(
- UserOnLineRecipes(CURRENT_USER_ID, it.number ?: "")
- )
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- ThreadUtils.runOnMainThread {
- downloadResource.value = Resource(0, Resource.Status.FAILURE)
- }
- }
- }
- companion object {
- const val ERR_NO_RECIPE_MATCH = -1
- }
- }
|