fix(credential): 多账号会话凭据按请求账号精确匹配;UI微调

- CredentialRepository 快照新增 requestedAccountId,暂存凭据严格按请求账号匹配,
  避免 A 账号刷新期间把暂存凭据误交给默认账号/其他账号
- Dashboard 首页提示与自动签到开关改为卡片样式,开关配色对齐雨晴粉主题
- 默认账号徽标加 maxLines/softWrap 防窄屏换行
This commit is contained in:
Liuxinyu176 2026-10-08 22:16:06 +08:00
parent 2509ab8a85
commit 79f99f5dee
3 changed files with 52 additions and 26 deletions

View File

@ -40,7 +40,9 @@ class CredentialRepository @Inject constructor(
val revision: Long,
val fingerprint: String,
/** 快照所属账号;单账号服务为 null。 */
val accountId: String? = null
val accountId: String? = null,
/** 创建快照时调用方请求的账号 ID(多账号服务可能是 null=默认账号),用于会话内精确匹配。 */
val requestedAccountId: String? = accountId
) {
val service: ServiceType get() = credential.service
}
@ -237,9 +239,9 @@ class CredentialRepository @Inject constructor(
if (session.snapshot.service == service) {
val matches = if (ServiceType.isMultiAccount(service)) {
val requested = accountId?.takeIf { it.isNotBlank() }
requested == null ||
session.snapshot.accountId == null ||
session.snapshot.accountId == requested
// 只允许读取与快照同一账号的暂存凭据;null=默认账号也要看快照当初请求的是不是默认账号,
// 避免 A 账号刷新期间把 A 的暂存凭据误交给默认账号(B)的读请求。
requested == session.snapshot.requestedAccountId
} else {
true
}
@ -368,7 +370,8 @@ class CredentialRepository @Inject constructor(
credential = credential,
revision = revisionFor(service, resolvedId),
fingerprint = credentialFingerprint(credential)!!,
accountId = resolvedId
accountId = resolvedId,
requestedAccountId = accountId?.takeIf { it.isNotBlank() }
)
}

View File

@ -102,6 +102,8 @@ import com.rainy.token.ui.components.AppTips
import com.rainy.token.ui.components.asString
import com.rainy.token.ui.dashboard.autocheckin.AutoCheckinManager
import com.rainy.token.ui.theme.inkMuted
import com.rainy.token.ui.theme.PureWhite
import com.rainy.token.ui.theme.inkWarm
import com.rainy.token.ui.theme.StrawberryPink
import android.app.AppOpsManager
import android.appwidget.AppWidgetManager
@ -347,9 +349,17 @@ fun DashboardScreen(
// 随机小技巧提示(每次启动随机一条)+ 最右侧自动签到开关
val tipTextRes = remember { AppTips.randomHintRes() }
val autoCheckinEnabled by viewModel.autoCheckinEnabled.collectAsStateWithLifecycle()
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surface
),
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 4.dp)
modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp)
) {
Text(
text = "💡 " + stringResource(tipTextRes),
@ -360,15 +370,24 @@ fun DashboardScreen(
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.auto_checkin_switch_label),
style = MaterialTheme.typography.labelSmall,
color = inkMuted()
style = MaterialTheme.typography.labelMedium,
color = inkWarm(),
fontWeight = FontWeight.SemiBold
)
Spacer(modifier = Modifier.width(2.dp))
Switch(
checked = autoCheckinEnabled,
onCheckedChange = viewModel::setAutoCheckinEnabled,
colors = SwitchDefaults.colors(checkedThumbColor = StrawberryPink)
colors = SwitchDefaults.colors(
checkedThumbColor = PureWhite,
checkedTrackColor = StrawberryPink,
checkedBorderColor = StrawberryPink,
uncheckedThumbColor = MaterialTheme.colorScheme.onSurfaceVariant,
uncheckedTrackColor = MaterialTheme.colorScheme.surfaceVariant,
uncheckedBorderColor = MaterialTheme.colorScheme.onSurfaceVariant
)
)
}
}
val items = rememberDashboardItems(
cards = uiState.cards,
@ -922,6 +941,8 @@ private fun DashboardCard(
text = stringResource(R.string.account_default_badge),
style = MaterialTheme.typography.labelSmall,
color = StrawberryPink,
maxLines = 1,
softWrap = false,
modifier = Modifier
.clip(RoundedCornerShape(8.dp))
.background(StrawberryPink.copy(alpha = 0.12f))

View File

@ -296,6 +296,8 @@ private fun AccountRow(
text = stringResource(R.string.account_default_badge),
style = MaterialTheme.typography.labelSmall,
color = StrawberryPink,
maxLines = 1,
softWrap = false,
modifier = Modifier
.padding(horizontal = 6.dp, vertical = 2.dp)
.background(