提交昨天的修改:优化多个模块和UI效果

This commit is contained in:
2026-03-17 13:42:09 +08:00
parent 3cf9818dad
commit 28c7628321
41 changed files with 991 additions and 358 deletions
+2 -2
View File
@@ -4,10 +4,10 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-01-28T08:24:39.059017600Z"> <DropdownSelection timestamp="2026-03-16T07:12:10.978585600Z">
<Target type="DEFAULT_BOOT"> <Target type="DEFAULT_BOOT">
<handle> <handle>
<DeviceId pluginId="Default" identifier="serial=192.168.1.80:5555;connection=d6ad651e" /> <DeviceId pluginId="Default" identifier="serial=192.168.1.115:5555;connection=8c23341a" />
</handle> </handle>
</Target> </Target>
</DropdownSelection> </DropdownSelection>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="migrated" value="true" />
<option name="pristineConfig" value="false" />
<option name="userId" value="4ab8791:19ce5d9ffb1:-7ffe" />
</MTProjectMetadataState>
</option>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+4
View File
@@ -0,0 +1,4 @@
kotlin version: 2.0.21
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
1. Kotlin compile daemon is ready
+58 -25
View File
@@ -1,8 +1,14 @@
plugins { plugins {
alias(libs.plugins.android.application) // alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android) // alias(libs.plugins.kotlin.android)
id("com.google.devtools.ksp") version "2.0.21-1.0.27" // id("com.google.devtools.ksp") version "2.0.21-1.0.27"
id("com.android.application")
id("org.jetbrains.kotlin.android")
// id("com.google.dagger.hilt.android")
id("com.google.devtools.ksp")
id("kotlin-parcelize")
kotlin("kapt")
} }
android { android {
@@ -42,10 +48,12 @@ android {
"proguard-rules.pro" "proguard-rules.pro"
) )
signingConfig = signingConfigs.getByName("debug_507") signingConfig = signingConfigs.getByName("debug_507")
// buildConfigField("boolean", "DEBUG", "false")
} }
debug { debug {
//507扫码秤主板在android.buildTypes{}内增加 //507扫码秤主板在android.buildTypes{}内增加
signingConfig = signingConfigs.getByName("debug_507") signingConfig = signingConfigs.getByName("debug_507")
// buildConfigField("boolean", "DEBUG", "true")
} }
} }
compileOptions { compileOptions {
@@ -57,6 +65,7 @@ android {
} }
buildFeatures { buildFeatures {
viewBinding = true viewBinding = true
buildConfig = true
} }
packagingOptions { packagingOptions {
pickFirst("lib/armeabi-v7a/libserial_port.so") pickFirst("lib/armeabi-v7a/libserial_port.so")
@@ -74,7 +83,9 @@ android {
} }
// li // li
} }
val isDebug = gradle.startParameter.taskNames.any {
it.contains("debug", ignoreCase = true)
}
dependencies { dependencies {
implementation(fileTree("libs") { include("*.jar", "*.aar") }) implementation(fileTree("libs") { include("*.jar", "*.aar") })
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
@@ -86,32 +97,54 @@ dependencies {
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
implementation(libs.androidx.activity.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation("com.google.code.gson:gson:2.10.1") implementation(libs.gson)
implementation("com.squareup.okhttp3:okhttp:4.9.1") implementation(libs.okhttp)
implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") implementation(libs.logging.interceptor)
implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation(libs.retrofit)
implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation(libs.converter.gson)
implementation("io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.2") implementation(libs.baserecyclerviewadapterhelper4)
implementation("androidx.room:room-runtime:2.5.2") // room
ksp("androidx.room:room-compiler:2.5.2") implementation(libs.androidx.room.runtime)
implementation("androidx.room:room-ktx:2.5.2") // Kotlin扩展 ksp(libs.androidx.room.compiler)
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7") implementation(libs.androidx.room.ktx)
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
implementation("androidx.activity:activity-ktx:1.8.0")
// implementation("biz.laenger.android:vpbs:0.0.6") // implementation("biz.laenger.android:vpbs:0.0.6")
//必须 1.0.0 以上 // refresh-layout
implementation("io.github.scwang90:refresh-layout-kernel:3.0.0-alpha") implementation(libs.refresh.layout.kernel)
//核心必须依赖 implementation(libs.refresh.header.classics)
implementation("io.github.scwang90:refresh-header-classics:3.0.0-alpha") implementation(libs.refresh.header.radar)
//经典刷新头 implementation(libs.refresh.footer.classics)
implementation("io.github.scwang90:refresh-header-radar:3.0.0-alpha")
implementation("io.github.scwang90:refresh-footer-classics:3.0.0-alpha")
//经典加载
//implementation("com.geyifeng.immersionbar:immersionbar:3.2.2") //implementation("com.geyifeng.immersionbar:immersionbar:3.2.2")
}
// glide
implementation(libs.glide)
annotationProcessor(libs.compiler)
// camerax
implementation(libs.androidx.camera.core)
implementation(libs.androidx.camera.camera2)
implementation(libs.androidx.camera.lifecycle)
implementation(libs.androidx.camera.view)
implementation(libs.androidx.camera.extensions)
//pytorch
implementation (libs.pytorch.android)
implementation (libs.pytorch.android.torchvision)
// objectbox
if (isDebug) {
debugImplementation(libs.objectbox.android.objectbrowser)
} else {
releaseImplementation(libs.objectbox.android)
}
}
apply(plugin = "io.objectbox")
+49
View File
@@ -0,0 +1,49 @@
{
"_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.",
"_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.",
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
"entities": [
{
"id": "1:6465153867413579585",
"lastPropertyId": "4:3660727688686055762",
"name": "Food",
"properties": [
{
"id": "1:3688350375714699356",
"name": "id",
"type": 6,
"flags": 1
},
{
"id": "2:6503828433160216329",
"name": "name",
"type": 9
},
{
"id": "3:1726525909323356793",
"name": "foodIdx",
"type": 5
},
{
"id": "4:3660727688686055762",
"name": "foodVector",
"indexId": "1:5497952887792054610",
"type": 28,
"flags": 8
}
],
"relations": []
}
],
"lastEntityId": "1:6465153867413579585",
"lastIndexId": "1:5497952887792054610",
"lastRelationId": "0:0",
"lastSequenceId": "0:0",
"modelVersion": 5,
"modelVersionParserMinimum": 5,
"retiredEntityUids": [],
"retiredIndexUids": [],
"retiredPropertyUids": [],
"retiredRelationUids": [],
"version": 1
}
Binary file not shown.
+8
View File
@@ -4,7 +4,12 @@
<!-- android:sharedUserId="android.uid.system"--> <!-- android:sharedUserId="android.uid.system"-->
<uses-feature android:name="android.hardware.usb.host" /> <uses-feature android:name="android.hardware.usb.host" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
tools:ignore="ProtectedPermissions" /> tools:ignore="ProtectedPermissions" />
@@ -84,6 +89,9 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" /> tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity android:name="com.shuwei.dish.match.ui.DeviceConfigActivity" /> <activity android:name="com.shuwei.dish.match.ui.DeviceConfigActivity" />
<activity android:name="com.shuwei.dish.match.ui.SettingActivity"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity android:name="com.shuwei.dish.match.ui.SubmitFoodActivity" /> <activity android:name="com.shuwei.dish.match.ui.SubmitFoodActivity" />
<receiver <receiver
@@ -1,4 +1,4 @@
package com.sw.dualscreen.adapter package com.shuwei.dish.match.adapter
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -7,12 +7,10 @@ import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import com.chad.library.adapter4.BaseQuickAdapter import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.sw.dualscreen.R import com.shuwei.dish.match.R
import com.sw.dualscreen.databinding.ListItemFoodCollectionBinding import com.shuwei.dish.match.databinding.ListItemFoodCollectionBinding
import com.sw.dualscreen.ext.dp import com.shuwei.dish.match.objbox.FoodCollectionBean
import com.sw.dualscreen.ext.load import com.shuwei.dish.match.utils.ext.load
import com.sw.dualscreen.objbox.FoodCollectionBean
import com.sw.dualscreen.utils.GlideUtils
class FoodCollectionAdapter (var list: MutableList<FoodCollectionBean>) : class FoodCollectionAdapter (var list: MutableList<FoodCollectionBean>) :
BaseQuickAdapter<FoodCollectionBean, FoodCollectionAdapter.VH>(list) { BaseQuickAdapter<FoodCollectionBean, FoodCollectionAdapter.VH>(list) {
@@ -8,6 +8,8 @@ import android.content.SharedPreferences
import android.util.Log import android.util.Log
import com.shuwei.dish.match.R import com.shuwei.dish.match.R
import com.shuwei.dish.match.db.DatabaseProvider import com.shuwei.dish.match.db.DatabaseProvider
import com.shuwei.dish.match.objbox.FoodModule
import com.shuwei.dish.match.objbox.ObjectBox
import com.shuwei.dish.match.ui.InitActivity.Companion.TAG import com.shuwei.dish.match.ui.InitActivity.Companion.TAG
import com.shuwei.dish.match.utils.AppUtil import com.shuwei.dish.match.utils.AppUtil
import com.shuwei.dish.match.utils.BootReceiver import com.shuwei.dish.match.utils.BootReceiver
@@ -26,6 +28,7 @@ class BaseApp : Application() {
// GlobalData.deviceId = "39a7abdd06b3c7ab" // GlobalData.deviceId = "39a7abdd06b3c7ab"
val filter = IntentFilter(Intent.ACTION_BOOT_COMPLETED) val filter = IntentFilter(Intent.ACTION_BOOT_COMPLETED)
registerReceiver(BootReceiver(), filter) registerReceiver(BootReceiver(), filter)
ObjectBox.init(this)
} }
companion object { companion object {
@@ -18,8 +18,16 @@ abstract class BaseFragment<VB : ViewBinding> : Fragment() {
abstract fun inflateBinding(inflater: LayoutInflater, container: ViewGroup?): VB abstract fun inflateBinding(inflater: LayoutInflater, container: ViewGroup?): VB
abstract fun initialize()
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initialize()
}
} }
@@ -1,4 +1,4 @@
package com.sw.inbound.objbox package com.shuwei.dish.match.objbox
import android.graphics.Bitmap import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
@@ -1,4 +1,4 @@
package com.sw.inbound.objbox package com.shuwei.dish.match.objbox
import io.objectbox.annotation.Entity import io.objectbox.annotation.Entity
import io.objectbox.annotation.HnswIndex import io.objectbox.annotation.HnswIndex
@@ -1,31 +1,19 @@
package com.sw.inbound.objbox package com.shuwei.dish.match.objbox
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.net.Uri
import android.renderscript.Element.DataType
import android.util.Log import android.util.Log
import androidx.core.graphics.scale import androidx.core.graphics.scale
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.sw.inbound.MyApp import com.shuwei.dish.match.utils.AssetsTool
import com.sw.inbound.objbox.ObjectBox.boxStore import com.shuwei.dish.match.utils.LogSaveUtil
import com.sw.inbound.utils.AssetsTool import com.shuwei.dish.match.utils.ext.toJsonString
import com.sw.inbound.utils.ImageUtil
import com.sw.inbound.utils.LogSaveUtil
import com.sw.inbound.utils.ext.toJsonString
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
import io.objectbox.query.IdWithScore
import io.objectbox.query.Query
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import okhttp3.internal.closeQuietly
import org.pytorch.IValue import org.pytorch.IValue
import org.pytorch.Module import org.pytorch.Module
import org.pytorch.torchvision.TensorImageUtils import org.pytorch.torchvision.TensorImageUtils
import timber.log.Timber
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.IOException import java.io.IOException
@@ -313,7 +301,7 @@ object FoodModule {
} }
private fun logInfo(msg:String) { private fun logInfo(msg:String) {
Timber.tag("FoodModule").d(msg) Log.d("FoodModule", msg)
LogSaveUtil.saveLogFile(msg) LogSaveUtil.saveLogFile(msg)
} }
@@ -14,20 +14,19 @@
* limitations under the License. * limitations under the License.
*/ */
package com.sw.inbound.objbox package com.shuwei.dish.match.objbox
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.util.Log import android.util.Log
import com.sw.inbound.MyApp import com.shuwei.dish.match.base.BaseApp
import com.sw.inbound.utils.LogSaveUtil import com.shuwei.dish.match.utils.LogSaveUtil
import io.objectbox.Box import io.objectbox.Box
import io.objectbox.BoxStore import io.objectbox.BoxStore
import io.objectbox.BoxStoreBuilder import io.objectbox.BoxStoreBuilder
import io.objectbox.exception.DbException import io.objectbox.exception.DbException
import io.objectbox.exception.FileCorruptException import io.objectbox.exception.FileCorruptException
import io.objectbox.kotlin.boxFor import io.objectbox.kotlin.boxFor
import io.objectbox.query.IdWithScore
import io.objectbox.query.Query import io.objectbox.query.Query
import io.objectbox.sync.Sync import io.objectbox.sync.Sync
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -39,12 +38,12 @@ import java.io.FileInputStream
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.IOException import java.io.IOException
import java.util.zip.GZIPOutputStream import java.util.zip.GZIPOutputStream
import com.shuwei.dish.match.BuildConfig
/** /**
* Singleton to keep BoxStore reference and provide current list of Notes Objects. * Singleton to keep BoxStore reference and provide current list of Notes Objects.
* Inserts demo data if no Objects are stored. * Inserts demo data if no Objects are stored.
*/ */
@SuppressLint("LogNotTimber")
object ObjectBox { object ObjectBox {
// 确保所有设备/版本使用相同的objectbox-models/default.json // 确保所有设备/版本使用相同的objectbox-models/default.json
@@ -88,7 +87,7 @@ object ObjectBox {
} }
} }
if (com.sw.inbound.BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
var syncAvailable = if (Sync.isAvailable()) "available" else "unavailable" var syncAvailable = if (Sync.isAvailable()) "available" else "unavailable"
Log.d( Log.d(
TAG, TAG,
@@ -144,7 +143,7 @@ object ObjectBox {
e.printStackTrace() e.printStackTrace()
LogSaveUtil.saveLogFile("safeDbOp出现FileCorruptException异常:${e.message},${e.errorCode}") LogSaveUtil.saveLogFile("safeDbOp出现FileCorruptException异常:${e.message},${e.errorCode}")
// 使用安全调用替代 !! 断言,避免 NPE // 使用安全调用替代 !! 断言,避免 NPE
val app = MyApp.instance ?: return@withContext null val app = BaseApp.instance ?: return@withContext null
init(app) init(app)
null null
} catch (e: Exception) { } catch (e: Exception) {
@@ -10,6 +10,7 @@ import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.databinding.ActivityInitBinding import com.shuwei.dish.match.databinding.ActivityInitBinding
import com.shuwei.dish.match.db.AppRepository import com.shuwei.dish.match.db.AppRepository
import com.shuwei.dish.match.http.UrlConfig import com.shuwei.dish.match.http.UrlConfig
import com.shuwei.dish.match.objbox.FoodModule
import com.shuwei.dish.match.utils.AppUtil import com.shuwei.dish.match.utils.AppUtil
import com.shuwei.dish.match.utils.QRCodeUtil import com.shuwei.dish.match.utils.QRCodeUtil
import com.shuwei.dish.match.utils.SpTool import com.shuwei.dish.match.utils.SpTool
@@ -38,7 +39,9 @@ class InitActivity : BaseActivity() {
// useBackground(false) // useBackground(false)
binding = ActivityInitBinding.inflate(layoutInflater) binding = ActivityInitBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
lifecycleScope.launch {
FoodModule.init(this@InitActivity)
}
// setHeaderBackground(isHomePage = true) // setHeaderBackground(isHomePage = true)
setHeaderBgVisible(false) setHeaderBgVisible(false)
BaseApp.appVersion = AppUtil.getAppVersionCode(this).toString() BaseApp.appVersion = AppUtil.getAppVersionCode(this).toString()
@@ -59,9 +59,7 @@ class SamplingListActivity : BaseActivity() {
it.visible() it.visible()
it.setImageResource(R.drawable.ic_setting) it.setImageResource(R.drawable.ic_setting)
it.setOnClickListener { it.setOnClickListener {
startActivity<DeviceConfigActivity> { startActivity<SettingActivity>()
putExtra(DeviceConfigActivity.COOK_MODE, 2)
}
} }
}, backAction = { }, backAction = {
it.gone() it.gone()
@@ -86,7 +84,7 @@ class SamplingListActivity : BaseActivity() {
appViewModel.deleteCookFoodAndGoods(cookMode = 1, foodId = foodId, onFinish = action) appViewModel.deleteCookFoodAndGoods(cookMode = 1, foodId = foodId, onFinish = action)
} }
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent) super.onNewIntent(intent)
val isConfigPage = intent?.getBooleanExtra(IS_CONFIG_PAGE, false) ?: false val isConfigPage = intent?.getBooleanExtra(IS_CONFIG_PAGE, false) ?: false
if (isConfigPage) { if (isConfigPage) {
@@ -394,9 +392,7 @@ class SamplingListActivity : BaseActivity() {
rightBtnText = "去设置", rightBtnText = "去设置",
leftBtnClick = {}, leftBtnClick = {},
rightBtnClick = { rightBtnClick = {
startActivity<DeviceConfigActivity> { startActivity<SettingActivity>()
putExtra(DeviceConfigActivity.COOK_MODE, 2)
}
}) })
} }
@@ -59,9 +59,7 @@ class SelectDishActivity : BaseActivity() {
it.visible() it.visible()
it.setImageResource(R.drawable.ic_setting) it.setImageResource(R.drawable.ic_setting)
it.setOnClickListener { it.setOnClickListener {
startActivity<DeviceConfigActivity> { startActivity<SettingActivity>()
putExtra(DeviceConfigActivity.COOK_MODE, 1)
}
} }
}, backAction = { }, backAction = {
it.gone() it.gone()
@@ -107,9 +105,7 @@ class SelectDishActivity : BaseActivity() {
rightBtnText = "去设置", rightBtnText = "去设置",
leftBtnClick = {}, leftBtnClick = {},
rightBtnClick = { rightBtnClick = {
startActivity<DeviceConfigActivity> { startActivity<SettingActivity>()
putExtra(DeviceConfigActivity.COOK_MODE, 1)
}
} }
) )
} }
@@ -167,7 +163,7 @@ class SelectDishActivity : BaseActivity() {
appViewModel.deleteCookFoodAndGoods(cookMode = 0, foodId = foodId, onFinish = action) appViewModel.deleteCookFoodAndGoods(cookMode = 0, foodId = foodId, onFinish = action)
} }
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent) super.onNewIntent(intent)
runCatching { runCatching {
val isConfigPage = intent?.getBooleanExtra(IS_CONFIG_PAGE, false) ?: false val isConfigPage = intent?.getBooleanExtra(IS_CONFIG_PAGE, false) ?: false
@@ -1,4 +1,4 @@
package com.sw.dualscreen.activity.fragment package com.shuwei.dish.match.ui.fragment
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
@@ -7,38 +7,27 @@ import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import androidx.camera.view.PreviewView
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.sw.dualscreen.GlobalData import com.shuwei.dish.match.R
import com.sw.dualscreen.R import com.shuwei.dish.match.adapter.FoodCollectionAdapter
import com.sw.dualscreen.activity.CollectedFoodActivity import com.shuwei.dish.match.base.BaseFragment
import com.sw.dualscreen.activity.SettingActivity import com.shuwei.dish.match.databinding.FragmentCollectBinding
import com.sw.dualscreen.adapter.CollectFoodListAdapter import com.shuwei.dish.match.objbox.FoodCollectionBean
import com.sw.dualscreen.adapter.FoodCollectionAdapter import com.shuwei.dish.match.objbox.FoodModule
import com.sw.dualscreen.databinding.FragmentCollectBinding import com.shuwei.dish.match.objbox.ObjectBox
import com.sw.dualscreen.databinding.LayoutCameraPreviewBinding import com.shuwei.dish.match.ui.SettingActivity
import com.sw.dualscreen.ext.clickWithDebounce import com.shuwei.dish.match.utils.BitmapSaver
import com.sw.dualscreen.ext.dp import com.shuwei.dish.match.utils.Debouncer
import com.sw.dualscreen.model.response.FoodInfo import com.shuwei.dish.match.utils.ImageUtil
import com.sw.dualscreen.objbox.Food import com.shuwei.dish.match.utils.ext.clickWithDebounce
import com.sw.dualscreen.objbox.FoodCollectionBean import com.shuwei.dish.match.utils.ext.toast
import com.sw.dualscreen.objbox.FoodModule
import com.sw.dualscreen.objbox.ObjectBox
import com.sw.dualscreen.utils.BitmapSaver
import com.sw.dualscreen.utils.CameraUtils
import com.sw.dualscreen.utils.Debouncer
import com.sw.dualscreen.utils.ImageUploader
import com.sw.dualscreen.utils.ImageUtil
import com.sw.plate.utils.ToastUtils
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.RequestBody import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
class CollectFragment : BaseFragment<FragmentCollectBinding>() { class CollectFragment : BaseFragment<FragmentCollectBinding>() {
@@ -57,25 +46,22 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
} }
} }
private val searchFoodList = mutableListOf<FoodInfo>() // private val searchFoodList = mutableListOf<FoodInfo>()
private var settingActivity: SettingActivity? = null // private var settingActivity: SettingActivity? = null
private var checkedItem: FoodInfo? = null // private var checkedItem: FoodInfo? = null
private val searchFoodAdapter by lazy { // private val searchFoodAdapter by lazy {
CollectFoodListAdapter(searchFoodList).apply { // CollectFoodListAdapter(searchFoodList).apply {
setOnItemClickListener { adapter, view, position -> // setOnItemClickListener { adapter, view, position ->
searchFoodList.forEachIndexed { index, item -> item.isChecked = index == position } // searchFoodList.forEachIndexed { index, item -> item.isChecked = index == position }
checkedItem = searchFoodList[position] // checkedItem = searchFoodList[position]
notifyDataSetChanged() // notifyDataSetChanged()
selectedFoodId = checkedItem!!.foodId // selectedFoodId = checkedItem!!.foodId
selectedFoodName = checkedItem!!.foodName // selectedFoodName = checkedItem!!.foodName
} // }
} // }
} // }
private val debouncer = Debouncer(2000) private val debouncer = Debouncer(2000)
private lateinit var previewView: PreviewView private lateinit var settingActivity: SettingActivity
private val cameraUtils: CameraUtils by lazy {
CameraUtils(requireActivity())
}
private val collectionAdapter: FoodCollectionAdapter by lazy { private val collectionAdapter: FoodCollectionAdapter by lazy {
FoodCollectionAdapter(foodCollectionList).apply { FoodCollectionAdapter(foodCollectionList).apply {
@@ -94,18 +80,23 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
} }
} }
override fun inflateViewBinding(): FragmentCollectBinding {
override fun inflateBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentCollectBinding {
return FragmentCollectBinding.inflate(LayoutInflater.from(context)) return FragmentCollectBinding.inflate(LayoutInflater.from(context))
} }
//typealias CameraCallback = (Uri) -> Unit
private val cameraCallback: (Uri) -> Unit = { uri -> private val cameraCallback: (Uri) -> Unit = { uri ->
try { try {
val index = foodCollectionList.indexOfFirst { it.imageFile == null } val index = foodCollectionList.indexOfFirst { it.imageFile == null }
if (index == -1) { if (index == -1) {
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") toast("每次只允许保存${MAX_COUNT}条数据")
settingActivity?.hideWaitingDialog() hideWaitingDialog()
rerurn@ cameraCallback rerurn@cameraCallback
} }
activity?.runOnUiThread { activity?.runOnUiThread {
foodCollectionList[index].let { foodCollectionList[index].let {
@@ -117,7 +108,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
} }
collectionAdapter.notifyItemChanged(index) collectionAdapter.notifyItemChanged(index)
} }
// settingActivity?.hideWaitingDialog() // hideWaitingDialog()
Thread { Thread {
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap -> ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
getImageVector(index, bitmap) getImageVector(index, bitmap)
@@ -125,9 +116,9 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
}.start() }.start()
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
settingActivity?.hideWaitingDialog() hideWaitingDialog()
ToastUtils.showToast("程序异常${e.message}") toast("程序异常${e.message}")
settingActivity?.log("程序异常${e.message}") log("程序异常${e.message}")
} }
} }
@@ -141,15 +132,15 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
FoodModule.bitmap2FloatArray(bitmap, false) FoodModule.bitmap2FloatArray(bitmap, false)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
ToastUtils.showToast("操作失败") toast("操作失败")
settingActivity?.log("操作失败:${e.message}") log("操作失败:${e.message}")
settingActivity?.hideWaitingDialog() hideWaitingDialog()
return return
} }
val file = BitmapSaver.saveToAppFilesDir( val file = BitmapSaver.saveToAppFilesDir(
bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg" bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg"
) )
settingActivity?.log("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}") log("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
activity?.runOnUiThread { activity?.runOnUiThread {
foodCollectionList[index].let { foodCollectionList[index].let {
@@ -163,45 +154,35 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
if (bitmap.isRecycled.not()) { if (bitmap.isRecycled.not()) {
bitmap.recycle() bitmap.recycle()
} }
settingActivity?.hideWaitingDialog() hideWaitingDialog()
} }
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun takePhoto() { private fun takePhoto() {
val count = foodCollectionList.count { it.bitmap != null } val count = foodCollectionList.count { it.bitmap != null }
if (count >= MAX_COUNT) { if (count >= MAX_COUNT) {
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") toast("每次只允许保存${MAX_COUNT}条数据")
return return
} }
settingActivity?.showWaitingDialog("采集中……") showWaitingDialog("采集中……")
cameraUtils.takePhoto(cameraCallback) { errMsg -> settingActivity.takePhoto(succCallback = cameraCallback, failCallback = { errMsg ->
settingActivity?.hideWaitingDialog() hideWaitingDialog()
// ToastUtils.showToast("拍照异常,请重新操作") // toast("拍照异常,请重新操作")
// if (cameraErrorCount >= 10) { // if (cameraErrorCount >= 10) {
// ToastUtils.showToast("拍照异常,请重新操作") // toast("拍照异常,请重新操作")
// settingActivity?.log("拍照异常,请重新操作:$errMsg") // log("拍照异常,请重新操作:$errMsg")
// cameraErrorCount = 0 // cameraErrorCount = 0
// return@takePhoto // return@takePhoto
// } // }
// cameraErrorCount++ // cameraErrorCount++
// takePhoto() // takePhoto()
} })
} }
private var cameraErrorCount = 0
override fun initialize() { override fun initialize() {
settingActivity = activity as SettingActivity settingActivity = activity as SettingActivity
cameraUtils.initCamera() // 首次显示 CollectFragment 时初始化相机
val previewBinding = settingActivity.initCamera(binding.flCameraPreview)
LayoutCameraPreviewBinding.inflate(layoutInflater, binding.flCameraPreview)
previewView = previewBinding.previewView.also {
it.updateLayoutParams {
width = 456.dp
height = 342.dp
}
}
cameraUtils.setPreviewController(previewView)
binding.rvFoodList.let { binding.rvFoodList.let {
it.layoutManager = it.layoutManager =
@@ -214,16 +195,16 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
} }
binding.btnSave.setOnClickListener { binding.btnSave.setOnClickListener {
if (checkedItem == null || checkedItem!!.isChecked.not()) { // if (checkedItem == null || checkedItem!!.isChecked.not()) {
ToastUtils.showToast("请选择菜品名称") // toast("请选择菜品名称")
return@setOnClickListener // return@setOnClickListener
} // }
val count = foodCollectionList.count { it.imageFile != null } // val count = foodCollectionList.count { it.imageFile != null }
if (count == 0) { // if (count == 0) {
ToastUtils.showToast("请拍摄菜品照片") // toast("请拍摄菜品照片")
return@setOnClickListener // return@setOnClickListener
} // }
upload() // upload()
} }
binding.editFoodName.setOnEditorActionListener { v, actionId, event -> binding.editFoodName.setOnEditorActionListener { v, actionId, event ->
@@ -239,173 +220,103 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
} }
binding.btnCollectedFood.setOnClickListener { binding.btnCollectedFood.setOnClickListener {
startActivity(Intent(requireActivity(), CollectedFoodActivity::class.java)) // startActivity(Intent(requireActivity(), CollectedFoodActivity::class.java))
} }
binding.btnTakePhoto.clickWithDebounce { binding.btnTakePhoto.clickWithDebounce {
val count = foodCollectionList.count { it.bitmap != null } val count = foodCollectionList.count { it.bitmap != null }
if (count >= MAX_COUNT) { if (count >= MAX_COUNT) {
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据") toast("每次只允许保存${MAX_COUNT}条数据")
return@clickWithDebounce return@clickWithDebounce
} }
takePhoto() takePhoto()
} }
binding.btnClearData.setOnClickListener { clearData() } binding.btnClearData.setOnClickListener { clearData() }
binding.rvSearchFood.let { // binding.rvSearchFood.let {
it.layoutManager = GridLayoutManager(context, 2) // it.layoutManager = GridLayoutManager(context, 2)
it.adapter = searchFoodAdapter // it.adapter = searchFoodAdapter
} // }
searchFood() searchFood()
} }
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun upload() { private fun upload() {
lifecycleScope.launch { // lifecycleScope.launch {
val totalFileCount = foodCollectionList.count { it.imageFile != null } // val totalFileCount = foodCollectionList.count { it.imageFile != null }
settingActivity?.showWaitingDialog2("图片上传中0/$totalFileCount") // showWaitingDialog2("图片上传中0/$totalFileCount")
val params = HashMap<String, RequestBody>() // val params = HashMap<String, RequestBody>()
//params["placeId"] = restId.toRequestBody() // //params["placeId"] = restId.toRequestBody()
params["foodId"] = checkedItem!!.foodId.toRequestBody() // params["foodId"] = checkedItem!!.foodId.toRequestBody()
params["foodName"] = checkedItem!!.foodName!!.toRequestBody() // params["foodName"] = checkedItem!!.foodName!!.toRequestBody()
params["version"] = GlobalData.foodModelVersion.toRequestBody() // params["version"] = GlobalData.foodModelVersion.toRequestBody()
ImageUploader(totalList = foodCollectionList, uploadImage = { batch ->
val files = batch.map { it.imageFile }
val foodVectorList = batch.filter { it.imageVector != null }.map {
it.imageVector!!.joinToString(
separator = ",", prefix = "[", postfix = "]"
)
}
val foodVectorJson =
foodVectorList.joinToString(separator = ",", prefix = "[", postfix = "]")
Timber.tag(TAG).d("json=$foodVectorJson")
params["foodVector"] = foodVectorJson.toRequestBody()
settingActivity?.viewModel?.uploadCollectFoodPics(files, params)
}, onProgress = { count, batch, idList ->
//batch.forEach {
// it.uploadSuccess = true
//}
runBlocking {
activity?.runOnUiThread {
settingActivity?.showWaitingDialog2("图片上传中$count/$totalFileCount")
}
val foodList = batch.mapIndexed { index, it ->
Food(
collectId = if (index < idList.size) idList[index] else null,
foodId = checkedItem!!.foodId,
foodName = checkedItem!!.foodName,
foodVector = it.imageVector,
version = GlobalData.foodModelVersion
)
}
ObjectBox.putAll(foodList)
activity?.runOnUiThread {
batch.forEach { it.isFinish = true }
collectionAdapter.notifyDataSetChanged()
}
}
}, onError = {
activity?.runOnUiThread {
binding.root.postDelayed({
settingActivity?.hideWaitingDialog()
ToastUtils.showToast("上传失败,请稍后重试")
}, 1000)
}
}, onComplete = {
//vectorThread()
binding.root.postDelayed({
settingActivity?.hideWaitingDialog()
ToastUtils.showToast("上传成功")
}, 1000)
}).processUploads()
}
// for (index in foodCollectionList.indices step 5) {
// val end = if(index + 5 < foodCollectionList.size - 1) index + 5 else foodCollectionList.size - 1
// val subList = foodCollectionList.subList(index, end)
// val subFiles = subList.map { it.imageFile }
// uploadCollectFoodPics(subFiles, params) { isSuccess->
// Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
// subList.filter { it.imageFile!=null }.forEach { it.uploadSuccess = isSuccess }
// //
//// val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() } // ImageUploader(totalList = foodCollectionList, uploadImage = { batch ->
//// runOnUiThread { // val files = batch.map { it.imageFile }
//// binding.btnUploadImage.text = "待上传图片${count}张" // val foodVectorList = batch.filter { it.imageVector != null }.map {
//// if (count == 0) { // it.imageVector!!.joinToString(
//// Loading.dismiss() // separator = ",", prefix = "[", postfix = "]"
//// } // )
//// } // }
// } // val foodVectorJson =
// foodVectorList.joinToString(separator = ",", prefix = "[", postfix = "]")
// log("json=$foodVectorJson")
// params["foodVector"] = foodVectorJson.toRequestBody()
// viewModel?.uploadCollectFoodPics(files, params)
// }, onProgress = { count, batch, idList ->
// //batch.forEach {
// // it.uploadSuccess = true
// //}
// runBlocking {
// activity?.runOnUiThread {
// showWaitingDialog2("图片上传中$count/$totalFileCount")
// }
// val foodList = batch.mapIndexed { index, it ->
// Food(
// collectId = if (index < idList.size) idList[index] else null,
// foodId = checkedItem!!.foodId,
// foodName = checkedItem!!.foodName,
// foodVector = it.imageVector,
// version = GlobalData.foodModelVersion
// )
// }
// ObjectBox.putAll(foodList)
// activity?.runOnUiThread {
// batch.forEach { it.isFinish = true }
// collectionAdapter.notifyDataSetChanged()
// }
// }
// }, onError = {
// activity?.runOnUiThread {
// binding.root.postDelayed({
// hideWaitingDialog()
// toast("上传失败,请稍后重试")
// }, 1000)
// }
// }, onComplete = {
// //vectorThread()
// binding.root.postDelayed({
// hideWaitingDialog()
// toast("上传成功")
// }, 1000)
// }).processUploads()
// } // }
} }
// private fun vectorThread() {
// settingActivity?.showWaitingDialog("加载中……")
// Thread {
// foodCollectionList
//// .filter { it.bitmap != null }
//// .filter { it.imageVector != null }
// .forEachIndexed { index, it ->
// if (it.imageVector == null) {
// return@forEachIndexed
// }
// image2VectorTask(imageVector = it.imageVector!!, index)
// }
// activity?.runOnUiThread {
// binding.root.postDelayed({
// settingActivity?.hideWaitingDialog()
// }, 1000)
// }
// }.start()
// }
// private fun image2VectorTask(imageVector: FloatArray?, position: Int) {
// if (imageVector == null) return
////// val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!)
//////
//////// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector)
//////// Timber.tag("mzf1").e(base64Str)
////////// viewModel.postImageData(
////////// context,
////////// foodId = selectedFoodId.toString(),
////////// foodName = selectedFoodName.toString(),
////////// foodVector = base64Str,
////////// uri = item.imageUri!!
////////// )
//// box.put(
//// Food(
//// collectId = null,
//// foodId = checkedItem!!.foodId,
//// foodName = checkedItem!!.foodName,
//// foodVector = imageVector,
//// version = "1.0.0"
//// )
//// )
//// if (position > -1) {
//// foodCollectionList[position].isFinish = true
//// activity?.runOnUiThread {
//// collectionAdapter.notifyItemChanged(position)
//// }
//// }
// }
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun searchFood() { fun searchFood() {
debouncer.debounce { debouncer.debounce {
settingActivity?.searchByFoodName(binding.editFoodName.text.toString()) { searchByFoodName(binding.editFoodName.text.toString()) {
searchFoodList.clear() // searchFoodList.clear()
searchFoodList.addAll(it) // searchFoodList.addAll(it)
searchFoodAdapter.notifyDataSetChanged() // searchFoodAdapter.notifyDataSetChanged()
} }
} }
} }
private var clickIndex = -1 var clickIndex = -1
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun clearData() { fun clearData() {
foodCollectionList.forEach { foodCollectionList.forEach {
it.bitmap = null it.bitmap = null
it.imageVector = null it.imageVector = null
@@ -422,20 +333,27 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
searchFood() searchFood()
} }
private var isFirstOpen = true
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
cameraUtils.bind() if (isVisible.not()) return
binding.llCameraFlag.run { binding.llCameraFlag.run {
visibility = View.VISIBLE visibility = View.VISIBLE
postDelayed({ postDelayed({
visibility = View.GONE visibility = View.GONE
}, 3000) }, 1000)
} }
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
cameraUtils.unbind()
binding.llCameraFlag.visibility = View.VISIBLE binding.llCameraFlag.visibility = View.VISIBLE
} }
private fun log(msg: String) {}
private fun searchByFoodName(name: String, block:(String)-> Unit) {}
private fun hideWaitingDialog() {}
private fun showWaitingDialog(msg: String) {}
private fun showWaitingDialog2(msg: String) {}
} }
@@ -0,0 +1,365 @@
package com.shuwei.dish.match.ui.fragment
import android.graphics.Typeface
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan
import android.text.style.LineHeightSpan
import android.text.style.StyleSpan
import android.util.Log
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.graphics.toColorInt
import androidx.core.view.forEach
import androidx.lifecycle.ViewModelProvider
import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.base.BaseFragment
import com.shuwei.dish.match.databinding.FragmentDeviceConfigBinding
import com.shuwei.dish.match.db.AppRepository
import com.shuwei.dish.match.dialog.CommonDialog
import com.shuwei.dish.match.dialog.SeasoningSearchDialog
import com.shuwei.dish.match.entity.SeasoningEntity
import com.shuwei.dish.match.entity.ResetReasoningRecord
import com.shuwei.dish.match.adapter.TextCellAdapter
import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.utils.AddressUtil
import com.shuwei.dish.match.utils.JsonAssetsLoader
import com.shuwei.dish.match.utils.MultiClickDetector
import com.shuwei.dish.match.utils.WeightUtil
import com.shuwei.dish.match.utils.ext.appendText
import com.shuwei.dish.match.utils.ext.buildSpannableString
import com.shuwei.dish.match.utils.ext.dp
import com.shuwei.dish.match.utils.ext.clickWithDebounce
import com.shuwei.dish.match.utils.ext.gone
import com.shuwei.dish.match.utils.ext.toast
import com.shuwei.dish.match.utils.ext.visible
import com.shuwei.dish.match.viewmodel.AppViewModel
import com.shuwei.dish.match.viewmodel.factory.AppFactory
import com.shuwei.dish.match.databinding.LayoutFoodRemindBinding
import com.shuwei.dish.match.ui.SamplingListActivity
import com.shuwei.dish.match.ui.SelectDishActivity
import com.shuwei.dish.match.utils.SpTool
import com.shuwei.dish.match.utils.ext.startActivity
/**
* 设备配置Fragment
* 功能:支持三种模式选择(制作、采样、品控),调料网格配置管理
*/
class DeviceConfigFragment : BaseFragment<FragmentDeviceConfigBinding>() {
companion object {
const val TAG = "DeviceConfigFragment"
const val COOK_MODE = "cookMode"
val modeList = listOf<ModeBean>(
ModeBean("制作模式", "菜品快速制作,记录熟重"),
ModeBean("采样模式", "菜品快速制作,记录熟重"),
ModeBean("品控模式", "菜品快速制作,记录熟重")
)
fun newInstance(cookMode: Int = 0): DeviceConfigFragment {
return DeviceConfigFragment().apply {
arguments = Bundle().apply {
putInt(COOK_MODE, cookMode)
}
}
}
}
data class ModeBean(
var modeName: String,
var modeDesc: String
)
private lateinit var appViewModel: AppViewModel
private var cookMode: Int = 0
private val weightArray = SparseArray<Double>()
private val addressArray = AddressUtil.getWeighAddressArray()
private var seasoningItems = mutableListOf<SeasoningEntity>()
private val detector = MultiClickDetector(targetCount = 10, intervalMs = 800)
override fun inflateBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentDeviceConfigBinding {
return FragmentDeviceConfigBinding.inflate(inflater, container, false)
}
override fun initialize(){
cookMode = arguments?.getInt(COOK_MODE, 0) ?: 0
initViewModel()
initUI()
addWeighListener()
addGridItemListener()
loadSeasoning()
}
/**
* 初始化ViewModel
*/
private fun initViewModel() {
val db = BaseApp.instance!!.database
val factory = AppFactory(AppRepository(db.appDao()))
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
}
/**
* 初始化UI
*/
private fun initUI() {
loadQualitySpan(isEnable = false)
when (cookMode) {
1 -> {
binding.rbModeCook.isChecked = true
binding.rbModeSampling.isChecked = false
loadCookSpan(isClicked = true)
loadSamplingSpan()
}
2 -> {
binding.rbModeCook.isChecked = false
binding.rbModeSampling.isChecked = true
loadCookSpan()
loadSamplingSpan(isClicked = true)
}
else -> {
binding.rbModeCook.isChecked = true
binding.rbModeSampling.isChecked = false
loadCookSpan(isClicked = true)
loadSamplingSpan()
}
}
binding.rbModeCook.setOnClickListener {
SpTool.put(SpTool.LAUNCH_PAGE_TYPE, 0)
binding.rbModeCook.isChecked = true
binding.rbModeSampling.isChecked = false
loadCookSpan(isClicked = true)
loadSamplingSpan()
activity?.startActivity<SelectDishActivity> {
putExtra(SelectDishActivity.IS_CONFIG_PAGE, true)
}
activity?.finish()
}
binding.rbModeSampling.setOnClickListener {
SpTool.put(SpTool.LAUNCH_PAGE_TYPE, 1)
binding.rbModeCook.isChecked = false
binding.rbModeSampling.isChecked = true
loadCookSpan()
loadSamplingSpan(isClicked = true)
activity?.startActivity<SamplingListActivity> {
putExtra(SamplingListActivity.IS_CONFIG_PAGE, true) }
activity?.finish()
}
}
/**
* 添加称重监听
*/
private fun addWeighListener() {
WeightUtil.addWeightListener(
weightKey = TAG,
getWeight = { address, state, weight ->
Log.d(TAG, "addWeighListener: address=$address,stat=$state,weight=$weight")
weightArray.put(address, weight)
val item = seasoningItems.firstOrNull { address == addressArray[it.sort] }
item?.let {
it.useWeight = weight.toDouble()
updateGridData(it)
}
Log.d(TAG, "addWeighListener: update-----------------------")
})
}
/**
* 添加网格项点击监听
*/
private fun addGridItemListener() {
binding.include.root.forEach { child ->
child.clickWithDebounce {
val sort = child.tag.toString().toInt()
val entity = seasoningItems.firstOrNull { it.sort == sort } ?: SeasoningEntity()
clickGridItem(sort, entity)
}
}
}
/**
* 加载调料数据
*/
private fun loadSeasoning() {
appViewModel.loadSeasoning {
seasoningItems.clear()
seasoningItems.addAll(it)
initConfigData()
setGridData(seasoningItems)
}
}
/**
* 初始化配置数据,确保有12个调料位置
*/
private fun initConfigData() {
repeat(12) { num ->
val firstOne = seasoningItems.firstOrNull { it.sort == num }
if (firstOne == null) {
seasoningItems.add(SeasoningEntity().also { it.sort = num })
}
}
}
/**
* 设置网格数据
*/
private fun setGridData(list: MutableList<SeasoningEntity>) {
val gridLayout = binding.include.root
list.forEach { entity ->
val tag = entity.sort.toString()
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
TextCellAdapter.loadLayout(frameLayout, entity)
}
}
/**
* 更新网格数据
*/
private fun updateGridData(entity: SeasoningEntity) {
val gridLayout = binding.include.root
val tag = entity.sort.toString()
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
TextCellAdapter.loadLayout(frameLayout, entity)
}
/**
* 点击网格项,打开调料搜索对话框
*/
private fun clickGridItem(sort: Int, entity: SeasoningEntity) {
val currentAddress = AddressUtil.getWeighAddressArray().get(sort)
SeasoningSearchDialog(
weighIndex = sort,
weighAddress = currentAddress,
clickName = entity.goodsName
).show(requireActivity() as BaseActivity) { item ->
syncItem(entity, item)
// 3-调料
entity.materialType = 3
entity.sort = sort
saveSeasoning(entity) {
val tag = sort.toString()
val gridLayout = binding.include.root
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
TextCellAdapter.loadLayout(frameLayout, entity)
}
}
}
/**
* 同步调料项数据
*/
private fun syncItem(oldItem: SeasoningEntity, newItem: SeasoningEntity) {
oldItem.run {
goodsId = newItem.goodsId
goodsName = newItem.goodsName
goodsOrRelationCode = newItem.goodsOrRelationCode
relateionType = newItem.relateionType
materialType = newItem.materialType
allEdible = newItem.allEdible
useWeight = newItem.useWeight
popularName = newItem.popularName
canteenId = newItem.canteenId
relateionType_dictText = newItem.relateionType_dictText
foodId = newItem.foodId
sort = newItem.sort
}
}
/**
* 保存调料数据
*/
fun saveSeasoning(entity: SeasoningEntity, action: () -> Unit = {}) {
appViewModel.saveSeasoning(entity) {
action()
toast("保存成功")
}
}
/**
* 加载品控模式文本样式
*/
private fun loadQualitySpan(isClicked: Boolean = false, isEnable: Boolean = true) {
binding.rbModeQuality.text =
getModeTextSpan(
topText = modeList[2].modeName,
bottomText = modeList[2].modeDesc,
topColor = if (isEnable) if (isClicked) "#00BC71" else "#000000" else "#B4B4B4",
bottomColor = if (isEnable) "#8B8B8B" else "#B4B4B4"
)
}
/**
* 加载采样模式文本样式
*/
private fun loadSamplingSpan(isClicked: Boolean = false, isEnable: Boolean = true) {
binding.rbModeSampling.text =
getModeTextSpan(
topText = modeList[1].modeName,
bottomText = modeList[1].modeDesc,
topColor = if (isEnable) if (isClicked) "#00BC71" else "#000000" else "#B4B4B4",
bottomColor = if (isEnable) "#8B8B8B" else "#B4B4B4"
)
}
/**
* 加载制作模式文本样式
*/
private fun loadCookSpan(isClicked: Boolean = false, isEnable: Boolean = true) {
binding.rbModeCook.text =
getModeTextSpan(
topText = modeList[0].modeName,
bottomText = modeList[0].modeDesc,
topColor = if (isEnable) if (isClicked) "#00BC71" else "#000000" else "#B4B4B4",
bottomColor = if (isEnable) "#8B8B8B" else "#B4B4B4"
)
}
/**
* 生成模式文本样式
*/
private fun getModeTextSpan(
topText: String,
topColor: String,
bottomText: String,
bottomColor: String
): SpannableStringBuilder {
return buildSpannableString {
appendText(
topText,
ForegroundColorSpan(topColor.toColorInt()),
StyleSpan(Typeface.BOLD),
AbsoluteSizeSpan(36, true),
LineHeightSpan { text, start, end, spanstartv, v, fm ->
fm.descent += 10.dp // 增加行间距
}
)
append("\n")
appendText(
bottomText,
ForegroundColorSpan(bottomColor.toColorInt()),
AbsoluteSizeSpan(26, true)
)
}
}
override fun onDestroyView() {
super.onDestroyView()
// 移除称重监听
WeightUtil.removeWeightListener(TAG)
}
}
@@ -87,8 +87,7 @@ class DishListFragment : BaseFragment<FragmentDishListBinding>() {
return FragmentDishListBinding.inflate(inflater, container, false) return FragmentDishListBinding.inflate(inflater, container, false)
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun initialize() {
super.onViewCreated(view, savedInstanceState)
activity = requireActivity() as SelectDishActivity activity = requireActivity() as SelectDishActivity
dinnerType = arguments?.getString(DINNER_TYPE, "0") ?: "0" dinnerType = arguments?.getString(DINNER_TYPE, "0") ?: "0"
binding.rvDishList.run { binding.rvDishList.run {
@@ -1,4 +1,4 @@
package com.sw.inbound.utils package com.shuwei.dish.match.utils
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
@@ -1,4 +1,4 @@
package com.sw.dualscreen.utils package com.shuwei.dish.match.utils
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.os.Environment import android.os.Environment
@@ -1,4 +1,4 @@
package com.sw.dualscreen.utils package com.shuwei.dish.match.utils
import android.net.Uri import android.net.Uri
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
@@ -1,4 +1,4 @@
package com.sw.dualscreen.utils package com.shuwei.dish.match.utils
/** /**
* 防抖工具 * 防抖工具
@@ -1,4 +1,4 @@
package com.sw.dualscreen.utils package com.shuwei.dish.match.utils
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
@@ -1,4 +1,4 @@
package com.sw.dualscreen.utils package com.shuwei.dish.match.utils
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
@@ -1,7 +1,7 @@
package com.sw.inbound.utils package com.shuwei.dish.match.utils
import com.sw.inbound.MyApp import android.util.Log
import timber.log.Timber import com.shuwei.dish.match.base.BaseApp
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@@ -21,11 +21,11 @@ object LogSaveUtil {
try { try {
saveLog(pattern, msg) saveLog(pattern, msg)
} catch (e: Exception) { } catch (e: Exception) {
Timber.tag(TAG).e(e, "Error saving crash info to file") Log.d(TAG, "Error saving crash info to file:${e.message}")
try { try {
saveLog(pattern, "Error saving crash info to file:${e.message}") saveLog(pattern, "Error saving crash info to file:${e.message}")
} catch (e: Exception) { } catch (e: Exception) {
Timber.tag(TAG).e(e, "save exception") Log.d(TAG, "save exception:${e.message}")
} }
} }
} }
@@ -41,18 +41,18 @@ object LogSaveUtil {
val saveTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date()) val saveTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date())
FileOutputStream(crashFile, true).use { it.write("$saveTime||$logInfo\n".toByteArray()) } FileOutputStream(crashFile, true).use { it.write("$saveTime||$logInfo\n".toByteArray()) }
Timber.tag(TAG).d("Crash info saved to: ${crashFile.absolutePath}") Log.d(TAG,"Crash info saved to: ${crashFile.absolutePath}")
} }
fun getCrashDir(): File { fun getCrashDir(): File {
//val crashDir = File(context.getExternalFilesDir(null), CRASH_REPORTS_DIR) //val crashDir = File(context.getExternalFilesDir(null), CRASH_REPORTS_DIR)
var crashDir = File(MyApp.instance!!.filesDir, CRASH_REPORTS_DIR) var crashDir = File(BaseApp.instance!!.filesDir, CRASH_REPORTS_DIR)
if (!crashDir.exists()) { if (!crashDir.exists()) {
crashDir.mkdirs() crashDir.mkdirs()
} }
if (!(crashDir.exists())) { if (!(crashDir.exists())) {
crashDir = File(MyApp.instance!!.cacheDir, CRASH_REPORTS_DIR) crashDir = File(BaseApp.instance!!.cacheDir, CRASH_REPORTS_DIR)
} }
return crashDir return crashDir
} }
@@ -1,4 +1,4 @@
package com.sw.dualscreen.utils package com.shuwei.dish.match.utils
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
@@ -6,7 +6,6 @@ import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException import androidx.camera.core.ImageCaptureException
import androidx.camera.view.CameraController import androidx.camera.view.CameraController
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import timber.log.Timber
import java.io.File import java.io.File
/** /**
@@ -43,7 +42,7 @@ class PhotoCaptureHelper(
fileNamePrefix: String = "IMG_", fileNamePrefix: String = "IMG_",
fileExtension: String = ".jpg" fileExtension: String = ".jpg"
) { ) {
Timber.d("开始拍照采集") // Timber.d("开始拍照采集")
try { try {
val executor = ContextCompat.getMainExecutor(context) val executor = ContextCompat.getMainExecutor(context)
@@ -62,7 +61,7 @@ class PhotoCaptureHelper(
object : ImageCapture.OnImageSavedCallback { object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
val photoUri = outputFileResults.savedUri ?: Uri.fromFile(photoFile) val photoUri = outputFileResults.savedUri ?: Uri.fromFile(photoFile)
Timber.d("照片保存成功: $photoUri") // Timber.d("照片保存成功: $photoUri")
onSuccess(photoUri) onSuccess(photoUri)
callbackList.forEach { callbackList.forEach {
it(photoUri) it(photoUri)
@@ -78,14 +77,14 @@ class PhotoCaptureHelper(
} }
} }
Timber.e(exception, errorMsg) // Timber.e(exception, errorMsg)
onError(errorMsg) onError(errorMsg)
} }
} }
) )
} catch (e: Exception) { } catch (e: Exception) {
val errorMsg = "创建临时文件失败: ${e.message}" val errorMsg = "创建临时文件失败: ${e.message}"
Timber.e(e, errorMsg) // Timber.e(e, errorMsg)
onError(errorMsg) onError(errorMsg)
} }
} }
@@ -1,6 +1,8 @@
package com.shuwei.dish.match.utils package com.shuwei.dish.match.utils
import android.content.Context import android.content.Context
import android.os.Handler
import android.os.Looper
import android.view.Gravity import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -11,7 +13,20 @@ import com.shuwei.dish.match.R
object ToastUtil { object ToastUtil {
fun show(context: Context, message: String, duration:Int = Toast.LENGTH_SHORT) { private val mainHandler = Handler(Looper.getMainLooper())
fun show(context: Context, message: String, duration: Int = Toast.LENGTH_SHORT) {
// 确保在主线程中执行
if (Thread.currentThread() == Looper.getMainLooper().thread) {
showToast(context, message, duration)
} else {
mainHandler.post {
showToast(context, message, duration)
}
}
}
private fun showToast(context: Context, message: String, duration: Int) {
val inflater = LayoutInflater.from(context) val inflater = LayoutInflater.from(context)
val layout: View = inflater.inflate(R.layout.custom_toast, null) val layout: View = inflater.inflate(R.layout.custom_toast, null)
val textView = layout.findViewById<TextView>(R.id.tvMessage) val textView = layout.findViewById<TextView>(R.id.tvMessage)
@@ -22,7 +37,6 @@ object ToastUtil {
toast.setGravity(Gravity.CENTER, 0, 0) // 调整位置居中显示 toast.setGravity(Gravity.CENTER, 0, 0) // 调整位置居中显示
toast.setDuration(duration) toast.setDuration(duration)
toast.show() toast.show()
} }
} }
@@ -82,6 +82,10 @@ object WeightUtil {
} }
} }
fun removeWeightListener(weightKey: String){
weightFuncMap?.remove(weightKey)
}
fun addWeightListener( fun addWeightListener(
weightKey: String, weightKey: String,
getWeight: WeightCallback = { _, _, _ -> } getWeight: WeightCallback = { _, _, _ -> }
@@ -11,11 +11,13 @@ import android.util.TypedValue
import android.view.View import android.view.View
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.widget.EditText import android.widget.EditText
import android.widget.ImageView
import android.widget.Toast import android.widget.Toast
import androidx.core.app.ActivityOptionsCompat import androidx.core.app.ActivityOptionsCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.shuwei.dish.match.utils.GlideUtils
import com.shuwei.dish.match.utils.ToastUtil import com.shuwei.dish.match.utils.ToastUtil
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -181,3 +183,6 @@ fun Double.roundedDecimalPlace(num: Int): Double {
fun Double.roundedOneDecimalPlace(): Double { fun Double.roundedOneDecimalPlace(): Double {
return this.roundedDecimalPlace(1) return this.roundedDecimalPlace(1)
} }
fun ImageView.load(url: Any?) {
GlideUtils.loadImage(context, url, this)
}
@@ -62,7 +62,7 @@
android:layout_marginStart="30dp" android:layout_marginStart="30dp"
android:layout_marginTop="40dp" android:layout_marginTop="40dp"
android:layout_marginBottom="40dp" android:layout_marginBottom="40dp"
android:text="@string/dish_composition" android:text="@string/dish_list"
android:textColor="@color/black666" android:textColor="@color/black666"
android:textSize="28sp" /> android:textSize="28sp" />
@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:background="@drawable/bg_other_page"
tools:ignore="HardcodedText">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:background="@drawable/shape_white_30_corners"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="106dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:background="@drawable/bg_bottom_line">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:text="菜品模式设置"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="28sp" />
<TextView
android:id="@+id/tvSetting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:text="配置终端默认模式"
android:textColor="@color/gray_b4"
android:textSize="28sp" />
</FrameLayout>
<LinearLayout
android:id="@+id/modeRadioGroup"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RadioButton
android:id="@+id/rbModeCook"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:button="@null"
android:drawableEnd="@drawable/mode_select"
android:background="@drawable/bg_bottom_line"
android:textSize="36sp"
tools:text="制作模式" />
<RadioButton
android:id="@+id/rbModeSampling"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:button="@null"
android:drawableEnd="@drawable/mode_select"
android:background="@drawable/bg_bottom_line"
android:textSize="36sp"
tools:text="采样模式" />
<RadioButton
android:id="@+id/rbModeQuality"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:button="@null"
android:drawableEnd="@drawable/ic_dish_disable"
android:enabled="false"
android:textColor="@color/gray_b4"
android:textSize="36sp"
tools:text="品控模式" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginBottom="60dp"
android:background="@drawable/shape_white_30_corners"
android:orientation="vertical"
android:gravity="center_vertical"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:text="@string/seasoning_setting"
android:textColor="@color/black666"
android:textSize="28sp" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="end"
android:text="@string/seasoning_setting2"
android:textColor="@color/gray_b4"
android:textSize="28sp" />
</LinearLayout>
<include
android:id="@+id/include"
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="@layout/layout_grid"/>
</LinearLayout>
</LinearLayout>
+1 -1
View File
@@ -22,7 +22,7 @@
<string name="food_remind_02">是否按当前食材制作或调整食材后再制作</string> <string name="food_remind_02">是否按当前食材制作或调整食材后再制作</string>
<string name="seasoning">调料</string> <string name="seasoning">调料</string>
<string name="seasoning_setting">调料设置</string> <string name="seasoning_setting">调料设置</string>
<string name="seasoning_setting2">点击分格配置分配调料</string> <string name="seasoning_setting2">点击分格配置调料</string>
<string name="input_seasoning_name">输入调料名称</string> <string name="input_seasoning_name">输入调料名称</string>
<string name="rb_sampling_cooking">烹饪中</string> <string name="rb_sampling_cooking">烹饪中</string>
<string name="rb_sampling_finished">已采样</string> <string name="rb_sampling_finished">已采样</string>
+37 -3
View File
@@ -1,5 +1,39 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { //plugins {
alias(libs.plugins.android.application) apply false // alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false // alias(libs.plugins.kotlin.android) apply false
//}
buildscript {
dependencies {
classpath(libs.gradle)
classpath(libs.kotlin.gradle.plugin)
classpath(libs.com.google.devtools.ksp.gradle.plugin)
classpath(libs.objectbox.gradle.plugin)
}
repositories {
maven { url = uri("https://maven.aliyun.com/repository/public/") }
maven { url = uri("https://maven.aliyun.com/repository/central") }
maven { url = uri("https://maven.aliyun.com/repository/google") }
maven { url = uri("https://maven.aliyun.com/repository/jcenter") }
maven { url = uri("https://jitpack.io") }
google()
mavenCentral()
}
}
allprojects {
repositories {
maven { url = uri("https://maven.aliyun.com/repository/public/") }
maven { url = uri("https://maven.aliyun.com/repository/central") }
maven { url = uri("https://maven.aliyun.com/repository/google") }
maven { url = uri("https://maven.aliyun.com/repository/jcenter") }
maven { url = uri("https://jitpack.io") }
google()
mavenCentral()
}
}
tasks.wrapper {
distributionType = Wrapper.DistributionType.ALL
} }
+53
View File
@@ -1,28 +1,81 @@
[versions] [versions]
activityKtx = "1.9.0"
agp = "8.11.1" agp = "8.11.1"
baserecyclerviewadapterhelper4 = "4.1.7" baserecyclerviewadapterhelper4 = "4.1.7"
baserecyclerviewadapterhelper4Version = "4.1.2"
comGoogleDevtoolsKspGradlePlugin = "2.0.21-1.0.27"
converterGson = "2.9.0"
glide = "4.12.0"
compiler = "4.12.0"
gradle = "8.10.1"
gson = "2.10.1"
kotlin = "2.0.21" kotlin = "2.0.21"
coreKtx = "1.10.1" coreKtx = "1.10.1"
junit = "4.13.2" junit = "4.13.2"
junitVersion = "1.1.5" junitVersion = "1.1.5"
espressoCore = "3.5.1" espressoCore = "3.5.1"
appcompat = "1.6.1" appcompat = "1.6.1"
kotlinGradlePlugin = "2.0.21"
lifecycleRuntimeKtx = "2.8.7"
lifecycleViewmodelKtx = "2.8.7"
loggingInterceptor = "4.9.1"
material = "1.10.0" material = "1.10.0"
gridlayout = "1.1.0" gridlayout = "1.1.0"
core = "3.4.1" core = "3.4.1"
androidCore = "3.3.0" androidCore = "3.3.0"
objectboxVersion = "5.3.0"
pytorch="1.13.0"
cameraCore = "1.4.1"
refreshLayoutKernel = "3.0.0-alpha"
refreshHeaderClassics = "3.0.0-alpha"
refreshHeaderRadar = "3.0.0-alpha"
roomRuntime = "2.5.2"
[libraries] [libraries]
android-core = { module = "com.google.zxing:android-core", version.ref = "androidCore" } android-core = { module = "com.google.zxing:android-core", version.ref = "androidCore" }
androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityKtx" }
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomRuntime" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomRuntime" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
baserecyclerviewadapterhelper4 = { module = "io.github.cymchad:BaseRecyclerViewAdapterHelper4", version.ref = "baserecyclerviewadapterhelper4Version" }
com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "comGoogleDevtoolsKspGradlePlugin" }
compiler = { module = "com.github.bumptech.glide:compiler", version.ref = "compiler" }
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" }
core = { module = "com.google.zxing:core", version.ref = "core" } core = { module = "com.google.zxing:core", version.ref = "core" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
gradle = { module = "com.android.tools.build:gradle", version.ref = "gradle" }
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
junit = { group = "junit", name = "junit", version.ref = "junit" } junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlinGradlePlugin" }
logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "loggingInterceptor" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" } material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", version.ref = "gridlayout" } androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", version.ref = "gridlayout" }
objectbox-gradle-plugin = { module = "io.objectbox:objectbox-gradle-plugin", version.ref = "objectboxVersion" }
objectbox-android-objectbrowser = { module = "io.objectbox:objectbox-android-objectbrowser", version.ref = "objectboxVersion" }
objectbox-android = { module = "io.objectbox:objectbox-android", version.ref = "objectboxVersion" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "loggingInterceptor" }
#noinspection Aligned16KB
pytorch-android={ group = "org.pytorch", name = "pytorch_android", version.ref = "pytorch" }
pytorch-android-torchvision={ group = "org.pytorch", name = "pytorch_android_torchvision", version.ref = "pytorch" }
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "cameraCore" }
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "cameraCore" }
androidx-camera-extensions = { module = "androidx.camera:camera-extensions", version.ref = "cameraCore" }
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraCore" }
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "cameraCore" }
refresh-footer-classics = { module = "io.github.scwang90:refresh-footer-classics", version.ref = "refreshLayoutKernel" }
refresh-header-radar = { module = "io.github.scwang90:refresh-header-radar", version.ref = "refreshHeaderRadar" }
refresh-header-classics = { module = "io.github.scwang90:refresh-header-classics", version.ref = "refreshHeaderClassics" }
refresh-layout-kernel = { module = "io.github.scwang90:refresh-layout-kernel", version.ref = "refreshLayoutKernel" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "converterGson" }
[plugins] [plugins]
android-application = { id = "com.android.application", version.ref = "agp" } android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+2 -1
View File
@@ -1,6 +1,7 @@
#Thu Jul 17 15:32:57 CST 2025 #Thu Jul 17 15:32:57 CST 2025
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip #distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
distributionUrl=https\://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.11.1-all.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
+23 -23
View File
@@ -1,26 +1,26 @@
pluginManagement { //pluginManagement {
repositories { // repositories {
google { // google {
content { // content {
includeGroupByRegex("com\\.android.*") // includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*") // includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*") // includeGroupByRegex("androidx.*")
} // }
} // }
mavenCentral() // mavenCentral()
gradlePluginPortal() // gradlePluginPortal()
maven { url = uri("https://jitpack.io") } // maven { url = uri("https://jitpack.io") }
} // }
} //}
dependencyResolutionManagement { //dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) // repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories { // repositories {
google() // google()
mavenCentral() // mavenCentral()
maven { url = uri("https://maven.aliyun.com/repository/public") } // maven { url = uri("https://maven.aliyun.com/repository/public") }
maven { url = uri("https://jitpack.io") } // maven { url = uri("https://jitpack.io") }
} // }
} //}
rootProject.name = "DishMatch" rootProject.name = "DishMatch"
include(":app") include(":app")