Bring back unread count related models

This commit is contained in:
Maciej Gomółka
2026-04-28 11:55:00 +02:00
committed by Maciej Gomółka
parent e5e8adafa3
commit 416ec90201
3 changed files with 41 additions and 22 deletions
@@ -67,7 +67,7 @@ final class MailboxModel: ObservableObject {
}
var unreadFilter: ReadFilter {
state.topBar.isUnreadButtonSelected ? .unread : .all
state.barsState.unreadButtonState.isSelected ? .unread : .all
}
var isOutbox: Bool {
@@ -240,8 +240,8 @@ extension MailboxModel {
}
private func onSelectedItemsChange() {
state.topBar.visibilityMode = selectionMode.selectionState.hasItems ? .selectionMode : .regular
state.topBar.selectAll = selectAllState
state.barsState.visibilityMode = selectionMode.selectionState.hasItems ? .selectionMode : .regular
state.barsState.selectAll = selectAllState
updateMailboxTitle()
updateSelectionStateInDataSource()
}
@@ -285,8 +285,6 @@ extension MailboxModel {
guard let userSession = dependencies.appContext.sessionState.userSession else { return }
do {
updateMailboxTitle()
// FIXME: - Implement new unread count
// state.topBar.unreadCount = .unknown
unreadCountLiveQuery = nil
// These disconnects will prevent unrequested scroller callbacks
@@ -297,7 +295,7 @@ extension MailboxModel {
conversationScroller?.terminate()
paginatedDataSource.resetToInitialState()
state.topBar = .init()
state.barsState = .init()
let mailbox =
selectedMailbox.isInbox
@@ -329,7 +327,9 @@ extension MailboxModel {
unreadCountLiveQuery = UnreadItemsCountLiveQuery(mailbox: mailbox) { [weak self] unreadCount in
AppLogger.log(message: "unread count callback: \(unreadCount)", category: .mailbox)
// FIXME: - Implement new unread count
await MainActor.run {
self?.state.barsState.unreadButtonState.counterState = .known(unreadCount: unreadCount)
}
}
await unreadCountLiveQuery?.setUpLiveQuery()
try await setUpSpamTrashToggleVisibility()
@@ -350,11 +350,11 @@ extension MailboxModel {
let spamTrashToggleState: SpamTrashToggleState
if supportsIncludeFilter {
spamTrashToggleState = .visible(isSelected: state.topBar.spamTrashToggleState.isSelected)
spamTrashToggleState = .visible(isSelected: state.barsState.spamTrashToggleState.isSelected)
} else {
spamTrashToggleState = .hidden
}
state.topBar.spamTrashToggleState = spamTrashToggleState
state.barsState.spamTrashToggleState = spamTrashToggleState
}
private func conversationScrollerHasMore() async -> Bool {
@@ -486,7 +486,7 @@ extension MailboxModel {
guard
let systemFolder = selectedMailbox.systemFolder,
[SystemLabel.allMail, .almostAllMail].contains(systemFolder),
case let systemLabel = state.topBar.spamTrashToggleState.systemLabel,
case let systemLabel = state.barsState.spamTrashToggleState.systemLabel,
let userSession = dependencies.appContext.sessionState.userSession,
let labelId = try? await resolveSystemLabelId(ctx: userSession, label: systemLabel).get()
else {
@@ -593,7 +593,7 @@ extension MailboxModel {
}
func onIncludeSpamTrashFilterChange() {
let includeSpamTrash = state.topBar.spamTrashToggleState.includeSpamTrash
let includeSpamTrash = state.barsState.spamTrashToggleState.includeSpamTrash
if viewMode == .conversations {
_ = conversationScroller?.changeInclude(include: includeSpamTrash)
} else {
@@ -821,7 +821,7 @@ extension MailboxModel {
extension MailboxModel {
struct State {
var mailboxTitle: LocalizedStringResource = "".notLocalized.stringResource
var topBar: TopBarState = .init()
var barsState: MailboxBarsState = .init()
// Navigation properties
var attachmentPresented: AttachmentViewConfig?
@@ -850,3 +850,22 @@ extension MailboxItemCellUIModel {
.init(id: id, isRead: isRead, isStarred: isStarred)
}
}
struct UnreadButtonState: Equatable {
var isSelected: Bool
var counterState: UnreadCounterState
}
enum UnreadCounterState: Equatable {
case known(unreadCount: UInt64)
case unknown
var string: String {
switch self {
case .known(let unreadCount):
UnreadCountFormatter.string(count: unreadCount, maxCount: 99)
case .unknown:
"-".notLocalized
}
}
}
@@ -21,7 +21,7 @@ import ProtonUIFoundations
import SwiftUI
import proton_app_uniffi
extension TopBarState {
extension MailboxBarsState {
var topBarState: MailboxTopBarState? {
switch visibilityMode {
case .regular:
@@ -59,18 +59,18 @@ struct MailboxListView: View {
.modify { view in
if #available(iOS 26, *) {
view
.mailboxTopSafeAreaBar(state: model.state.topBar.topBarState, onEvent: handleTopBarEvent)
.mailboxTopSafeAreaBar(state: model.state.barsState.topBarState, onEvent: handleTopBarEvent)
}
}
}
.onChange(of: model.state.topBar.isUnreadButtonSelected) { model.onUnreadFilterChange() }
.onChange(of: model.state.topBar.spamTrashToggleState) { model.onIncludeSpamTrashFilterChange() }
.onChange(of: model.state.barsState.unreadButtonState.isSelected) { model.onUnreadFilterChange() }
.onChange(of: model.state.barsState.spamTrashToggleState) { model.onIncludeSpamTrashFilterChange() }
}
private func handleTopBarEvent(_ event: MailboxTopBarEvent) {
switch event {
case .spamTrashToggleTapped:
model.state.topBar.spamTrashToggleState = model.state.topBar.spamTrashToggleState.toggled()
model.state.barsState.spamTrashToggleState = model.state.barsState.spamTrashToggleState.toggled()
case .selectAllTapped:
model.onSelectAllTapped()
}
@@ -122,7 +122,7 @@ extension MailboxListView {
emptyView: {
NoResultsView(
variant: model.selectedMailbox.emptyScreenVariant(
isUnreadFilterOn: model.state.topBar.isUnreadButtonSelected
isUnreadFilterOn: model.state.barsState.unreadButtonState.isSelected
))
},
emptyFolderBanner: $model.emptyFolderBanner,
@@ -139,7 +139,7 @@ extension MailboxListView {
.onChange(of: model.selectedMailbox) { _, _ in
self.isListAtTop = true
}
.onChange(of: model.state.topBar.isUnreadButtonSelected) { _, _ in
.onChange(of: model.state.barsState.unreadButtonState.isSelected) { _, _ in
self.isListAtTop = true
}
.onLoad {
@@ -149,7 +149,7 @@ extension MailboxListView {
@ViewBuilder
private func topBar() -> some View {
if let viewModel = model.state.topBar.topBarState {
if let viewModel = model.state.barsState.topBarState {
MailboxTopBarView(state: viewModel, onEvent: handleTopBarEvent)
.background(DS.Color.Background.norm.shadow(DS.Shadows.raisedBottom, isVisible: !isListAtTop))
.zIndex(1)
@@ -20,9 +20,9 @@ import ProtonUIFoundations
import SwiftUI
import proton_app_uniffi
struct TopBarState: Equatable {
struct MailboxBarsState: Equatable {
var visibilityMode: TopBarVisibilityMode = .regular
var isUnreadButtonSelected: Bool = false
var unreadButtonState: UnreadButtonState = .init(isSelected: false, counterState: .unknown)
var selectAll: SelectAllState = .canSelectMoreItems
var spamTrashToggleState: SpamTrashToggleState = .hidden
}