fix: SMTP default port 465 + corrupt port recovery + click feedback on save buttons

- default SMTP port 587 -> 465 (SMTPS implicit TLS)
- init-collector: auto-correct port < 25 to 465 (previous bug stored 3)
- save-email fallback 587 -> 465
- email / SMS-number / SMS-quota save buttons show "✓ 已保存" for 2s

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 16:54:26 +08:00
parent 0c6b730115
commit 4c55366fec
2 changed files with 25 additions and 6 deletions
@@ -92,7 +92,7 @@ class SettingsStore(
// 电邮转发 // 电邮转发
val emailForwardingEnabled = MutableStateFlow(false) val emailForwardingEnabled = MutableStateFlow(false)
val smtpHost = MutableStateFlow("") val smtpHost = MutableStateFlow("")
val smtpPort = MutableStateFlow(587) val smtpPort = MutableStateFlow(465)
val smtpUser = MutableStateFlow("") val smtpUser = MutableStateFlow("")
val smtpPassword = MutableStateFlow("") val smtpPassword = MutableStateFlow("")
val smtpFrom = MutableStateFlow("") val smtpFrom = MutableStateFlow("")
@@ -129,7 +129,7 @@ class SettingsStore(
// 电邮转发 // 电邮转发
emailForwardingEnabled.value = p[K.EMAIL_ENABLED] ?: false emailForwardingEnabled.value = p[K.EMAIL_ENABLED] ?: false
smtpHost.value = p[K.EMAIL_HOST] ?: "" smtpHost.value = p[K.EMAIL_HOST] ?: ""
smtpPort.value = p[K.EMAIL_PORT] ?: 587 smtpPort.value = p[K.EMAIL_PORT]?.let { if (it < 25) 465 else it } ?: 465
smtpUser.value = p[K.EMAIL_USER] ?: "" smtpUser.value = p[K.EMAIL_USER] ?: ""
smtpPassword.value = p[K.EMAIL_PASS] ?: "" smtpPassword.value = p[K.EMAIL_PASS] ?: ""
smtpFrom.value = p[K.EMAIL_FROM] ?: "" smtpFrom.value = p[K.EMAIL_FROM] ?: ""
@@ -45,6 +45,7 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -114,6 +115,9 @@ fun SettingsScreen(onOpenLog: () -> Unit) {
var smtpPasswordInput by remember(smtpPassword) { mutableStateOf(smtpPassword) } var smtpPasswordInput by remember(smtpPassword) { mutableStateOf(smtpPassword) }
var smtpFromInput by remember(smtpFrom) { mutableStateOf(smtpFrom) } var smtpFromInput by remember(smtpFrom) { mutableStateOf(smtpFrom) }
var emailToInput by remember(emailTo) { mutableStateOf(emailTo) } var emailToInput by remember(emailTo) { mutableStateOf(emailTo) }
var emailSaved by remember { mutableStateOf(false) }
var smsNumSaved by remember { mutableStateOf(false) }
var smsQuotaSaved by remember { mutableStateOf(false) }
val smsPermLauncher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { } val smsPermLauncher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { }
val hasSmsPerm = remember { val hasSmsPerm = remember {
@@ -228,15 +232,22 @@ fun SettingsScreen(onOpenLog: () -> Unit) {
onClick = { onClick = {
app.appScope.launch { app.appScope.launch {
app.settings.setSmtpHost(smtpHostInput.trim()) app.settings.setSmtpHost(smtpHostInput.trim())
app.settings.setSmtpPort(smtpPortInput.trim().toIntOrNull() ?: 587) app.settings.setSmtpPort(smtpPortInput.trim().toIntOrNull() ?: 465)
app.settings.setSmtpUser(smtpUserInput.trim()) app.settings.setSmtpUser(smtpUserInput.trim())
app.settings.setSmtpPassword(smtpPasswordInput.trim()) app.settings.setSmtpPassword(smtpPasswordInput.trim())
app.settings.setSmtpFrom(smtpFromInput.trim()) app.settings.setSmtpFrom(smtpFromInput.trim())
app.settings.setEmailTo(emailToInput.trim()) app.settings.setEmailTo(emailToInput.trim())
} }
emailSaved = true
}, },
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) { Text("保存电邮设置") } ) { Text(if (emailSaved) "✓ 已保存" else "保存电邮设置") }
if (emailSaved) {
LaunchedEffect(Unit) {
kotlinx.coroutines.delay(2000)
emailSaved = false
}
}
} }
} }
} }
@@ -262,7 +273,11 @@ fun SettingsScreen(onOpenLog: () -> Unit) {
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) { Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
OutlinedButton(onClick = { OutlinedButton(onClick = {
app.appScope.launch { app.settings.setSmsTargetNumber(smsTargetInput.trim()) } app.appScope.launch { app.settings.setSmsTargetNumber(smsTargetInput.trim()) }
}, modifier = Modifier.weight(1f)) { Text("保存号码") } smsNumSaved = true
}, modifier = Modifier.weight(1f)) { Text(if (smsNumSaved) "✓ 已保存" else "保存号码") }
if (smsNumSaved) {
LaunchedEffect(Unit) { kotlinx.coroutines.delay(2000); smsNumSaved = false }
}
if (!hasSmsPerm) { if (!hasSmsPerm) {
OutlinedButton(onClick = { OutlinedButton(onClick = {
smsPermLauncher.launch(android.Manifest.permission.SEND_SMS) smsPermLauncher.launch(android.Manifest.permission.SEND_SMS)
@@ -294,7 +309,11 @@ fun SettingsScreen(onOpenLog: () -> Unit) {
app.settings.setSmsBalance(q) app.settings.setSmsBalance(q)
if (q > 5) app.settings.setSmsSuspended(false) if (q > 5) app.settings.setSmsSuspended(false)
} }
}) { Text("保存额度并解除挂起") } smsQuotaSaved = true
}) { Text(if (smsQuotaSaved) "✓ 已保存" else "保存额度并解除挂起") }
if (smsQuotaSaved) {
LaunchedEffect(Unit) { kotlinx.coroutines.delay(2000); smsQuotaSaved = false }
}
Spacer(Modifier.size(8.dp)) Spacer(Modifier.size(8.dp))
val balanceText = when { val balanceText = when {