优化性能

This commit is contained in:
BBIT-Kai
2026-05-29 13:42:47 +08:00
parent f91251adc6
commit d0aa93cd9d
12 changed files with 333 additions and 330 deletions
@@ -204,6 +204,7 @@ fun MyTable(
ratio: List<Float>, ratio: List<Float>,
items: List<List<Any>>, items: List<List<Any>>,
verticalPadding: Dp = 5.dp, verticalPadding: Dp = 5.dp,
itemKey: ((List<Any>, Int) -> Any)? = null,
) { ) {
Column(modifier = modifier) { Column(modifier = modifier) {
TableHeadLine( TableHeadLine(
@@ -211,7 +212,13 @@ fun MyTable(
list = headerStrings.zip(ratio.map { it.toInt() }) list = headerStrings.zip(ratio.map { it.toInt() })
) )
LazyColumn { LazyColumn {
items(count = items.size) { itIndex -> items(
count = items.size,
key = { index ->
itemKey?.invoke(items[index], index)
?: items[index].joinToString(separator = "|") { it.toString() } + "#$index"
}
) { itIndex ->
TableContent( TableContent(
verticalPadding = verticalPadding, verticalPadding = verticalPadding,
modifier = M modifier = M
@@ -317,6 +324,7 @@ fun <T : Any> MyAnyTable(
// 每行 // 每行
info: List<T>, info: List<T>,
itemKey: ((T) -> Any)? = null,
onLongClick: (T) -> Unit = {}, onLongClick: (T) -> Unit = {},
onClick: (T) -> Unit = {}, onClick: (T) -> Unit = {},
@@ -330,7 +338,10 @@ fun <T : Any> MyAnyTable(
) )
var selectIndex by rememberSaveable { mutableStateOf(-1) } var selectIndex by rememberSaveable { mutableStateOf(-1) }
LazyColumn { LazyColumn {
items(count = info.size) { index -> items(
count = info.size,
key = { index -> itemKey?.invoke(info[index]) ?: "${info[index].hashCode()}-$index" }
) { index ->
// 每行 // 每行
val lineItem = info[index] val lineItem = info[index]
Card( Card(
@@ -418,6 +429,7 @@ fun <T : Any> MyTable2(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
infos: List<T>, infos: List<T>,
items: List<MyTableData<T>>, items: List<MyTableData<T>>,
itemKey: ((T) -> Any)? = null,
onLongClick: (T) -> Unit = {}, onLongClick: (T) -> Unit = {},
onClick: (T) -> Unit = {}, onClick: (T) -> Unit = {},
onExpend: @Composable (T) -> Unit = {}, onExpend: @Composable (T) -> Unit = {},
@@ -433,7 +445,10 @@ fun <T : Any> MyTable2(
var selectIndex by rememberSaveable { mutableStateOf(-1) } var selectIndex by rememberSaveable { mutableStateOf(-1) }
LazyColumn { LazyColumn {
items(count = infos.size) { index -> items(
count = infos.size,
key = { index -> itemKey?.invoke(infos[index]) ?: "${infos[index].hashCode()}-$index" }
) { index ->
val lineItem = infos[index] val lineItem = infos[index]
Card( Card(
@@ -172,15 +172,9 @@ fun MyButton(
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
Button( Button(
onClick = { onClick = onClick,
if (enabled) {
onClick()
} else {
Toasty.showToast("正在开发中,敬请期待")
}
},
modifier = modifier, modifier = modifier,
enabled = true, enabled = enabled,
interactionSource = interactionSource, interactionSource = interactionSource,
shape = shape, shape = shape,
border = border, border = border,
@@ -2,6 +2,8 @@
package com.bbitcn.f8.pad.receiver package com.bbitcn.f8.pad.receiver
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@@ -35,10 +37,15 @@ class SystemInfoReceiver(private val context: Context) {
private val _signalStrength = MutableStateFlow(0) private val _signalStrength = MutableStateFlow(0)
val signalStrength = _signalStrength.asStateFlow() val signalStrength = _signalStrength.asStateFlow()
private val _bluetoothEnabled = MutableStateFlow(false)
val bluetoothEnabled = _bluetoothEnabled.asStateFlow()
private val connectivityManager = private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val telephonyManager = private val telephonyManager =
context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
private val bluetoothManager =
context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
/** /**
* 信号强度监听器 * 信号强度监听器
@@ -78,6 +85,12 @@ class SystemInfoReceiver(private val context: Context) {
} }
} }
private val bluetoothReceiver = object : BroadcastReceiver() {
override fun onReceive(ctx: Context?, intent: Intent?) {
refreshBluetoothStatus()
}
}
fun register() { fun register() {
val batteryIntentFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED) val batteryIntentFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
@@ -85,10 +98,15 @@ class SystemInfoReceiver(private val context: Context) {
batteryReceiver, batteryReceiver,
batteryIntentFilter batteryIntentFilter
) )
context.registerReceiverCompat(
bluetoothReceiver,
IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
)
connectivityManager.registerDefaultNetworkCallback(networkCallback) connectivityManager.registerDefaultNetworkCallback(networkCallback)
registerSignalStrengthListener() registerSignalStrengthListener()
refreshNetworkStatus() refreshNetworkStatus()
refreshBluetoothStatus()
// 开始轮询网络状态 防止状态假死 // 开始轮询网络状态 防止状态假死
PollingTask.getInstance("SystemInfoReceiver").startPollingTaskOnIOThread("NetworkStatusPolling",30_000) { PollingTask.getInstance("SystemInfoReceiver").startPollingTaskOnIOThread("NetworkStatusPolling",30_000) {
refreshNetworkStatus() refreshNetworkStatus()
@@ -97,6 +115,11 @@ class SystemInfoReceiver(private val context: Context) {
fun unregister() { fun unregister() {
context.unregisterReceiver(batteryReceiver) context.unregisterReceiver(batteryReceiver)
runCatching {
context.unregisterReceiver(bluetoothReceiver)
}.onFailure {
MyLog.appError("取消蓝牙监听失败:${it.message}")
}
runCatching { runCatching {
connectivityManager.unregisterNetworkCallback(networkCallback) connectivityManager.unregisterNetworkCallback(networkCallback)
}.onFailure { }.onFailure {
@@ -159,6 +182,12 @@ class SystemInfoReceiver(private val context: Context) {
} }
} }
private fun refreshBluetoothStatus() {
_bluetoothEnabled.value = runCatching {
bluetoothManager.adapter?.isEnabled == true
}.getOrDefault(false)
}
private fun registerSignalStrengthListener() { private fun registerSignalStrengthListener() {
runCatching { runCatching {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@@ -181,7 +181,7 @@ fun TabPagerScreen(
} }
HorizontalPager( HorizontalPager(
state = pagerState, state = pagerState,
beyondViewportPageCount = tabs.size, beyondViewportPageCount = 1,
modifier = M modifier = M
.fillMaxWidth() .fillMaxWidth()
.weight(1f) .weight(1f)
@@ -19,14 +19,13 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.geometry.Rect import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.bbitcn.f8.pad.M import com.bbitcn.f8.pad.M
@@ -48,7 +47,6 @@ import com.bbitcn.f8.pad.ui.screen.mainFunc.UserScreen
import com.bbitcn.f8.pad.ui.screen.view.Toasty import com.bbitcn.f8.pad.ui.screen.view.Toasty
import com.bbitcn.f8.pad.ui.viewmodel.UpdateViewModel import com.bbitcn.f8.pad.ui.viewmodel.UpdateViewModel
import com.cyberecho.ui.screen.ChatDialog import com.cyberecho.ui.screen.ChatDialog
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Preview(showBackground = true, widthDp = 1280) @Preview(showBackground = true, widthDp = 1280)
@@ -75,41 +73,13 @@ fun MainScreen(
} }
Box(modifier = M.fillMaxWidth(), contentAlignment = Alignment.BottomStart) { Box(modifier = M.fillMaxWidth(), contentAlignment = Alignment.BottomStart) {
var selectedPage by rememberSaveable { mutableStateOf(0) } var selectedPage by rememberSaveable { mutableStateOf(0) }
var contentPage by rememberSaveable { mutableStateOf(0) } val pageStateHolder = rememberSaveableStateHolder()
var isSwitchingPage by remember { mutableStateOf(false) }
val cachedPages = remember { mutableStateListOf<Int>() }
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val menu by mainViewModel.menu.collectAsState() val menu by mainViewModel.menu.collectAsState()
LaunchedEffect(menu, selectedPage) { LaunchedEffect(menu) {
if (menu.isEmpty()) { if (menu.isNotEmpty() && selectedPage !in menu.indices) {
contentPage = 0 selectedPage = selectedPage.coerceIn(0, menu.lastIndex)
isSwitchingPage = false
cachedPages.clear()
return@LaunchedEffect
}
val safeSelectedPage = selectedPage.coerceIn(0, menu.lastIndex)
if (safeSelectedPage != selectedPage) {
selectedPage = safeSelectedPage
return@LaunchedEffect
}
cachedPages.removeAll { it !in menu.indices }
if (cachedPages.isEmpty()) {
cachedPages.add(safeSelectedPage)
}
if (contentPage != safeSelectedPage && safeSelectedPage !in cachedPages) {
isSwitchingPage = true
withFrameNanos { }
delay(180)
cachedPages.add(safeSelectedPage)
contentPage = safeSelectedPage
isSwitchingPage = false
} else if (contentPage != safeSelectedPage) {
contentPage = safeSelectedPage
isSwitchingPage = false
} }
} }
Row(modifier = M.fillMaxWidth()) { Row(modifier = M.fillMaxWidth()) {
@@ -137,24 +107,14 @@ fun MainScreen(
onClick = { onClick = {
if (selectedPage != index) { if (selectedPage != index) {
selectedPage = index selectedPage = index
isSwitchingPage = index !in cachedPages
if (index in cachedPages) {
contentPage = index
}
} }
} }
) )
} }
} }
Box(modifier = M.weight(1f).fillMaxSize()) { Box(modifier = M.weight(1f).fillMaxSize()) {
val selectedMenu = menu.getOrNull(selectedPage) val pageIndex = menu.getOrNull(selectedPage)?.index ?: -1
if (isSwitchingPage && selectedMenu != null && selectedPage !in cachedPages) { pageStateHolder.SaveableStateProvider(pageIndex) {
MainPageLoading(selectedMenu.title)
} else {
cachedPages.forEach { page ->
key(page) {
val pageIndex = menu.getOrNull(page)?.index ?: -1
MainPageHost(visible = page == contentPage) {
MainPageContent( MainPageContent(
index = pageIndex, index = pageIndex,
navController = navController, navController = navController,
@@ -166,9 +126,6 @@ fun MainScreen(
} }
} }
} }
}
}
}
Column( Column(
modifier = M modifier = M
.width(70.dp) .width(70.dp)
@@ -246,39 +203,6 @@ fun MainScreen(
ChatDialog(chatDialogData) ChatDialog(chatDialogData)
} }
@Composable
private fun MainPageLoading(title: String) {
Box(modifier = M.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(
text = "正在加载$title...",
color = MyColors.Gray,
fontSize = MaterialTheme.typography.bodyLarge.fontSize
)
}
}
@Composable
private fun MainPageHost(
visible: Boolean,
content: @Composable () -> Unit
) {
Box(
modifier = if (visible) {
M
.fillMaxSize()
.alpha(1f)
.zIndex(1f)
} else {
M
.size(0.dp)
.alpha(0f)
.zIndex(0f)
}
) {
content()
}
}
@Composable @Composable
private fun MainPageContent( private fun MainPageContent(
index: Int, index: Int,
@@ -43,7 +43,6 @@ import androidx.navigation.compose.rememberNavController
import com.bbitcn.f8.pad.M import com.bbitcn.f8.pad.M
import com.bbitcn.f8.pad.R import com.bbitcn.f8.pad.R
import com.bbitcn.f8.pad.base.WhiteText import com.bbitcn.f8.pad.base.WhiteText
import com.bbitcn.f8.pad.base.isBluetoothEnabled
import com.bbitcn.f8.pad.receiver.SystemInfoReceiver import com.bbitcn.f8.pad.receiver.SystemInfoReceiver
import com.bbitcn.f8.pad.ui.screen.view.drawer.DrawerViewModel import com.bbitcn.f8.pad.ui.screen.view.drawer.DrawerViewModel
import com.bbitcn.f8.pad.ui.theme.MyColors import com.bbitcn.f8.pad.ui.theme.MyColors
@@ -81,8 +80,6 @@ fun MyTopBar(
) { ) {
val context = LocalContext.current val context = LocalContext.current
val systemInfoReceiver = remember { SystemInfoReceiver(context) } val systemInfoReceiver = remember { SystemInfoReceiver(context) }
val date by topInfoViewModel.date.collectAsState()
val time by topInfoViewModel.time.collectAsState()
val logoState by topInfoViewModel.logoState.collectAsState() val logoState by topInfoViewModel.logoState.collectAsState()
val versionName = remember { MyUtil.getVersionName() } val versionName = remember { MyUtil.getVersionName() }
@@ -98,9 +95,33 @@ fun MyTopBar(
.height(45.dp) .height(45.dp)
.background(color = MyColors.Black), .background(color = MyColors.Black),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) {
TopBarLogoTitle(
logoState = logoState,
versionName = versionName,
navController = navController,
topInfoViewModel = topInfoViewModel
)
Spacer(modifier = M.weight(1f))
if (curPageName != "login") {
TopBarStatusArea(
drawerViewModel = drawerViewModel,
topInfoViewModel = topInfoViewModel,
systemInfoReceiver = systemInfoReceiver
)
}
}
}
@Composable
private fun TopBarLogoTitle(
logoState: Pair<Pair<Int, String>, Int>,
versionName: String,
navController: NavController,
topInfoViewModel: TopInfoViewModel
) { ) {
AnimatedContent( AnimatedContent(
logoState, targetState = logoState,
transitionSpec = { transitionSpec = {
EnterTransition.None togetherWith ExitTransition.None EnterTransition.None togetherWith ExitTransition.None
}, },
@@ -109,13 +130,11 @@ fun MyTopBar(
indication = null indication = null
) { ) {
if (logoState.first.first != R.drawable.logo_white) { if (logoState.first.first != R.drawable.logo_white) {
// 当前页面
// val curPage = navController.currentDestination?.route ?: "main"
// Toasty.setCurPage(curPage)
topInfoViewModel.toScreen() topInfoViewModel.toScreen()
navController.popBackStack() navController.popBackStack()
} }
}, },
label = "topBarLogo"
) { ) {
Image( Image(
modifier = M modifier = M
@@ -129,7 +148,8 @@ fun MyTopBar(
targetState = logoState, targetState = logoState,
transitionSpec = { transitionSpec = {
EnterTransition.None togetherWith ExitTransition.None EnterTransition.None togetherWith ExitTransition.None
}, label = "animated content" },
label = "topBarTitle"
) { value -> ) { value ->
Row(verticalAlignment = Alignment.Bottom) { Row(verticalAlignment = Alignment.Bottom) {
Text( Text(
@@ -146,25 +166,19 @@ fun MyTopBar(
fontSize = MaterialTheme.typography.bodySmall.fontSize fontSize = MaterialTheme.typography.bodySmall.fontSize
) )
} }
} }
Spacer(modifier = M.weight(1f)) }
if (curPageName != "login") {
@Composable
private fun TopBarStatusArea(
drawerViewModel: DrawerViewModel,
topInfoViewModel: TopInfoViewModel,
systemInfoReceiver: SystemInfoReceiver
) {
Row( Row(
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
val padding = M.padding(horizontal = 5.dp)
// Image(
// modifier = M
// .clickable{
// topInfoViewModel.getFrpNewVersion()
// }
// .padding(end = 5.dp)
// .size(25.dp),
// painter = painterResource(id = R.drawable.icon_sos),
// contentDescription = "frp",
// )
Image( Image(
modifier = M modifier = M
.padding(end = 5.dp) .padding(end = 5.dp)
@@ -172,95 +186,81 @@ fun MyTopBar(
painter = painterResource(id = R.drawable.icon_lock), painter = painterResource(id = R.drawable.icon_lock),
contentDescription = "screen_lock", contentDescription = "screen_lock",
) )
DeviceStatusCluster(
drawerViewModel = drawerViewModel,
topInfoViewModel = topInfoViewModel,
systemInfoReceiver = systemInfoReceiver
)
TopBarClock(topInfoViewModel)
}
}
@Composable
private fun DeviceStatusCluster(
drawerViewModel: DrawerViewModel,
topInfoViewModel: TopInfoViewModel,
systemInfoReceiver: SystemInfoReceiver
) {
Row( Row(
modifier = M.clickable { drawerViewModel.openSetDrawer() }, modifier = M.clickable { drawerViewModel.openSetDrawer() },
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
if (isBluetoothEnabled()) { val bluetoothEnabled by systemInfoReceiver.bluetoothEnabled.collectAsState()
Image( if (bluetoothEnabled) {
modifier = M TopBarIcon(R.drawable.bluetooth, "蓝牙")
.padding(end = 5.dp)
.size(25.dp),
painter = painterResource(id = R.drawable.bluetooth),
contentDescription = "蓝牙",
)
} }
val printer1 by PrinterBT.state.collectAsState() val printer1 by PrinterBT.state.collectAsState()
val printer2 by JTPrinterUSB.state.collectAsState() val printer2 by JTPrinterUSB.state.collectAsState()
val printerState = if (printer1 == 1 || printer2 == 1) 1 else 0 val printerState = if (printer1 == 1 || printer2 == 1) 1 else 0
Image( TopBarIcon(
modifier = M icon = if (printerState == 1) R.drawable.print_on else R.drawable.print_off,
.padding(end = 5.dp) contentDescription = "打印机"
.size(25.dp),
painter = painterResource(id = if (printerState == 1) R.drawable.print_on else R.drawable.print_off),
contentDescription = "打印机",
) )
val water by WaterCutMeterBT.state.collectAsState() val water by WaterCutMeterBT.state.collectAsState()
Image( TopBarIcon(
modifier = M icon = if (water == 1) R.drawable.water_on else R.drawable.water_off,
.padding(end = 5.dp) contentDescription = "含水仪"
.size(25.dp),
painter = painterResource(id = if (water == 1) R.drawable.water_on else R.drawable.water_off),
contentDescription = "含水仪",
) )
val scale1 by ScaleBT.state.collectAsState() val scale1 by ScaleBT.state.collectAsState()
val scale2 by ScaleSerial.state.collectAsState() val scale2 by ScaleSerial.state.collectAsState()
val scaleState = if (scale1 == 1 || scale2 == 1) 1 else 0 val scaleState = if (scale1 == 1 || scale2 == 1) 1 else 0
Image( TopBarIcon(
modifier = M icon = if (scaleState == 1) R.drawable.scale_on else R.drawable.scale_off,
.padding(end = 5.dp) contentDescription = "电子秤"
.size(25.dp),
painter = painterResource(id = if (scaleState == 1) R.drawable.scale_on else R.drawable.scale_off),
contentDescription = "电子秤",
) )
//分隔符
VerticalDivider( VerticalDivider(
modifier = padding modifier = M
.padding(horizontal = 5.dp)
.width(1.dp), .width(1.dp),
color = MyColors.White color = MyColors.White
) )
// 电量显示
val batteryVisible by topInfoViewModel.batteryVisible.collectAsState() val batteryVisible by topInfoViewModel.batteryVisible.collectAsState()
if (batteryVisible) { if (batteryVisible) {
val batteryLevel by systemInfoReceiver.batteryLevel.collectAsState() val batteryLevel by systemInfoReceiver.batteryLevel.collectAsState()
BatteryLevelBoxWithImage(batteryLevel) BatteryLevelBoxWithImage(batteryLevel)
} }
val signalStrength by systemInfoReceiver.signalStrength.collectAsState() val signalStrength by systemInfoReceiver.signalStrength.collectAsState()
val networkType by systemInfoReceiver.networkType.collectAsState() val networkType by systemInfoReceiver.networkType.collectAsState()
Image( TopBarIcon(
modifier = M icon = networkIconResource(networkType, signalStrength),
.padding(end = 10.dp)
.size(25.dp),
painter = painterResource(
id =
if (networkType == "WIFI") {
when (signalStrength) {
0 -> R.drawable.server_0
1 -> R.drawable.wifi_2
2 -> R.drawable.wifi_2
3 -> R.drawable.wifi_3
4 -> R.drawable.wifi_4
else -> R.drawable.server_0
}
} else if (networkType == "Cellular") {
when (signalStrength) {
0 -> R.drawable.server_0
1 -> R.drawable._4g_1
2 -> R.drawable._4g_2
3 -> R.drawable._4g_3
4 -> R.drawable._4g_4
else -> R.drawable._4g_0
}
} else if (networkType == "Ethernet") {
R.drawable.rj45
} else {
R.drawable.server_0
}
),
contentDescription = "信号", contentDescription = "信号",
endPadding = 10
) )
} }
}
@Composable
private fun TopBarClock(topInfoViewModel: TopInfoViewModel) {
val date by topInfoViewModel.date.collectAsState()
val time by topInfoViewModel.time.collectAsState()
WhiteText( WhiteText(
text = date, text = date,
fontSize = 15.sp, fontSize = 15.sp,
@@ -272,7 +272,44 @@ fun MyTopBar(
fontSize = 30.sp fontSize = 30.sp
) )
} }
@Composable
private fun TopBarIcon(
icon: Int,
contentDescription: String,
endPadding: Int = 5
) {
Image(
modifier = M
.padding(end = endPadding.dp)
.size(25.dp),
painter = painterResource(id = icon),
contentDescription = contentDescription,
)
} }
private fun networkIconResource(networkType: String, signalStrength: Int): Int {
return when (networkType) {
"WIFI" -> when (signalStrength) {
0 -> R.drawable.server_0
1 -> R.drawable.wifi_2
2 -> R.drawable.wifi_2
3 -> R.drawable.wifi_3
4 -> R.drawable.wifi_4
else -> R.drawable.server_0
}
"Cellular" -> when (signalStrength) {
0 -> R.drawable.server_0
1 -> R.drawable._4g_1
2 -> R.drawable._4g_2
3 -> R.drawable._4g_3
4 -> R.drawable._4g_4
else -> R.drawable._4g_0
}
"Ethernet" -> R.drawable.rj45
else -> R.drawable.server_0
} }
} }
@@ -300,7 +337,7 @@ fun BatteryLevelBoxWithImage(batteryLevel: Int) {
) { ) {
val fillWidth = size.width * batteryLevel / 100 val fillWidth = size.width * batteryLevel / 100
drawRect( drawRect(
color = if (batteryLevel > 0.2f) MyColors.Green else MyColors.Red, // 低电量红色 color = if (batteryLevel > 20) MyColors.Green else MyColors.Red, // 低电量红色
topLeft = Offset(0f, 0f), // 从左上角开始填充 topLeft = Offset(0f, 0f), // 从左上角开始填充
size = Size(fillWidth, size.height) // 宽度根据电量动态变化 size = Size(fillWidth, size.height) // 宽度根据电量动态变化
) )
@@ -24,7 +24,7 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@@ -203,14 +203,17 @@ fun Messages(
modifier = M modifier = M
.fillMaxSize() .fillMaxSize()
) { ) {
items(chatRecords) { itemsIndexed(
items = chatRecords,
key = { index, message -> "${message.timestamp}-${message.isFromUser}-$index" }
) { index, it ->
Message( Message(
modifier = M, modifier = M,
msg = it, msg = it,
isEndMessageByAuthor = true, isEndMessageByAuthor = true,
isNewMessageByAuthor = true isNewMessageByAuthor = true
) )
if (chatRecords.indexOf(it) == chatRecords.size - 1) { if (index == chatRecords.lastIndex) {
DateHeader(System.currentTimeMillis()) DateHeader(System.currentTimeMillis())
} }
} }
@@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@@ -137,7 +138,7 @@ fun HomeScreenInLandscape(
.weight(1f) .weight(1f)
.fillMaxWidth() .fillMaxWidth()
) { ) {
ShortCut(homeViewModel) ShortCut(navController, homeViewModel)
} }
} }
Column( Column(
@@ -227,7 +228,7 @@ fun HomeScreenInPortrait(
.weight(0.5f) .weight(0.5f)
.fillMaxWidth() .fillMaxWidth()
) { ) {
ShortCut(homeViewModel) ShortCut(navController, homeViewModel)
} }
} }
} }
@@ -358,8 +359,10 @@ fun WeatherInfo(homeViewModel: HomeViewModel) {
}) })
} }
LazyRow { LazyRow {
items(weatherInfo.casts) { itemsIndexed(
val index = weatherInfo.casts.indexOf(it) items = weatherInfo.casts,
key = { index, item -> item.date.ifEmpty { "weather-$index" } }
) { index, it ->
WeatherItem( WeatherItem(
it.weekstr, it.weekstr,
it.date, it.date,
@@ -430,8 +433,10 @@ fun MessageInfo(homeViewModel: HomeViewModel) {
}) })
} }
LazyColumn { LazyColumn {
items(count = notices.size) { index -> items(
val notice = notices[index] items = notices,
key = { it.id }
) { notice ->
MessageItem( MessageItem(
homeViewModel, homeViewModel,
true, true,
@@ -503,7 +508,7 @@ fun MessageItem(
} }
@Composable @Composable
fun ShortCut(homeViewModel: HomeViewModel) { fun ShortCut(navController: NavController, homeViewModel: HomeViewModel) {
Row(modifier = M.fillMaxHeight(), verticalAlignment = Alignment.CenterVertically) { Row(modifier = M.fillMaxHeight(), verticalAlignment = Alignment.CenterVertically) {
Box( Box(
modifier = M modifier = M
@@ -527,12 +532,10 @@ fun ShortCut(homeViewModel: HomeViewModel) {
) )
} }
LazyRow(verticalAlignment = Alignment.CenterVertically) { LazyRow(verticalAlignment = Alignment.CenterVertically) {
item { item(key = "addUser") {
// ShowCutItem(R.drawable.user_add, "新增用户", onClick = {}) ShowCutItem(R.drawable.user_add, "新增农户") {
// ShowCutItem(R.drawable.user_query, "用户查询", onClick = {}) navController.navigate("addUser")
// ShowCutItem(R.drawable.silk_add, "新增收茧", onClick = {}) }
// ShowCutItem(R.drawable.silk_trans, "茧转移", onClick = {})
// ShowCutItem(R.drawable.device_link, "设备连接", onClick = {})
} }
} }
} }
@@ -12,7 +12,7 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@@ -111,8 +111,10 @@ fun SettingWeather(
InputFrame("本周天气预报") { InputFrame("本周天气预报") {
Column { Column {
LazyRow { LazyRow {
items(weatherInfo.casts) { itemsIndexed(
val index = weatherInfo.casts.indexOf(it) items = weatherInfo.casts,
key = { index, item -> item.date.ifEmpty { "weather-$index" } }
) { index, it ->
WeatherItem( WeatherItem(
it.weekstr, it.date, it.dayweatherpic, it.weekstr, it.date, it.dayweatherpic,
it.nighttemp + "~" + it.daytemp + "", index it.nighttemp + "~" + it.daytemp + "", index
@@ -1,53 +1,49 @@
package com.bbitcn.f8.pad.ui.theme package com.bbitcn.f8.pad.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.graphics.Color
private val DarkColorScheme = darkColorScheme( private val DarkColorScheme = darkColorScheme(
primary = Purple80, primary = MyColors.BlueGreen,
secondary = PurpleGrey80, onPrimary = MyColors.White,
tertiary = Pink80 primaryContainer = MyColors.LightBlueGreen,
secondary = MyColors.Green,
tertiary = MyColors.Orange,
background = MyColors.Black,
surface = Color(0xFF202625),
onBackground = MyColors.White,
onSurface = MyColors.White,
) )
private val LightColorScheme = lightColorScheme( private val LightColorScheme = lightColorScheme(
primary = Purple40, primary = MyColors.BlueGreen,
secondary = PurpleGrey40, onPrimary = MyColors.White,
tertiary = Pink40 primaryContainer = MyColors.LightBlueGreen,
secondary = MyColors.Green,
/* Other default colors to override tertiary = MyColors.Orange,
background = Color(0xFFFFFBFE), background = Color(0xFFF7FAFA),
surface = Color(0xFFFFFBFE), surface = MyColors.White,
onPrimary = Color.White, surfaceVariant = MyColors.LightBlue,
onSecondary = Color.White, onBackground = MyColors.Black,
onTertiary = Color.White, onSurface = MyColors.Black,
onBackground = Color(0xFF1C1B1F), outline = MyColors.Disabled,
onSurface = Color(0xFF1C1B1F),
*/
) )
@Composable @Composable
@Suppress("UNUSED_PARAMETER")
fun AppTheme( fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(), darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+ dynamicColor: Boolean = false,
dynamicColor: Boolean = true,
content: @Composable () -> Unit content: @Composable () -> Unit
) { ) {
val colorScheme = when { val colorScheme = if (darkTheme) {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { DarkColorScheme
val context = LocalContext.current } else {
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) LightColorScheme
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
} }
MaterialTheme( MaterialTheme(

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB