feat: show blog name and site icon in Feed top bar

Replace account name with blog title from SiteMetadataCache in the Feed
TopAppBar. Show site icon (24dp, circular) before the title. Truncate
blog name to 20 characters with ellipsis. Falls back to account name
or "Swoosh" if no cached site data exists.
This commit is contained in:
Paweł Orzech 2026-03-20 00:32:24 +01:00
parent 471fea6183
commit 0679b18b8e

View file

@ -81,6 +81,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.swoosh.microblog.data.CredentialsManager import com.swoosh.microblog.data.CredentialsManager
import com.swoosh.microblog.data.ShareUtils import com.swoosh.microblog.data.ShareUtils
import com.swoosh.microblog.data.SiteMetadataCache
import com.swoosh.microblog.data.model.FeedPost import com.swoosh.microblog.data.model.FeedPost
import com.swoosh.microblog.data.model.GhostAccount import com.swoosh.microblog.data.model.GhostAccount
import com.swoosh.microblog.data.model.PostFilter import com.swoosh.microblog.data.model.PostFilter
@ -113,6 +114,10 @@ fun FeedScreen(
val context = LocalContext.current val context = LocalContext.current
val snackbarHostState = remember { SnackbarHostState() } val snackbarHostState = remember { SnackbarHostState() }
val baseUrl = remember { CredentialsManager(context).ghostUrl } val baseUrl = remember { CredentialsManager(context).ghostUrl }
val siteMetadataCache = remember { SiteMetadataCache(context) }
val siteData = remember(activeAccount?.id) {
activeAccount?.let { siteMetadataCache.get(it.id) }
}
// Track which post is pending delete confirmation // Track which post is pending delete confirmation
var postPendingDelete by remember { mutableStateOf<FeedPost?>(null) } var postPendingDelete by remember { mutableStateOf<FeedPost?>(null) }
@ -201,8 +206,19 @@ fun FeedScreen(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable { showAccountSwitcher = true } modifier = Modifier.clickable { showAccountSwitcher = true }
) { ) {
// Account color indicator // Site icon or account avatar
if (activeAccount != null) { val siteIconUrl = siteData?.icon ?: siteData?.logo
if (siteIconUrl != null) {
AsyncImage(
model = siteIconUrl,
contentDescription = "Site icon",
modifier = Modifier
.size(24.dp)
.clip(CircleShape),
contentScale = ContentScale.Crop
)
Spacer(modifier = Modifier.width(8.dp))
} else if (activeAccount != null) {
AccountAvatar( AccountAvatar(
account = activeAccount!!, account = activeAccount!!,
size = 28 size = 28
@ -211,8 +227,12 @@ fun FeedScreen(
} }
Column { Column {
// Use blog name from site metadata, truncate to ~20 chars
val displayName = siteData?.title?.let {
if (it.length > 20) it.take(20) + "\u2026" else it
} ?: activeAccount?.name ?: "Swoosh"
Text( Text(
text = activeAccount?.name ?: "Swoosh", text = displayName,
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis