-
Notifications
You must be signed in to change notification settings - Fork 53
PM-12565: Add settings badges for account setup steps #972
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,80 @@ | ||
// MARK: - SettingsProcessorDelegate | ||
|
||
/// A delegate of `SettingsProcessor` that is notified when the settings tab badge needs to be updated. | ||
/// | ||
@MainActor | ||
protocol SettingsProcessorDelegate: AnyObject { | ||
/// Called when the settings tab badge needs to be updated. | ||
/// | ||
/// - Parameter badgeValue: The value to display in the settings tab badge. | ||
/// | ||
func updateSettingsTabBadge(_ badgeValue: String?) | ||
} | ||
|
||
// MARK: - SettingsProcessor | ||
|
||
/// The processor used to manage state and handle actions for the settings screen. | ||
/// | ||
final class SettingsProcessor: StateProcessor<SettingsState, SettingsAction, Void> { | ||
// MARK: Types | ||
|
||
typealias Services = HasErrorReporter | ||
& HasSettingsRepository | ||
typealias Services = HasConfigService | ||
& HasErrorReporter | ||
& HasStateService | ||
|
||
// MARK: Private Properties | ||
|
||
/// The task used to update the tab's badge count. | ||
private var badgeUpdateTask: Task<Void, Never>? | ||
|
||
/// The `Coordinator` that handles navigation. | ||
private let coordinator: AnyCoordinator<SettingsRoute, SettingsEvent> | ||
|
||
/// A delegate of the processor that is notified when the settings tab badge needs to be updated. | ||
private weak var delegate: SettingsProcessorDelegate? | ||
|
||
/// The services used by this processor. | ||
private var services: Services | ||
|
||
// MARK: Initialization | ||
|
||
/// Creates a new `SettingsProcessor`. | ||
/// | ||
/// - Parameters: | ||
/// - coordinator: The `Coordinator` that handles navigation. | ||
/// - delegate: A delegate of the processor that is notified when the settings tab badge needs | ||
/// to be updated. | ||
/// - services: The services used by the processor. | ||
/// - state: The initial state of the processor. | ||
/// | ||
init( | ||
coordinator: AnyCoordinator<SettingsRoute, SettingsEvent>, | ||
delegate: SettingsProcessorDelegate, | ||
services: Services, | ||
state: SettingsState | ||
) { | ||
self.coordinator = coordinator | ||
self.delegate = delegate | ||
self.services = services | ||
super.init(state: state) | ||
|
||
// Kick off this task in init so that the tab bar badge will be updated immediately when | ||
// the tab bar is shown vs once the user navigates to the settings tab. | ||
badgeUpdateTask = Task { @MainActor [weak self] in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just for my understanding, whats the benefit of storing this task in a variable vs just kicking off the Task in the init? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Storing a reference to the task allows us to cancel it when the processor goes away (e.g. when you switch accounts or logout, etc). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. makes sense, thanks! |
||
guard await self?.services.configService.getFeatureFlag(.nativeCreateAccountFlow) == true else { return } | ||
do { | ||
guard let publisher = try await self?.services.stateService.settingsBadgePublisher() else { return } | ||
for await badgeValue in publisher.values { | ||
self?.delegate?.updateSettingsTabBadge(badgeValue) | ||
} | ||
} catch { | ||
self?.services.errorReporter.log(error: error) | ||
} | ||
} | ||
} | ||
|
||
deinit { | ||
badgeUpdateTask?.cancel() | ||
} | ||
|
||
// MARK: Methods | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 @matt-livefront these methods are currently called in
loginWithMasterPassword
so potentially ifupdateSettingsBadgePublisher
throws thenloginWithMasterPassword
would fail which is not correct IMO. The badge update is a secondary effect but that shouldn't block the flow of logging in.I think the
updateSettingsBadgePublisher
should not throw and just wrap the code in ado...catch
and log any error to theerrorReporter
so it doesn't affect any caller flows.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, great point! I have a fix here: #988.