diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 27caee4..5b16a55 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,8 +13,8 @@ android { applicationId = "com.a2i.forwarder" minSdk = 34 targetSdk = 36 - versionCode = 26 - versionName = "1.8.9" + versionCode = 27 + versionName = "1.8.10" } signingConfigs { diff --git a/app/src/main/java/com/a2i/forwarder/ui/Components.kt b/app/src/main/java/com/a2i/forwarder/ui/Components.kt index 941267f..9b47f7c 100644 --- a/app/src/main/java/com/a2i/forwarder/ui/Components.kt +++ b/app/src/main/java/com/a2i/forwarder/ui/Components.kt @@ -7,6 +7,7 @@ import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background +import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -68,6 +69,8 @@ fun SectionCard( title: String? = null, modifier: Modifier = Modifier, subtitle: String? = null, + titleIcon: ImageVector? = null, + titleIconTint: Color = MaterialTheme.colorScheme.primary, headerAction: (@Composable () -> Unit)? = null, content: @Composable ColumnScope.() -> Unit, ) { @@ -81,12 +84,18 @@ fun SectionCard( Column(Modifier.padding(16.dp)) { if (title != null) { if (headerAction == null) { - Text( - title, - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold, - modifier = Modifier.padding(bottom = if (subtitle == null) 10.dp else 2.dp), - ) + Row(verticalAlignment = Alignment.CenterVertically) { + if (titleIcon != null) { + Icon(titleIcon, null, tint = titleIconTint, modifier = Modifier.size(22.dp)) + Spacer(Modifier.width(8.dp)) + } + Text( + title, + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold, + modifier = Modifier.padding(bottom = if (subtitle == null) 10.dp else 2.dp), + ) + } if (subtitle != null) { Text( subtitle, @@ -103,12 +112,18 @@ fun SectionCard( verticalAlignment = Alignment.Top, ) { Column(Modifier.weight(1f)) { - Text( - title, - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold, - modifier = Modifier.padding(bottom = if (subtitle == null) 0.dp else 2.dp), - ) + Row(verticalAlignment = Alignment.CenterVertically) { + if (titleIcon != null) { + Icon(titleIcon, null, tint = titleIconTint, modifier = Modifier.size(22.dp)) + Spacer(Modifier.width(8.dp)) + } + Text( + title, + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold, + modifier = Modifier.padding(bottom = if (subtitle == null) 0.dp else 2.dp), + ) + } if (subtitle != null) { Text( subtitle, diff --git a/app/src/main/java/com/a2i/forwarder/ui/screens/SettingsScreen.kt b/app/src/main/java/com/a2i/forwarder/ui/screens/SettingsScreen.kt index 9369f7f..e6dc1ba 100644 --- a/app/src/main/java/com/a2i/forwarder/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/com/a2i/forwarder/ui/screens/SettingsScreen.kt @@ -6,6 +6,7 @@ import android.net.Uri import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -26,11 +27,15 @@ import androidx.compose.material.icons.automirrored.filled.Send import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.Email import androidx.compose.material.icons.filled.History import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.KeyboardArrowDown import androidx.compose.material.icons.filled.KeyboardArrowUp +import androidx.compose.material.icons.filled.Notifications +import androidx.compose.material.icons.filled.Pets import androidx.compose.material.icons.filled.RestartAlt +import androidx.compose.material.icons.filled.Sms import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.SystemUpdateAlt import androidx.compose.material.icons.filled.Update @@ -57,12 +62,16 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.documentfile.provider.DocumentFile import com.a2i.forwarder.A2iApp +import com.a2i.forwarder.R import com.a2i.forwarder.core.BarkClient import com.a2i.forwarder.core.EmailSender import com.a2i.forwarder.core.IconExporter @@ -167,6 +176,7 @@ fun SettingsScreen(onOpenLog: () -> Unit) { summary = "iPhone / iPad 推送目标", mark = "B", markColor = Color(0xFFFF9800), + markLogo = painterResource(R.drawable.ic_bark_logo), platforms = listOf("iOS"), stopFirst = barkStopFirst, onStopFirstChange = { v -> app.appScope.launch { app.settings.setBarkStopOnFirst(v) } }, @@ -199,6 +209,7 @@ fun SettingsScreen(onOpenLog: () -> Unit) { summary = "Android / iOS topic 推送", mark = "n", markColor = Color(0xFF43A047), + markLogo = painterResource(R.drawable.ic_ntfy_logo), platforms = listOf("Android", "iOS"), stopFirst = ntfyStopFirst, onStopFirstChange = { v -> app.appScope.launch { app.settings.setNtfyStopOnFirst(v) } }, @@ -234,6 +245,7 @@ fun SettingsScreen(onOpenLog: () -> Unit) { summary = "鸿蒙手机推送目标", mark = "M", markColor = Color(0xFF7E57C2), + markIcon = Icons.Filled.Pets, platforms = listOf("HarmonyOS"), stopFirst = meowStopFirst, onStopFirstChange = { v -> app.appScope.launch { app.settings.setMeowStopOnFirst(v) } }, @@ -269,6 +281,7 @@ fun SettingsScreen(onOpenLog: () -> Unit) { summary = "SMTP 邮箱推送目标", mark = "@", markColor = Color(0xFF1976D2), + markIcon = Icons.Filled.Email, platforms = listOf("Email"), stopFirst = emailStopFirst, onStopFirstChange = { v -> app.appScope.launch { app.settings.setEmailStopOnFirst(v) } }, @@ -302,6 +315,7 @@ fun SettingsScreen(onOpenLog: () -> Unit) { summary = "无网络时发送关键通知", mark = "S", markColor = Color(0xFF00897B), + markIcon = Icons.Filled.Sms, platforms = listOf("SMS"), stopFirst = smsStopFirst, onStopFirstChange = { v -> app.appScope.launch { app.settings.setSmsStopOnFirst(v) } }, @@ -421,6 +435,8 @@ private fun ChannelSectionHeader( summary: String, mark: String, markColor: Color, + markIcon: ImageVector? = null, + markLogo: Painter? = null, platforms: List, stopFirst: Boolean, onStopFirstChange: (Boolean) -> Unit, @@ -435,7 +451,7 @@ private fun ChannelSectionHeader( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, ) { - ChannelMark(mark = mark, tint = markColor) + ChannelMark(mark = mark, tint = markColor, icon = markIcon, logoPainter = markLogo) Spacer(Modifier.width(10.dp)) Row( modifier = Modifier.weight(1f), @@ -492,7 +508,7 @@ private fun ChannelSectionHeader( } @Composable -private fun ChannelMark(mark: String, tint: Color) { +private fun ChannelMark(mark: String, tint: Color, icon: ImageVector? = null, logoPainter: Painter? = null) { Surface( modifier = Modifier.size(36.dp), shape = RoundedCornerShape(10.dp), @@ -504,13 +520,13 @@ private fun ChannelMark(mark: String, tint: Color) { horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, ) { - Text( - mark, - style = MaterialTheme.typography.titleSmall, - fontWeight = FontWeight.Bold, - color = tint, - maxLines = 1, - ) + if (logoPainter != null) { + Image(logoPainter, null, modifier = Modifier.size(24.dp)) + } else if (icon != null) { + Icon(icon, null, tint = tint, modifier = Modifier.size(20.dp)) + } else { + Text(mark, style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.Bold, color = tint, maxLines = 1) + } } } } diff --git a/app/src/main/res/drawable/ic_bark_logo.png b/app/src/main/res/drawable/ic_bark_logo.png new file mode 100644 index 0000000..eba752a Binary files /dev/null and b/app/src/main/res/drawable/ic_bark_logo.png differ diff --git a/app/src/main/res/drawable/ic_ntfy_logo.png b/app/src/main/res/drawable/ic_ntfy_logo.png new file mode 100644 index 0000000..05c6fd8 Binary files /dev/null and b/app/src/main/res/drawable/ic_ntfy_logo.png differ