mirror of
https://github.com/gkd-kit/gkd.git
synced 2026-09-03 07:19:59 +08:00
feat: refine home service controls
This commit is contained in:
@@ -278,29 +278,13 @@ fun AdvancedPage() {
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(contentPadding),
|
||||
) {
|
||||
Text(
|
||||
text = "特权服务",
|
||||
modifier = Modifier.titleItemPadding(showTop = false),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
SettingItem(
|
||||
title = "特权服务",
|
||||
subtitle = "管理授权与启动方式",
|
||||
imageVector = PerfIcon.ArrowForward,
|
||||
onClickLabel = "打开高级授权页面",
|
||||
onClick = {
|
||||
mainVm.navigatePage(PrivilegePageRoute)
|
||||
},
|
||||
)
|
||||
|
||||
val server by HttpService.httpServerFlow.collectAsState()
|
||||
val httpServerRunning = server != null
|
||||
val localNetworkIps by HttpService.localNetworkIpsFlow.collectAsState()
|
||||
|
||||
Text(
|
||||
text = "HTTP",
|
||||
modifier = Modifier.titleItemPadding(),
|
||||
modifier = Modifier.titleItemPadding(showTop = false),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
|
||||
@@ -14,7 +14,6 @@ import li.songe.gkd.priv.gkdPrivilegeUiConfig
|
||||
import li.songe.gkd.ui.component.PerfIcon
|
||||
import li.songe.gkd.ui.component.PerfIconButton
|
||||
import li.songe.gkd.ui.component.PerfTopAppBar
|
||||
import li.songe.gkd.ui.icon.GitHub
|
||||
import li.songe.gkd.ui.share.LocalMainViewModel
|
||||
import priv.kit.ui.PrivilegeScaffold
|
||||
import priv.kit.ui.PrivilegeUiViewModel
|
||||
@@ -23,8 +22,6 @@ import priv.kit.ui.R as PrivilegeUiR
|
||||
@Serializable
|
||||
data object PrivilegePageRoute : NavKey
|
||||
|
||||
private const val PRIV_KIT_REPOSITORY_URL = "https://github.com/priv-kit/priv-kit"
|
||||
|
||||
@Composable
|
||||
fun PrivilegePage() {
|
||||
val mainVm = LocalMainViewModel.current
|
||||
@@ -48,15 +45,6 @@ fun PrivilegePage() {
|
||||
title = {
|
||||
Text(text = stringResource(PrivilegeUiR.string.priv_ui_title))
|
||||
},
|
||||
actions = {
|
||||
PerfIconButton(
|
||||
imageVector = GitHub,
|
||||
contentDescription = "GitHub",
|
||||
onClick = {
|
||||
mainVm.openUrl(PRIV_KIT_REPOSITORY_URL)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -18,6 +18,8 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.IconButtonDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -70,6 +72,7 @@ import li.songe.gkd.ui.style.EmptyHeight
|
||||
import li.songe.gkd.ui.style.itemHorizontalPadding
|
||||
import li.songe.gkd.ui.style.itemVerticalPadding
|
||||
import li.songe.gkd.ui.style.surfaceCardColors
|
||||
import li.songe.gkd.util.AutomatorModeOption
|
||||
import li.songe.gkd.util.HOME_PAGE_URL
|
||||
import li.songe.gkd.util.ShortUrlSet
|
||||
import li.songe.gkd.util.latestRecordDescFlow
|
||||
@@ -82,6 +85,8 @@ fun useControlPage(): ScaffoldExt {
|
||||
val context = LocalActivity.current as MainActivity
|
||||
val mainVm = LocalMainViewModel.current
|
||||
val vm = viewModel<HomeVm>()
|
||||
val privilegeContext by privilegeContextFlow.collectAsState()
|
||||
val automatorMode by mainVm.automatorModeFlow.collectAsState()
|
||||
val scrollKey = rememberSaveable { mutableIntStateOf(0) }
|
||||
val (scrollBehavior, scrollState) = useScrollBehaviorState(scrollKey)
|
||||
LaunchedEffect(null) {
|
||||
@@ -102,10 +107,21 @@ fun useControlPage(): ScaffoldExt {
|
||||
}, actions = {
|
||||
PerfIconButton(
|
||||
imageVector = PerfIcon.RocketLaunch,
|
||||
onClickLabel = "前往工作模式页面",
|
||||
contentDescription = "工作模式",
|
||||
onClickLabel = "前往特权服务页面",
|
||||
contentDescription = if (privilegeContext == null) {
|
||||
"特权服务,未连接"
|
||||
} else {
|
||||
"特权服务,已连接"
|
||||
},
|
||||
colors = IconButtonDefaults.iconButtonColors(
|
||||
contentColor = when {
|
||||
privilegeContext != null -> MaterialTheme.colorScheme.primary
|
||||
automatorMode == AutomatorModeOption.AutomationMode -> MaterialTheme.colorScheme.error
|
||||
else -> MaterialTheme.colorScheme.onSurfaceVariant
|
||||
},
|
||||
),
|
||||
onClick = throttle {
|
||||
mainVm.navigatePage(AuthA11yRoute)
|
||||
mainVm.navigatePage(PrivilegePageRoute)
|
||||
},
|
||||
)
|
||||
})
|
||||
@@ -154,9 +170,7 @@ fun useControlPage(): ScaffoldExt {
|
||||
}
|
||||
}
|
||||
if (store.useA11y || actualA11yScopeAppList.contains(topAppIdFlow.collectAsState().value)) {
|
||||
PageSwitchItemCard(
|
||||
imageVector = PerfIcon.Memory,
|
||||
title = "服务状态",
|
||||
ServiceStatusCard(
|
||||
subtitle = if (a11yRunning) {
|
||||
"无障碍正在运行"
|
||||
} else if (mainVm.a11yServiceEnabledFlow.collectAsState().value) {
|
||||
@@ -178,13 +192,14 @@ fun useControlPage(): ScaffoldExt {
|
||||
switchAutomatorService()
|
||||
}
|
||||
},
|
||||
mode = automatorMode.label,
|
||||
onModeClick = {
|
||||
mainVm.navigatePage(AuthA11yRoute)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
val automation by uiAutomationFlow.collectAsState()
|
||||
val privilegeContext by privilegeContextFlow.collectAsState()
|
||||
PageSwitchItemCard(
|
||||
imageVector = PerfIcon.Memory,
|
||||
title = "服务状态",
|
||||
ServiceStatusCard(
|
||||
subtitle = if (automation != null) {
|
||||
"自动化正在运行"
|
||||
} else if (privilegeContext == null) {
|
||||
@@ -204,6 +219,10 @@ fun useControlPage(): ScaffoldExt {
|
||||
switchAutomatorService()
|
||||
}
|
||||
},
|
||||
mode = automatorMode.label,
|
||||
onModeClick = {
|
||||
mainVm.navigatePage(AuthA11yRoute)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -224,16 +243,7 @@ fun useControlPage(): ScaffoldExt {
|
||||
},
|
||||
)
|
||||
|
||||
ServerStatusCard()
|
||||
|
||||
PageItemCard(
|
||||
title = "触发记录",
|
||||
subtitle = "规则误触可定位关闭",
|
||||
imageVector = PerfIcon.History,
|
||||
onClickLabel = "打开触发记录页面",
|
||||
onClick = {
|
||||
mainVm.navigatePage(ActionLogRoute())
|
||||
})
|
||||
TriggerOverviewCard()
|
||||
|
||||
if (ActivityService.isRunning.collectAsState().value) {
|
||||
PageItemCard(
|
||||
@@ -342,12 +352,108 @@ private fun PageSwitchItemCard(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ServiceStatusCard(
|
||||
subtitle: String,
|
||||
checked: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
mode: String,
|
||||
onModeClick: () -> Unit,
|
||||
) {
|
||||
val onStatusClick = throttle { onCheckedChange(!checked) }
|
||||
val onModeRowClick = throttle(onModeClick)
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = MaterialTheme.shapes.large,
|
||||
colors = surfaceCardColors,
|
||||
) {
|
||||
IconTextCard(
|
||||
imageVector = PerfIcon.Memory,
|
||||
modifier = Modifier
|
||||
.semantics(mergeDescendants = true) {}
|
||||
.clickable(
|
||||
onClickLabel = "切换服务状态",
|
||||
onClick = onStatusClick,
|
||||
),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
Text(
|
||||
text = "服务状态",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
Text(
|
||||
text = subtitle,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.width(8.dp))
|
||||
PerfSwitch(
|
||||
checked = checked,
|
||||
onCheckedChange = null,
|
||||
)
|
||||
}
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(
|
||||
start = itemVerticalPadding + 40.dp + itemHorizontalPadding,
|
||||
end = itemVerticalPadding,
|
||||
),
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.semantics(mergeDescendants = true) {}
|
||||
.clickable(
|
||||
onClickLabel = "前往工作模式页面",
|
||||
onClick = onModeRowClick,
|
||||
)
|
||||
.padding(
|
||||
start = itemVerticalPadding,
|
||||
end = itemVerticalPadding,
|
||||
top = 10.dp,
|
||||
bottom = 10.dp,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
PerfIcon(
|
||||
imageVector = PerfIcon.AutoMode,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 10.dp)
|
||||
.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
contentDescription = null,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(itemHorizontalPadding))
|
||||
Text(
|
||||
text = "工作模式",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Text(
|
||||
text = mode,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
PerfIcon(
|
||||
imageVector = PerfIcon.KeyboardArrowRight,
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun IconTextCard(
|
||||
imageVector: ImageVector, content: @Composable () -> Unit
|
||||
imageVector: ImageVector,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(itemVerticalPadding),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
@@ -368,18 +474,25 @@ private fun IconTextCard(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ServerStatusCard() {
|
||||
private fun TriggerOverviewCard() {
|
||||
val mainVm = LocalMainViewModel.current
|
||||
val vm = viewModel<HomeVm>()
|
||||
val openActionLog = throttle {
|
||||
mainVm.navigatePage(ActionLogRoute())
|
||||
}
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.semantics {
|
||||
onClick(label = "不执行操作", action = null)
|
||||
}, shape = RoundedCornerShape(20.dp), colors = surfaceCardColors, onClick = {}) {
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(20.dp),
|
||||
colors = surfaceCardColors,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.semantics(mergeDescendants = true) {}
|
||||
.clickable(
|
||||
onClickLabel = "打开触发记录页面",
|
||||
onClick = openActionLog,
|
||||
)
|
||||
.padding(
|
||||
start = itemVerticalPadding,
|
||||
end = itemVerticalPadding,
|
||||
@@ -401,18 +514,20 @@ private fun ServerStatusCard() {
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
Text(
|
||||
text = "数据概览",
|
||||
text = "触发记录",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
val usedSubsItemCount by vm.usedSubsItemCountFlow.collectAsState()
|
||||
AnimatedVisibility(usedSubsItemCount > 0) {
|
||||
Text(
|
||||
text = "已开启 $usedSubsItemCount 条订阅",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = "规则误触可定位关闭",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
PerfIcon(
|
||||
imageVector = PerfIcon.KeyboardArrowRight,
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
||||
@@ -13,7 +13,6 @@ import li.songe.gkd.util.EMPTY_RULE_TIP
|
||||
import li.songe.gkd.util.findOption
|
||||
import li.songe.gkd.util.getSubsStatus
|
||||
import li.songe.gkd.util.ruleSummaryFlow
|
||||
import li.songe.gkd.util.usedSubsEntriesFlow
|
||||
|
||||
class HomeVm : BaseViewModel() {
|
||||
|
||||
@@ -23,8 +22,6 @@ class HomeVm : BaseViewModel() {
|
||||
}.stateInit(EMPTY_RULE_TIP)
|
||||
}
|
||||
|
||||
val usedSubsItemCountFlow = usedSubsEntriesFlow.mapNew { it.size }
|
||||
|
||||
val sortTypeFlow = storeFlow.asMutableStateFlow(
|
||||
getter = { AppSortOption.objects.findOption(it.appSort) },
|
||||
setter = {
|
||||
|
||||
@@ -14,7 +14,7 @@ coil = "3.5.0"
|
||||
telephoto = "0.19.0"
|
||||
remap = "0.1.4"
|
||||
shizuku = "13.1.5"
|
||||
priv-kit = "0.3.2"
|
||||
priv-kit = "0.3.3"
|
||||
loc = "0.7.1"
|
||||
|
||||
[libraries]
|
||||
|
||||
Reference in New Issue
Block a user