mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-27 15:48:54 +00:00
ui: highlight the chat list filter button while this profile has unread
The unread filter button looked identical whether or not there was anything to filter for, so nothing suggested that switching it on would show something. Tint it with the accent colour while the current profile's unread count is above zero - the same per-profile count the profile picker shows - and give it the pill the active state already draws, as a 12% accent fill behind a 40% accent hairline ring. The three states then read as one progression: grey strokes, accent strokes on a faint pill, solid accent pill when the filter is on. Tinting alone was too easy to miss on 16sp strokes, and adding the pill outline gives the change a shape rather than only a hue. On iOS the ring comes from the SF Symbol variants, so the button steps through line.3.horizontal.decrease, .circle and .circle.fill.
This commit is contained in:
@@ -764,14 +764,23 @@ struct ChatListSearchBar: View {
|
||||
|
||||
private func toggleFilterButton() -> some View {
|
||||
let showUnread = chatTagsModel.activeFilter == .unread
|
||||
let currentUserUnread = m.users.contains { $0.user.activeUser && $0.unreadCount > 0 }
|
||||
let highlight = showUnread || currentUserUnread
|
||||
let symbol = if showUnread {
|
||||
"line.3.horizontal.decrease.circle.fill"
|
||||
} else if currentUserUnread {
|
||||
"line.3.horizontal.decrease.circle"
|
||||
} else {
|
||||
"line.3.horizontal.decrease"
|
||||
}
|
||||
return ZStack {
|
||||
Color.clear
|
||||
.frame(width: 22, height: 22)
|
||||
Image(systemName: showUnread ? "line.3.horizontal.decrease.circle.fill" : "line.3.horizontal.decrease")
|
||||
Image(systemName: symbol)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.foregroundColor(showUnread ? theme.colors.primary : theme.colors.secondary)
|
||||
.frame(width: showUnread ? 22 : 16, height: showUnread ? 22 : 16)
|
||||
.foregroundColor(highlight ? theme.colors.primary : theme.colors.secondary)
|
||||
.frame(width: highlight ? 22 : 16, height: highlight ? 22 : 16)
|
||||
.onTapGesture {
|
||||
if chatTagsModel.activeFilter == .unread {
|
||||
chatTagsModel.activeFilter = nil
|
||||
|
||||
@@ -33,6 +33,7 @@ The toolbar supports two layout modes:
|
||||
- When active, `searchMode = true` hides the navigation bar and shows inline search
|
||||
- Filters chat list in real-time by contact/group name and message content
|
||||
- Detects pasted SimpleX links (`searchShowingSimplexLink`) and offers to connect
|
||||
- Unread filter toggle button at the trailing edge while search is unfocused and the list is non-empty; highlighted while the current profile has unread
|
||||
|
||||
### Chat Filter Tabs (Tags)
|
||||
|
||||
|
||||
+20
-3
@@ -709,6 +709,7 @@ private fun BoxScope.unreadBadge(text: String? = "") {
|
||||
@Composable
|
||||
private fun ToggleFilterEnabledButton() {
|
||||
val showUnread = remember { chatModel.activeChatTagFilter }.value == ActiveFilter.Unread
|
||||
val currentUserUnread = chatModel.users.any { it.user.activeUser && it.unreadCount > 0 }
|
||||
|
||||
IconButton(onClick = {
|
||||
if (showUnread) {
|
||||
@@ -718,14 +719,30 @@ private fun ToggleFilterEnabledButton() {
|
||||
}
|
||||
}) {
|
||||
val sp16 = with(LocalDensity.current) { 16.sp.toDp() }
|
||||
val primary = MaterialTheme.colors.primary
|
||||
val tint = when {
|
||||
showUnread -> MaterialTheme.colors.background
|
||||
currentUserUnread -> primary
|
||||
else -> MaterialTheme.colors.secondary
|
||||
}
|
||||
val fill = when {
|
||||
showUnread -> primary
|
||||
currentUserUnread -> primary.copy(alpha = 0.12f)
|
||||
else -> Color.Unspecified
|
||||
}
|
||||
val stroke = when {
|
||||
showUnread -> primary
|
||||
currentUserUnread -> primary.copy(alpha = 0.4f)
|
||||
else -> Color.Unspecified
|
||||
}
|
||||
Icon(
|
||||
painterResource(MR.images.ic_filter_list),
|
||||
null,
|
||||
tint = if (showUnread) MaterialTheme.colors.background else MaterialTheme.colors.secondary,
|
||||
tint = tint,
|
||||
modifier = Modifier
|
||||
.padding(3.dp)
|
||||
.background(color = if (showUnread) MaterialTheme.colors.primary else Color.Unspecified, shape = RoundedCornerShape(50))
|
||||
.border(width = 1.dp, color = if (showUnread) MaterialTheme.colors.primary else Color.Unspecified, shape = RoundedCornerShape(50))
|
||||
.background(color = fill, shape = RoundedCornerShape(50))
|
||||
.border(width = 1.dp, color = stroke, shape = RoundedCornerShape(50))
|
||||
.padding(3.dp)
|
||||
.size(sp16)
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ The toolbar supports two layout modes controlled by `appPrefs.oneHandUI`:
|
||||
|---|---|
|
||||
| Search icon | Magnifying glass icon at leading edge |
|
||||
| Text field | `SearchTextField` with placeholder "Search or paste SimpleX link" |
|
||||
| Filter button | `ToggleFilterEnabledButton` (filter icon) toggles unread-only filter; shown when search text is empty |
|
||||
| Filter button | `ToggleFilterEnabledButton` (filter icon) toggles unread-only filter, highlighted while the current profile has unread; shown when search text is empty |
|
||||
| Clear button | Appears when text is entered; `BackHandler` clears search on back |
|
||||
|
||||
Behavior:
|
||||
|
||||
Reference in New Issue
Block a user