perf: some changes

This commit is contained in:
lisonge 2024-02-22 22:34:21 +08:00
parent d683296a7b
commit 3d10cfe45a
14 changed files with 700 additions and 675 deletions

View File

@ -182,8 +182,12 @@ dependencies {
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx)
implementation(libs.androidx.room.paging)
ksp(libs.androidx.room.compiler)
implementation(libs.androidx.paging.runtime)
implementation(libs.androidx.paging.compose)
implementation(libs.ktor.server.core)
implementation(libs.ktor.server.cio)
implementation(libs.ktor.server.content.negotiation)

View File

@ -1,6 +1,7 @@
package li.songe.gkd.data
import android.os.Parcelable
import androidx.paging.PagingSource
import androidx.room.ColumnInfo
import androidx.room.Dao
import androidx.room.Delete
@ -49,6 +50,9 @@ data class ClickLog(
@Query("SELECT * FROM click_log ORDER BY id DESC LIMIT 1000")
fun query(): Flow<List<ClickLog>>
@Query("SELECT * FROM click_log ORDER BY id DESC ")
fun pagingSource(): PagingSource<Int, ClickLog>
@Query("SELECT COUNT(*) FROM click_log")
fun count(): Flow<Int>

View File

@ -295,7 +295,6 @@ fun AppItemPage(
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
Text(text = "编辑禁用", modifier = Modifier
.clickable {
setExcludeGroupRaw(menuGroupRaw)
@ -345,7 +344,6 @@ fun AppItemPage(
}
}
}
}
if (editGroupRaw != null && appRawVal != null && subsItemVal != null) {
var source by remember {

View File

@ -181,7 +181,6 @@ fun CategoryPage(subsItemId: Long) {
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
enableGroupRadioOptions.forEach { option ->
val onClick: () -> Unit = {
vm.viewModelScope.launchTry(Dispatchers.IO) {
@ -216,7 +215,6 @@ fun CategoryPage(subsItemId: Long) {
}
}
}
}
val subsRawVal = subsRaw
if (editNameCategory != null && subsRawVal != null) {
@ -328,7 +326,6 @@ fun CategoryPage(subsItemId: Long) {
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
Text(text = "编辑", modifier = Modifier
.clickable {
setEditNameCategory(menuCategory)
@ -360,6 +357,5 @@ fun CategoryPage(subsItemId: Long) {
}
}
}
}
}

View File

@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
@ -33,15 +32,18 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey
import com.blankj.utilcode.util.LogUtils
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootNavGraph
import kotlinx.coroutines.Dispatchers
@ -75,8 +77,9 @@ fun ClickLogPage() {
val navController = LocalNavController.current
val vm = hiltViewModel<ClickLogVm>()
val clickDataList by vm.clickDataListFlow.collectAsState()
// val clickDataList by vm.clickDataListFlow.collectAsState()
val clickLogCount by vm.clickLogCountFlow.collectAsState()
val clickDataItems = vm.pagingDataFlow.collectAsLazyPagingItems()
val appInfoCache by appInfoCacheFlow.collectAsState()
val subsIdToRaw by subsIdToRawFlow.collectAsState()
@ -105,6 +108,10 @@ fun ClickLogPage() {
mutableStateOf(false)
}
LaunchedEffect(key1 = clickDataItems.itemSnapshotList.items, block = {
LogUtils.d(clickDataItems.itemSnapshotList.items.size)
})
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = {
TopAppBar(
@ -121,7 +128,7 @@ fun ClickLogPage() {
},
title = { Text(text = "触发记录" + if (clickLogCount <= 0) "" else ("-$clickLogCount")) },
actions = {
if (clickDataList.isNotEmpty()) {
if (clickLogCount > 0) {
IconButton(onClick = { showDeleteDlg = true }) {
Icon(
imageVector = Icons.Outlined.Delete,
@ -131,11 +138,14 @@ fun ClickLogPage() {
}
})
}, content = { contentPadding ->
if (clickDataList.isNotEmpty()) {
LazyColumn(
modifier = Modifier.padding(contentPadding),
) {
items(clickDataList, { it.t0.id }) { (clickLog, group, rule) ->
items(
count = clickDataItems.itemCount,
key = clickDataItems.itemKey { c -> c.t0.id }
) { i ->
val (clickLog, group, rule) = clickDataItems[i] ?: return@items
Column(modifier = Modifier
.clickable {
previewClickLog = clickLog
@ -184,18 +194,14 @@ fun ClickLogPage() {
HorizontalDivider()
}
item {
Spacer(modifier = Modifier.height(10.dp))
}
}
} else {
Column(
modifier = Modifier
.padding(contentPadding)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.height(40.dp))
Text(text = "暂无记录")
if (clickLogCount == 0) {
Text(
text = "暂无记录",
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center
)
}
}
}
})
@ -214,7 +220,6 @@ fun ClickLogPage() {
}
val appInfo = appInfoCache[clickLog.appId]
Column {
Text(text = "查看规则组", modifier = Modifier
.clickable {
clickLog.appId ?: return@clickable
@ -331,8 +336,6 @@ fun ClickLogPage() {
)
}
}
}
}
if (showDeleteDlg) {

View File

@ -2,6 +2,10 @@ package li.songe.gkd.ui
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.cachedIn
import androidx.paging.map
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
@ -15,9 +19,10 @@ import javax.inject.Inject
@HiltViewModel
class ClickLogVm @Inject constructor() : ViewModel() {
val clickDataListFlow =
combine(DbSet.clickLogDao.query(), subsIdToRawFlow) { clickLogs, subsIdToRaw ->
clickLogs.map { c ->
val pagingDataFlow = Pager(PagingConfig(pageSize = 100)) { DbSet.clickLogDao.pagingSource() }
.flow.cachedIn(viewModelScope)
.combine(subsIdToRawFlow) { pagingData, subsIdToRaw ->
pagingData.map { c ->
val group = if (c.groupType == SubsConfig.AppGroupType) {
val app = subsIdToRaw[c.subsId]?.apps?.find { a -> a.id == c.appId }
app?.groups?.find { g -> g.key == c.groupKey }
@ -33,7 +38,28 @@ class ClickLogVm @Inject constructor() : ViewModel() {
}
Tuple3(c, group, rule)
}
}.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
}
// val clickDataListFlow =
// combine(DbSet.clickLogDao.query(), subsIdToRawFlow) { clickLogs, subsIdToRaw ->
// clickLogs.map { c ->
// val group = if (c.groupType == SubsConfig.AppGroupType) {
// val app = subsIdToRaw[c.subsId]?.apps?.find { a -> a.id == c.appId }
// app?.groups?.find { g -> g.key == c.groupKey }
// } else {
// subsIdToRaw[c.subsId]?.globalGroups?.find { g -> g.key == c.groupKey }
// }
// val rule = group?.rules?.run {
// if (c.ruleKey != null) {
// find { r -> r.key == c.ruleKey }
// } else {
// getOrNull(c.ruleIndex)
// }
// }
// Tuple3(c, group, rule)
// }
// }.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
val clickLogCountFlow =
DbSet.clickLogDao.count().stateIn(viewModelScope, SharingStarted.Eagerly, 0)

View File

@ -122,7 +122,7 @@ fun GlobalRuleExcludePage(subsItemId: Long, groupKey: Int) {
AppBarTextField(
value = searchStr,
onValueChange = { newValue -> vm.searchStrFlow.value = newValue.trim() },
hint = "请输入应用名称",
hint = "请输入应用名称/ID",
modifier = Modifier.focusRequester(focusRequester)
)
} else {

View File

@ -272,7 +272,6 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
Text(text = "编辑禁用", modifier = Modifier
.clickable {
setMenuGroupRaw(null)
@ -319,7 +318,6 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
}
}
}
}
if (editGroupRaw != null && rawSubs != null) {
var source by remember {
mutableStateOf(json.encodeToJson5String(editGroupRaw))

View File

@ -37,11 +37,11 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
@ -123,7 +123,6 @@ fun SnapshotPage() {
}
})
}, content = { contentPadding ->
if (snapshots.isNotEmpty()) {
LazyColumn(
modifier = Modifier.padding(contentPadding),
) {
@ -166,20 +165,17 @@ fun SnapshotPage() {
HorizontalDivider()
}
item {
Spacer(modifier = Modifier.height(10.dp))
}
}
} else {
Column(
modifier = Modifier
.padding(contentPadding)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.height(40.dp))
Text(text = "暂无记录")
if (snapshots.isEmpty()) {
Text(
text = "暂无记录",
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center
)
}
}
}
})
selectedSnapshot?.let { snapshotVal ->
@ -190,7 +186,6 @@ fun SnapshotPage() {
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
val modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
@ -307,7 +302,6 @@ fun SnapshotPage() {
}
}
}
}
when (val uploadStatusVal = uploadStatus) {
is LoadStatus.Failure -> {

View File

@ -2,7 +2,6 @@ package li.songe.gkd.ui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
@ -50,6 +49,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
@ -145,7 +145,7 @@ fun SubsPage(
AppBarTextField(
value = searchStr,
onValueChange = { newValue -> vm.searchStrFlow.value = newValue.trim() },
hint = "请输入应用名称",
hint = "请输入应用名称/ID",
modifier = Modifier.focusRequester(focusRequester)
)
} else {
@ -265,26 +265,17 @@ fun SubsPage(
})
}
item {
if (appAndConfigs.isEmpty()) {
Spacer(modifier = Modifier.height(40.dp))
Column(
if (appAndConfigs.isEmpty()) {
Text(
text = if (searchStr.isNotEmpty()) "暂无搜索结果" else "暂无规则",
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
if (searchStr.isNotEmpty()) {
Text(text = "暂无搜索结果")
} else {
Text(text = "暂无规则")
textAlign = TextAlign.Center
)
}
}
}
}
item {
Spacer(modifier = Modifier.height(20.dp))
}
}
}
val subsItemVal = subsItem
@ -431,7 +422,6 @@ fun SubsPage(
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
Text(text = "复制", modifier = Modifier
.clickable {
ClipboardUtils.copyText(
@ -459,4 +449,3 @@ fun SubsPage(
}
}
}
}

View File

@ -48,6 +48,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
@ -106,7 +107,7 @@ fun useAppListPage(): ScaffoldExt {
AppBarTextField(
value = searchStr,
onValueChange = { newValue -> vm.searchStrFlow.value = newValue.trim() },
hint = "请输入应用名称",
hint = "请输入应用名称/ID",
modifier = Modifier.focusRequester(focusRequester)
)
} else {
@ -280,6 +281,16 @@ fun useAppListPage(): ScaffoldExt {
}
}
}
item {
Spacer(modifier = Modifier.height(40.dp))
if (orderedAppInfos.isEmpty() && searchStr.isNotEmpty()) {
Text(
text = "暂无搜索结果",
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center
)
}
}
}
}
}

View File

@ -102,7 +102,6 @@ fun useSettingsPage(): ScaffoldExt {
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
updateTimeRadioOptions.forEach { option ->
Row(
verticalAlignment = Alignment.CenterVertically,
@ -129,7 +128,6 @@ fun useSettingsPage(): ScaffoldExt {
}
}
}
}
if (showEnableDarkThemeDlg) {
Dialog(onDismissRequest = { showEnableDarkThemeDlg = false }) {
@ -139,7 +137,6 @@ fun useSettingsPage(): ScaffoldExt {
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
darkThemeRadioOptions.forEach { option ->
Row(
verticalAlignment = Alignment.CenterVertically,
@ -165,7 +162,6 @@ fun useSettingsPage(): ScaffoldExt {
}
}
}
}
if (showToastInputDlg) {
var value by remember {
@ -215,7 +211,6 @@ fun useSettingsPage(): ScaffoldExt {
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
val modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
@ -260,7 +255,6 @@ fun useSettingsPage(): ScaffoldExt {
}
}
}
}
when (val uploadStatusVal = uploadStatus) {
is LoadStatus.Failure -> {

View File

@ -6,9 +6,9 @@ import android.webkit.URLUtil
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@ -22,6 +22,7 @@ import androidx.compose.material.icons.automirrored.filled.FormatListBulleted
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
@ -114,7 +115,6 @@ fun useSubsManagePage(): ScaffoldExt {
.padding(16.dp),
shape = RoundedCornerShape(16.dp),
) {
Column {
val subsRawVal = subsIdToRaw[menuSubItemVal.id]
if (subsRawVal != null) {
Text(text = "应用规则", modifier = Modifier
@ -194,7 +194,6 @@ fun useSubsManagePage(): ScaffoldExt {
}
}
}
}
deleteSubItem?.let { deleteSubItemVal ->
AlertDialog(onDismissRequest = { deleteSubItem = null },
@ -291,9 +290,13 @@ fun useSubsManagePage(): ScaffoldExt {
if (isDragging) 1.dp else 0.dp,
label = "width",
)
val interactionSource = remember { MutableInteractionSource() }
Card(
onClick = { menuSubItem = subItem },
modifier = Modifier
.longPressDraggableHandle(onDragStopped = {
.longPressDraggableHandle(
interactionSource = interactionSource,
onDragStopped = {
val changeItems = mutableListOf<SubsItem>()
orderSubItems.forEachIndexed { i, subsItem ->
if (subItems[i] != subsItem) {
@ -309,17 +312,17 @@ fun useSubsManagePage(): ScaffoldExt {
DbSet.subsItemDao.update(*changeItems.toTypedArray())
}
}
})
.animateItemPlacement()
.padding(vertical = 3.dp, horizontal = 8.dp)
.clickable {
menuSubItem = subItem
},
)
.animateItemPlacement()
.padding(vertical = 3.dp, horizontal = 8.dp),
elevation = CardDefaults.cardElevation(draggedElevation = 10.dp),
shape = RoundedCornerShape(8.dp),
border = if (isDragging) BorderStroke(
width,
MaterialTheme.colorScheme.primary
) else null
) else null,
interactionSource = interactionSource,
) {
SubsItemCard(
subsItem = subItem,

View File

@ -128,9 +128,14 @@ dependencyResolutionManagement {
library("androidx.room.runtime", "androidx.room:room-runtime:$roomVersion")
library("androidx.room.compiler", "androidx.room:room-compiler:$roomVersion")
library("androidx.room.ktx", "androidx.room:room-ktx:$roomVersion")
library("androidx.room.paging", "androidx.room:room-paging:$roomVersion")
library("androidx.splashscreen", "androidx.core:core-splashscreen:1.0.1")
val pagingVersion = "3.2.1"
library("androidx.paging.runtime", "androidx.paging:paging-runtime:$pagingVersion")
library("androidx.paging.compose", "androidx.paging:paging-compose:$pagingVersion")
library(
"google.accompanist.drawablepainter",
"com.google.accompanist:accompanist-drawablepainter:0.34.0"
@ -203,7 +208,7 @@ dependencyResolutionManagement {
library("coil.gif", "io.coil-kt:coil-gif:$coilVersion")
// https://github.com/Calvin-LL/Reorderable
library("others.reorderable", "sh.calvin.reorderable:reorderable:1.3.1")
library("others.reorderable", "sh.calvin.reorderable:reorderable:1.3.2")
// https://www.objecthunter.net/exp4j/
library("exp4j", "net.objecthunter:exp4j:0.4.8")