-
Notifications
You must be signed in to change notification settings - Fork 927
PM-28492: Replace Authenticator Toasts with Snackbars #6180
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
Conversation
|
Claude finished @david-livefront's task ββ View job Final Review AssessmentOverall Assessment: APPROVE This PR successfully migrates the Authenticator app from Android Toast to Compose Snackbar pattern, following the established relay pattern from the Password Manager app. The implementation is clean and well-tested. Remaining Recommendations:
Note: Finding 3 was withdrawn after author clarification - ItemSearchScreen correctly only subscribes to ITEM_SAVED since it doesn't navigate to add screens. |
| .onEach(::sendAction) | ||
| .launchIn(viewModelScope) | ||
| snackbarRelayManager | ||
| .getSnackbarDataFlow(SnackbarRelay.IMPORT_SUCCESS) |
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.
π Finding 2: SettingsViewModel subscribes to IMPORT_SUCCESS but doesn't navigate to ImportingScreen
Details
The SettingsViewModel subscribes to SnackbarRelay.IMPORT_SUCCESS to show snackbars (lines 94-98), but the Settings screen doesn't navigate to the Importing screen where imports happen.
The ImportingViewModel sends this relay event when an import succeeds (ImportingViewModel.kt:116), then immediately navigates back. The Settings screen would show this snackbar, but only if the user happens to be on the Settings screen when returning from Import.
This pattern works but seems unusual. Consider whether:
- This is intentional (showing import success when returning to Settings)
- The snackbar should only be shown on the screen where import was initiated (ItemListing)
- Documentation explaining this relay pattern would be helpful
For reference, the Password Manager app has similar patterns in VaultAddEditScreen subscribing to attachment upload relays.
|
|
||
| init { | ||
| snackbarRelayManager | ||
| .getSnackbarDataFlow(relay = SnackbarRelay.ITEM_SAVED) |
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.
π Finding 3: Missing snackbar relay subscription for ITEM_ADDED
Details
The ItemSearchViewModel subscribes to SnackbarRelay.ITEM_SAVED but not to SnackbarRelay.ITEM_ADDED. Since items can be added from other screens (ManualCodeEntry, QR scan), the search screen should also display those snackbars when they navigate back.
Compare with ItemListingViewModel.kt:98-102 which subscribes to both:
snackbarRelayManager
.getSnackbarDataFlow(SnackbarRelay.ITEM_SAVED, SnackbarRelay.ITEM_ADDED)
.map(ItemListingEvent::ShowSnackbar)
.onEach(::sendEvent)
.launchIn(viewModelScope)Consider whether search should also subscribe to ITEM_ADDED, or if this is intentional behavior.
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.
@claude You cannot add an item from the ItemSearchScreen, so there is no benefit to subscribing to that data.
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.
Claude finished @david-livefront's task ββ View job
Response to Clarification
Thank you for the clarification! You're absolutely right - since the ItemSearchScreen doesn't have functionality to navigate to screens where items can be added (like ManualCodeEntryScreen or QR scan), there's no scenario where a user would return to the search screen after adding an item. Therefore, subscribing to SnackbarRelay.ITEM_ADDED would indeed provide no benefit.
The current implementation is correct:
ItemSearchViewModelonly subscribes toITEM_SAVEDbecause users can navigate from search β edit item β save β return to searchItemListingViewModelsubscribes to bothITEM_SAVEDandITEM_ADDEDbecause users can navigate from listing β add/edit screens β return to listing
Finding 3 is withdrawn - the implementation is correct as-is.
| * between producers and consumers of the data. | ||
| */ | ||
| @Serializable | ||
| enum class SnackbarRelay { |
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.
π Finding 4: Consider adding KDoc to SnackbarRelay enum
Details
Per docs/STYLE_AND_BEST_PRACTICES.md:272-273, all public classes should include KDoc documentation. The SnackbarRelay enum is public and would benefit from documentation explaining:
- The purpose of each relay constant
- Which screens produce/consume each relay
- Example usage pattern
Suggested documentation:
/**
* Models a relay key to be mapped to an instance of [BitwardenSnackbarData] being sent
* between producers and consumers of the data.
*/
@Serializable
enum class SnackbarRelay {
/**
* Relays success message when import completes.
* Producer: ImportingViewModel
* Consumer: SettingsViewModel
*/
IMPORT_SUCCESS,
/**
* Relays success message when a new item is added.
* Producer: ManualCodeEntryViewModel, ItemListingViewModel (QR scan)
* Consumer: ItemListingViewModel
*/
ITEM_ADDED,
/**
* Relays success message when an existing item is saved.
* Producer: EditItemViewModel
* Consumer: ItemListingViewModel, ItemSearchViewModel
*/
ITEM_SAVED,
}| @Singleton | ||
| fun provideSnackbarRelayManager( | ||
| dispatcherManager: DispatcherManager, | ||
| ): SnackbarRelayManager<SnackbarRelay> = SnackbarRelayManagerImpl( |
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.
π Finding 5: Missing KDoc for provideSnackbarRelayManager function
Details
Per docs/STYLE_AND_BEST_PRACTICES.md:347-380, public functions should include KDoc documentation. This provider function should document its purpose and parameters.
Suggested documentation:
/**
* Provides a singleton [SnackbarRelayManager] for the Authenticator app to relay
* snackbar messages between ViewModels and screens.
*/
@Provides
@Singleton
fun provideSnackbarRelayManager(
dispatcherManager: DispatcherManager,
): SnackbarRelayManager<SnackbarRelay> = SnackbarRelayManagerImpl(
dispatcherManager = dispatcherManager,
)| .launchIn(viewModelScope) | ||
|
|
||
| snackbarRelayManager | ||
| .getSnackbarDataFlow(SnackbarRelay.ITEM_SAVED, SnackbarRelay.ITEM_ADDED) |
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.
π Exemplary implementation: Correct usage of SnackbarRelayManager pattern
This demonstrates proper usage of the relay pattern:
- Subscribes to multiple relay keys in a single flow
- Maps to event with BackgroundEvent marker
- Uses
onEach(::sendEvent)for clean event emission - Properly scoped with
launchIn(viewModelScope)
This pattern is consistent with the Password Manager app's implementation.
|
|
||
| CreateItemResult.Success -> { | ||
| sendEvent(EditItemEvent.ShowToast(BitwardenString.item_saved.asText())) | ||
| snackbarRelayManager.sendSnackbarData( |
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.
π Correct pattern: Using sendSnackbarData before navigation
The pattern of sending snackbar data via relay manager before emitting NavigateBack event (lines 240-244) is correct. This ensures the destination screen can receive and display the snackbar upon arrival.
| is ItemListingEvent.NavigateToManualAddItem -> onNavigateToManualKeyEntry() | ||
| is ItemListingEvent.ShowToast -> { | ||
| Toast.makeText(context, event.message(resources), Toast.LENGTH_LONG).show() | ||
| is ItemListingEvent.ShowSnackbar -> { |
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.
π Good refactoring: Removed Toast imports and Android framework dependencies
The removal of android.widget.Toast, LocalContext, and related Android framework dependencies from the Screen composables aligns with best practices for keeping UI layer testable and framework-agnostic. Snackbars are now properly integrated with Compose's state management.
|
Great job! No new security vulnerabilities introduced in this pull request |
1c1f757 to
8ed4c8a
Compare
Codecov Reportβ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #6180 +/- ##
==========================================
+ Coverage 85.24% 85.26% +0.01%
==========================================
Files 724 724
Lines 52901 52907 +6
Branches 7687 7681 -6
==========================================
+ Hits 45094 45109 +15
+ Misses 5126 5120 -6
+ Partials 2681 2678 -3 β View full report in Codecov by Sentry. π New features to boost your workflow:
|
|
Thanks @SaintPatrck |

ποΈ Tracking
PM-28492
π Objective
This PR replaces all the toasts in the Authenticator app with Snackbars.
πΈ Screenshots
Screen_recording_20251119_145313.mp4