From 6d8cf09d9eaa268abdd61bc779fa0d140c63ad71 Mon Sep 17 00:00:00 2001 From: M57 <41645758+Hy4ri@users.noreply.github.com> Date: Tue, 4 Aug 2026 18:11:25 +0300 Subject: [PATCH] refactor(chat): remove StickySubagentBar, rely on in-chat todo card (#811) The sticky top bar duplicated the todo tool's in-chat card and depended on the broken state.todos gate. The bubble (TodoTaskCard) already renders todos from tool message content, so the bar is redundant. Subagent state remains available via the in-chat inspection sheet. Co-authored-by: M57 --- .../m57/hermescontrol/ui/chat/ChatScreen.kt | 10 -- .../ui/chat/components/StickySubagentBar.kt | 150 ------------------ 2 files changed, 160 deletions(-) delete mode 100644 app/src/main/java/com/m57/hermescontrol/ui/chat/components/StickySubagentBar.kt diff --git a/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatScreen.kt index 41cdfd03..9e4397cb 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatScreen.kt @@ -85,7 +85,6 @@ import com.m57.hermescontrol.ui.chat.components.ContextUsageChip import com.m57.hermescontrol.ui.chat.components.ReactionHeartsOverlay import com.m57.hermescontrol.ui.chat.components.ReloginDialog import com.m57.hermescontrol.ui.chat.components.SearchBarRow -import com.m57.hermescontrol.ui.chat.components.StickySubagentBar import com.m57.hermescontrol.ui.chat.components.SubagentInspectionSheet import com.m57.hermescontrol.ui.chat.components.rememberChatScrollController import com.m57.hermescontrol.ui.chat.components.tailContentKey @@ -478,15 +477,6 @@ fun ChatScreen( } } - StickySubagentBar( - indicators = state.subagentIndicators, - todos = state.todos, - onClick = { - showSubagentInspectionSheet = true - scrollController.resumeFollowing() - }, - ) - Box( modifier = Modifier diff --git a/app/src/main/java/com/m57/hermescontrol/ui/chat/components/StickySubagentBar.kt b/app/src/main/java/com/m57/hermescontrol/ui/chat/components/StickySubagentBar.kt deleted file mode 100644 index 02d64385..00000000 --- a/app/src/main/java/com/m57/hermescontrol/ui/chat/components/StickySubagentBar.kt +++ /dev/null @@ -1,150 +0,0 @@ -package com.m57.hermescontrol.ui.chat.components - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.expandVertically -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.shrinkVertically -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ChevronRight -import androidx.compose.material.icons.filled.ElectricBolt -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.platform.testTag -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.m57.hermescontrol.ui.chat.SubagentIndicator -import com.m57.hermescontrol.ui.chat.TodoItem - -/** - * Compact sticky progress indicator displayed below the top app bar - * when background subagents or agent todos are in progress. - */ -@Composable -fun StickySubagentBar( - indicators: List = emptyList(), - todos: List = emptyList(), - onClick: () -> Unit, - modifier: Modifier = Modifier, -) { - val activeSubagents = indicators.count { it.isRunning } - val activeTodos = todos.count { it.isInProgress } - val isVisible = activeSubagents > 0 || activeTodos > 0 - - AnimatedVisibility( - visible = isVisible, - enter = fadeIn() + expandVertically(), - exit = fadeOut() + shrinkVertically(), - modifier = modifier, - ) { - Surface( - modifier = - Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp, vertical = 4.dp) - .clip(RoundedCornerShape(12.dp)) - .clickable(onClick = onClick) - .testTag("sticky_subagent_bar"), - color = MaterialTheme.colorScheme.tertiaryContainer, - shadowElevation = 2.dp, - ) { - Row( - modifier = - Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.weight(1f), - ) { - Icon( - imageVector = Icons.Default.ElectricBolt, - contentDescription = "Active Tasks", - tint = MaterialTheme.colorScheme.primary, - modifier = Modifier.size(18.dp), - ) - - Spacer(modifier = Modifier.width(8.dp)) - - CircularProgressIndicator( - modifier = Modifier.size(12.dp), - strokeWidth = 2.dp, - color = MaterialTheme.colorScheme.onTertiaryContainer, - ) - - Spacer(modifier = Modifier.width(8.dp)) - - val labelText = - when { - activeSubagents > 0 && activeTodos > 0 -> { - "$activeSubagents Subagents · $activeTodos Task Active" - } - activeSubagents > 0 -> { - val activeSub = indicators.firstOrNull { it.isRunning } - val goalText = activeSub?.goal?.takeIf { it.isNotBlank() } - val countStr = - if (activeSubagents == 1) { - "1 Subagent Active" - } else { - "$activeSubagents Subagents Active" - } - if (goalText != null) "$countStr · $goalText" else countStr - } - else -> { - val activeTodo = todos.firstOrNull { it.isInProgress } - val todoText = activeTodo?.content?.takeIf { it.isNotBlank() } - if (todoText != null) "Task In Progress: $todoText" else "1 Task In Progress" - } - } - - Text( - text = labelText, - style = MaterialTheme.typography.labelMedium, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onTertiaryContainer, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } - - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text = "Inspect", - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.primary, - fontSize = 11.sp, - ) - Icon( - imageVector = Icons.Default.ChevronRight, - contentDescription = "Inspect", - tint = MaterialTheme.colorScheme.primary, - modifier = Modifier.size(16.dp), - ) - } - } - } - } -}