Skip to content

Commit

Permalink
feat: add ActionLog for App/Subs
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Jan 13, 2025
1 parent 9e1ab82 commit 889c643
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 43 deletions.
12 changes: 12 additions & 0 deletions app/src/main/kotlin/li/songe/gkd/data/ActionLog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,24 @@ data class ActionLog(
@Query("DELETE FROM action_log")
suspend fun deleteAll()

@Query("DELETE FROM action_log WHERE subs_id=:subsId")
suspend fun deleteSubsAll(subsId: Long)

@Query("DELETE FROM action_log WHERE app_id=:appId")
suspend fun deleteAppAll(appId: String)

@Query("SELECT * FROM action_log ORDER BY id DESC LIMIT 1000")
fun query(): Flow<List<ActionLog>>

@Query("SELECT * FROM action_log ORDER BY id DESC ")
fun pagingSource(): PagingSource<Int, ActionLog>

@Query("SELECT * FROM action_log WHERE subs_id=:subsId ORDER BY id DESC ")
fun pagingSubsSource(subsId: Long): PagingSource<Int, ActionLog>

@Query("SELECT * FROM action_log WHERE app_id=:appId ORDER BY id DESC ")
fun pagingAppSource(appId: String): PagingSource<Int, ActionLog>

@Query("SELECT COUNT(*) FROM action_log")
fun count(): Flow<Int>

Expand Down
83 changes: 62 additions & 21 deletions app/src/main/kotlin/li/songe/gkd/ui/ActionLogPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import li.songe.gkd.ui.component.EmptyText
import li.songe.gkd.ui.component.FixedTimeText
import li.songe.gkd.ui.component.LocalNumberCharWidth
import li.songe.gkd.ui.component.StartEllipsisText
import li.songe.gkd.ui.component.TowLineText
import li.songe.gkd.ui.component.measureNumberTextWidth
import li.songe.gkd.ui.component.waitResult
import li.songe.gkd.ui.style.EmptyHeight
Expand All @@ -87,12 +88,14 @@ import li.songe.gkd.util.toast

@Destination<RootGraph>(style = ProfileTransitions::class)
@Composable
fun ActionLogPage() {
fun ActionLogPage(
subsId: Long? = null,
appId: String? = null,
) {
val context = LocalContext.current as MainActivity
val mainVm = context.mainVm
val navController = LocalNavController.current
val vm = viewModel<ActionLogVm>()
val actionLogCount by vm.actionLogCountFlow.collectAsState()
val actionDataItems = vm.pagingDataFlow.collectAsLazyPagingItems()

val subsIdToRaw by subsIdToRawFlow.collectAsState()
Expand Down Expand Up @@ -134,16 +137,46 @@ fun ActionLogPage() {
)
}
},
title = { Text(text = "触发记录") },
title = {
val title = "触发记录"
if (subsId != null) {
TowLineText(
title = title,
subtitle = subsIdToRaw[subsId]?.name ?: subsId.toString()
)
} else if (appId != null) {
TowLineText(
title = title,
subtitle = appId,
showApp = true,
)
} else {
Text(text = title)
}
},
actions = {
if (actionLogCount > 0) {
if (actionDataItems.itemCount > 0) {
IconButton(onClick = throttle(fn = mainVm.viewModelScope.launchAsFn {
val text = if (subsId != null) {
"确定删除当前订阅所有触发记录?"
} else if (appId != null) {
"确定删除当前应用所有触发记录?"
} else {
"确定删除所有触发记录?"
}
mainVm.dialogFlow.waitResult(
title = "删除记录",
text = "确定删除所有触发记录?",
text = text,
error = true,
)
DbSet.actionLogDao.deleteAll()
if (subsId != null) {
DbSet.actionLogDao.deleteSubsAll(subsId)
} else if (appId != null) {
DbSet.actionLogDao.deleteAppAll(appId)
} else {
DbSet.actionLogDao.deleteAll()
}

})) {
Icon(
imageVector = Icons.Outlined.Delete,
Expand Down Expand Up @@ -172,13 +205,15 @@ fun ActionLogPage() {
lastItem = lastItem,
onClick = {
previewActionLog = item.t0
}
},
subsId = subsId,
appId = appId,
)
}
}
item {
Spacer(modifier = Modifier.height(EmptyHeight))
if (actionLogCount == 0 && actionDataItems.loadState.refresh !is LoadState.Loading) {
if (actionDataItems.itemCount == 0 && actionDataItems.loadState.refresh !is LoadState.Loading) {
EmptyText(text = "暂无记录")
}
}
Expand Down Expand Up @@ -330,7 +365,9 @@ private fun ActionLogCard(
i: Int,
item: Tuple3<ActionLog, RawSubscription.RawGroupProps?, RawSubscription.RawRuleProps?>,
lastItem: Tuple3<ActionLog, RawSubscription.RawGroupProps?, RawSubscription.RawRuleProps?>?,
onClick: () -> Unit
onClick: () -> Unit,
subsId: Long?,
appId: String?,
) {
val context = LocalContext.current as MainActivity
val (actionLog, group, rule) = item
Expand All @@ -348,7 +385,7 @@ private fun ActionLogCard(
top = verticalPadding
)
) {
if (isDiffApp) {
if (isDiffApp && appId == null) {
AppNameText(appId = actionLog.appId)
}
Row(
Expand All @@ -357,7 +394,9 @@ private fun ActionLogCard(
.fillMaxWidth()
.height(IntrinsicSize.Min)
) {
Spacer(modifier = Modifier.width(2.dp))
if (appId == null) {
Spacer(modifier = Modifier.width(2.dp))
}
Spacer(
modifier = Modifier
.fillMaxHeight()
Expand Down Expand Up @@ -386,16 +425,18 @@ private fun ActionLogCard(
color = LocalContentColor.current.copy(alpha = 0.5f),
)
}
Text(
text = subscription?.name ?: "id=${actionLog.subsId}",
modifier = Modifier.clickable(onClick = throttle {
if (subsItemsFlow.value.any { it.id == actionLog.subsId }) {
context.mainVm.sheetSubsIdFlow.value = actionLog.subsId
} else {
toast("订阅不存在")
}
})
)
if (subsId == null) {
Text(
text = subscription?.name ?: "id=${actionLog.subsId}",
modifier = Modifier.clickable(onClick = throttle {
if (subsItemsFlow.value.any { it.id == actionLog.subsId }) {
context.mainVm.sheetSubsIdFlow.value = actionLog.subsId
} else {
toast("订阅不存在")
}
})
)
}
Row(
modifier = Modifier.fillMaxWidth()
) {
Expand Down
20 changes: 13 additions & 7 deletions app/src/main/kotlin/li/songe/gkd/ui/ActionLogVm.kt
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
package li.songe.gkd.ui

import androidx.lifecycle.SavedStateHandle
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 kotlinx.coroutines.flow.SharingStarted
import com.ramcosta.composedestinations.generated.destinations.ActionLogPageDestination
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.data.SubsConfig
import li.songe.gkd.data.Tuple3
import li.songe.gkd.db.DbSet
import li.songe.gkd.util.subsIdToRawFlow

class ActionLogVm : ViewModel() {
class ActionLogVm(stateHandle: SavedStateHandle) : ViewModel() {
private val args = ActionLogPageDestination.argsFrom(stateHandle)

val pagingDataFlow = Pager(PagingConfig(pageSize = 100)) { DbSet.actionLogDao.pagingSource() }
val pagingDataFlow = Pager(PagingConfig(pageSize = 100)) {
if (args.subsId != null) {
DbSet.actionLogDao.pagingSubsSource(subsId = args.subsId)
} else if (args.appId != null) {
DbSet.actionLogDao.pagingAppSource(appId = args.appId)
} else {
DbSet.actionLogDao.pagingSource()
}
}
.flow
.combine(subsIdToRawFlow) { pagingData, subsIdToRaw ->
pagingData.map { c ->
Expand All @@ -38,7 +47,4 @@ class ActionLogVm : ViewModel() {
}
.cachedIn(viewModelScope)

val actionLogCountFlow =
DbSet.actionLogDao.count().stateIn(viewModelScope, SharingStarted.Eagerly, 0)

}
11 changes: 11 additions & 0 deletions app/src/main/kotlin/li/songe/gkd/ui/AppConfigPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.Sort
import androidx.compose.material.icons.filled.History
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
Expand Down Expand Up @@ -50,6 +51,7 @@ import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.ActionLogPageDestination
import com.ramcosta.composedestinations.generated.destinations.AppItemPageDestination
import com.ramcosta.composedestinations.generated.destinations.GlobalRulePageDestination
import com.ramcosta.composedestinations.utils.toDestinationsNavigator
Expand Down Expand Up @@ -118,6 +120,15 @@ fun AppConfigPage(appId: String) {
appId = appId
)
}, actions = {
IconButton(onClick = throttle {
navController.toDestinationsNavigator()
.navigate(ActionLogPageDestination(appId = appId))
}) {
Icon(
imageVector = Icons.Default.History,
contentDescription = null,
)
}
IconButton(onClick = {
expanded = true
}) {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/li/songe/gkd/ui/AppItemPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ fun AppItemPage(
}, title = {
TowLineText(
title = subsRaw?.name ?: subsItemId.toString(),
subTitle = appInfoCache[appId]?.name ?: appRaw.name ?: appId
subtitle = appInfoCache[appId]?.name ?: appRaw.name ?: appId
)
}, actions = {})
}, floatingActionButton = {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/li/songe/gkd/ui/CategoryPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ fun CategoryPage(subsItemId: Long) {
}, title = {
TowLineText(
title = subsRaw?.name ?: subsItemId.toString(),
subTitle = "规则类别"
subtitle = "规则类别"
)
}, actions = {
IconButton(onClick = throttle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ fun GlobalRuleExcludePage(subsItemId: Long, groupKey: Int) {
} else {
TowLineText(
title = rawSubs?.name ?: subsItemId.toString(),
subTitle = (group?.name ?: groupKey.toString())
subtitle = (group?.name ?: groupKey.toString())
)
}
}, actions = {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/li/songe/gkd/ui/GlobalRulePage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ fun GlobalRulePage(subsItemId: Long, focusGroupKey: Int? = null) {
}, title = {
TowLineText(
title = rawSubs?.name ?: subsItemId.toString(),
subTitle = "全局规则"
subtitle = "全局规则"
)
})
},
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/kotlin/li/songe/gkd/ui/SubsPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ fun SubsPage(
} else {
TowLineText(
title = subsRaw?.name ?: subsItemId.toString(),
subTitle = "应用规则",
subtitle = "应用规则",
)
}
}, actions = {
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/kotlin/li/songe/gkd/ui/component/SubsSheet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
import androidx.compose.material.icons.automirrored.filled.OpenInNew
import androidx.compose.material.icons.filled.History
import androidx.compose.material.icons.filled.Share
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.Edit
Expand Down Expand Up @@ -42,6 +43,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ramcosta.composedestinations.generated.destinations.ActionLogPageDestination
import com.ramcosta.composedestinations.generated.destinations.CategoryPageDestination
import com.ramcosta.composedestinations.generated.destinations.CategoryPageDestination.invoke
import com.ramcosta.composedestinations.generated.destinations.GlobalRulePageDestination
Expand Down Expand Up @@ -416,6 +418,14 @@ fun SubsSheet(
modifier = childModifier,
horizontalArrangement = Arrangement.End
) {
IconButton(onClick = throttle {
setSubsId(null)
sheetSubsIdFlow.value = null
navController.toDestinationsNavigator()
.navigate(ActionLogPageDestination(subsId = subsItem.id))
}) {
Icon(imageVector = Icons.Default.History, contentDescription = null)
}
if (subscription != null || !subsItem.isLocal) {
IconButton(onClick = throttle {
context.mainVm.showShareDataIdsFlow.value = setOf(subsItem.id)
Expand Down
24 changes: 16 additions & 8 deletions app/src/main/kotlin/li/songe/gkd/ui/component/TowLineText.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package li.songe.gkd.ui.component

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.text.style.TextOverflow

@Composable
fun TowLineText(
title: String,
subTitle: String
subtitle: String,
showApp: Boolean = false,
) {
Column {
Text(
Expand All @@ -18,11 +21,16 @@ fun TowLineText(
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleMedium
)
Text(
text = subTitle,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleSmall
)
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.titleSmall) {
if (showApp) {
AppNameText(appId = subtitle)
} else {
Text(
text = subtitle,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
}
}
2 changes: 1 addition & 1 deletion app/src/main/kotlin/li/songe/gkd/ui/home/ControlPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ fun useControlPage(): ScaffoldExt {
imageVector = Icons.Default.History,
onClick = {
navController.toDestinationsNavigator()
.navigate(ActionLogPageDestination)
.navigate(ActionLogPageDestination())
}
)

Expand Down
1 change: 0 additions & 1 deletion app/src/main/kotlin/li/songe/gkd/util/SubsState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.withContext
import kotlinx.serialization.encodeToString
import li.songe.gkd.appScope
import li.songe.gkd.data.AppRule
import li.songe.gkd.data.CategoryConfig
Expand Down

0 comments on commit 889c643

Please sign in to comment.