mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 08:15:24 +00:00
Add a shared NotificationCountBadge view
Extract the unread notification count capsule from the room list cell into its own view so it can be reused elsewhere. It caps the displayed value at 99+ and comes in a medium size (used by the room list) and a small size.
This commit is contained in:
@@ -407,6 +407,10 @@ extension AccessibilityTests {
|
||||
try await performAccessibilityAudit(named: "NoticeRoomTimelineView_Previews")
|
||||
}
|
||||
|
||||
func testNotificationCountBadge() async throws {
|
||||
try await performAccessibilityAudit(named: "NotificationCountBadge_Previews")
|
||||
}
|
||||
|
||||
func testNotificationPermissionsScreen() async throws {
|
||||
try await performAccessibilityAudit(named: "NotificationPermissionsScreen_Previews")
|
||||
}
|
||||
|
||||
@@ -266,6 +266,7 @@
|
||||
288408E6151D7BD3EBAA073A /* RoomScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = B343C5255FB408DDE853CFDF /* RoomScreenHook.swift */; };
|
||||
28E8C44DD6E39BEB2A1599C8 /* AccessibilityTestsAppCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CABD320DE5566D133890B24 /* AccessibilityTestsAppCoordinator.swift */; };
|
||||
291A3E0EECD496D0FCC2ADAA /* TimelineScrollButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E14E3688FF3532456A656 /* TimelineScrollButton.swift */; };
|
||||
293179E5CE24DDF1FE82A110 /* NotificationCountBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = E124365DC2141340F6F81A72 /* NotificationCountBadge.swift */; };
|
||||
29491EE7AE37E239E839C5A3 /* LocationSharingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */; };
|
||||
2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024F7398C5FC12586FB10E9D /* EffectsScene.swift */; };
|
||||
298F9EC30E918F12AB7F1EE8 /* TypingIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81F0325E252B057FAEEE1B2D /* TypingIndicatorView.swift */; };
|
||||
@@ -3135,6 +3136,7 @@
|
||||
E0FCA0957FAA0E15A9F5579D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Untranslated.stringsdict; sourceTree = "<group>"; };
|
||||
E0FF9CB3EFA753277291F609 /* EncryptionResetScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
E10DA51DBC8C7E1460DBCCBD /* UserProfileListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileListRow.swift; sourceTree = "<group>"; };
|
||||
E124365DC2141340F6F81A72 /* NotificationCountBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCountBadge.swift; sourceTree = "<group>"; };
|
||||
E157152B11E347F735C3FD6E /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = tr; path = tr.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
E1573D28C8A9FB6399D0EEFB /* SecureBackupLogoutConfirmationScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupLogoutConfirmationScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
E1714DD78BFE27ADD40A6F89 /* LinkNewDeviceScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
@@ -4191,6 +4193,7 @@
|
||||
C352359663A0E52BA20761EE /* LoadableImage.swift */,
|
||||
FFECCE59967018204876D0A5 /* LocationMarkerView.swift */,
|
||||
50E31AB0E77BB70E2BC77463 /* MatrixUserShareLink.swift */,
|
||||
E124365DC2141340F6F81A72 /* NotificationCountBadge.swift */,
|
||||
648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */,
|
||||
C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */,
|
||||
95547A6C69606B5282C765D3 /* RemoveItemButton.swift */,
|
||||
@@ -9245,6 +9248,7 @@
|
||||
7F825CBD857D65DC986087BA /* NoticeRoomTimelineView.swift in Sources */,
|
||||
3F70E237CE4C3FAB02FC227F /* NotificationConstants.swift in Sources */,
|
||||
5500904C40D67D131E7E9A26 /* NotificationContentBuilder.swift in Sources */,
|
||||
293179E5CE24DDF1FE82A110 /* NotificationCountBadge.swift in Sources */,
|
||||
28426806399E3659BEBC5918 /* NotificationHandler.swift in Sources */,
|
||||
E6A2F6E4795C1054025AACFF /* NotificationItemProxy.swift in Sources */,
|
||||
9312F5A17AE59A9E910C51D6 /* NotificationItemProxyMock.swift in Sources */,
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright 2026 Element Creations Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
/// A capsule showing an unread notification count, capped at 99+.
|
||||
struct NotificationCountBadge: View {
|
||||
enum Size {
|
||||
case small
|
||||
case medium
|
||||
}
|
||||
|
||||
let count: Int
|
||||
var size: Size = .medium
|
||||
|
||||
var body: some View {
|
||||
Text(count > 99 ? "99+" : "\(count)")
|
||||
.font(size == .small ? .compound.bodyXSSemibold : .compound.bodySMSemibold)
|
||||
.foregroundStyle(.compound.textOnSolidPrimary)
|
||||
.lineLimit(1)
|
||||
.padding(.horizontal, size == .small ? 4 : 6)
|
||||
.frame(minWidth: size == .small ? 16 : 20, minHeight: size == .small ? 16 : 20)
|
||||
.background(.compound.iconAccentPrimary, in: .capsule)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct NotificationCountBadge_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
VStack(spacing: 8) {
|
||||
ForEach([Size.small, .medium], id: \.self) { size in
|
||||
HStack(spacing: 8) {
|
||||
NotificationCountBadge(count: 1, size: size)
|
||||
NotificationCountBadge(count: 42, size: size)
|
||||
NotificationCountBadge(count: 100, size: size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private typealias Size = NotificationCountBadge.Size
|
||||
}
|
||||
@@ -106,6 +106,7 @@ enum TestablePreviewsDictionary {
|
||||
"ModerationAndSafetySettingsScreen_Previews" : ModerationAndSafetySettingsScreen_Previews.self,
|
||||
"MultiAccountAnnouncementView_Previews" : MultiAccountAnnouncementView_Previews.self,
|
||||
"NoticeRoomTimelineView_Previews" : NoticeRoomTimelineView_Previews.self,
|
||||
"NotificationCountBadge_Previews" : NotificationCountBadge_Previews.self,
|
||||
"NotificationPermissionsScreen_Previews" : NotificationPermissionsScreen_Previews.self,
|
||||
"NotificationSettingsEditScreenRoomCell_Previews" : NotificationSettingsEditScreenRoomCell_Previews.self,
|
||||
"NotificationSettingsEditScreen_Previews" : NotificationSettingsEditScreen_Previews.self,
|
||||
|
||||
@@ -146,13 +146,7 @@ struct HomeScreenRoomCell: View {
|
||||
|
||||
if room.badges.isDotShown {
|
||||
if room.isHighlighted, room.badges.notificationCount > 0 {
|
||||
Text(formattedNotificationCount)
|
||||
.font(.compound.bodySMSemibold)
|
||||
.foregroundColor(.compound.textOnSolidPrimary)
|
||||
.lineLimit(1)
|
||||
.padding(.horizontal, 6)
|
||||
.frame(minWidth: 20, minHeight: 20)
|
||||
.background(.compound.iconAccentPrimary, in: .capsule)
|
||||
NotificationCountBadge(count: Int(room.badges.notificationCount))
|
||||
.accessibilityLabel(L10n.a11yNotificationsNewMessages)
|
||||
} else {
|
||||
Circle()
|
||||
@@ -170,10 +164,6 @@ struct HomeScreenRoomCell: View {
|
||||
.accessibilityLabel(L10n.a11yNotificationsNewMentions)
|
||||
}
|
||||
|
||||
private var formattedNotificationCount: String {
|
||||
room.badges.notificationCount > 99 ? "99+" : "\(room.badges.notificationCount)"
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var lastMessage: some View {
|
||||
if let displayedLastMessage = room.displayedLastMessage {
|
||||
|
||||
@@ -711,6 +711,13 @@ extension PreviewTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
func notificationCountBadge() async throws {
|
||||
for (index, preview) in NotificationCountBadge_Previews._allPreviews.enumerated() {
|
||||
try await assertSnapshots(matching: preview, step: index)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
func notificationPermissionsScreen() async throws {
|
||||
for (index, preview) in NotificationPermissionsScreen_Previews._allPreviews.enumerated() {
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e1b9fdaf8ac1653153e78faa59162c930af5e5f6d647293ea907840f436f97b8
|
||||
size 73171
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cdd5c07929cc8ac34ba855e4143f2ab1c23bde0c0780acfdf885e50c486733dc
|
||||
size 74808
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:09a997528760f172b9b41994487e309e8958e7dd2404585bc7535a9f0f0b160a
|
||||
size 33306
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c058780bc218c210e7b1b12efd2838f332091103246cdebfb7a2f717dbfb2d9c
|
||||
size 34183
|
||||
Reference in New Issue
Block a user