Unread badges for tabs#145
Conversation
There was a problem hiding this comment.
Pull request overview
Adds unread-count badges to the bottom navigation tabs (Contacts/Channels) and introduces a new Contacts list ordering toggle to keep people (users) at the top, with localization updates to support the new UI label.
Changes:
- Add unread badge rendering to
QuickSwitchBarand wire unread totals fromMeshCoreConnectorinto screens using the bottom navigation. - Add a “users/people first” toggle to the Contacts filter menu and update contacts sorting to partition users before other contact types.
- Add the new localization key + Ukrainian translation, and update
untranslated.jsonplus generated localization outputs.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| untranslated.json | Updates the untranslated-keys list to reflect the new listFilter_usersFirst string. |
| lib/widgets/quick_switch_bar.dart | Adds badge display to Contacts/Channels icons and adds selected icon for Map. |
| lib/widgets/list_filter_widget.dart | Adds “users first” toggle option to the Contacts filter popup menu. |
| lib/screens/map_screen.dart | Passes unread totals into QuickSwitchBar. |
| lib/screens/device_screen.dart | Passes unread totals into QuickSwitchBar from the device hub screen. |
| lib/screens/contacts_screen.dart | Introduces _prioritizePeople and applies people-first ordering + refactors sorting into a helper. |
| lib/screens/channels_screen.dart | Passes unread totals into QuickSwitchBar. |
| lib/connector/meshcore_connector.dart | Splits unread total counting into contacts vs channels for badge usage. |
| lib/l10n/app_en.arb | Adds the new listFilter_usersFirst string. |
| lib/l10n/app_uk.arb | Adds Ukrainian translation for listFilter_usersFirst and updates a few other Ukrainian strings. |
| lib/l10n/app_localizations.dart | Adds the new listFilter_usersFirst abstract getter (generated). |
| lib/l10n/app_localizations_en.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_bg.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_de.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_es.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_fr.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_it.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_nl.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_pl.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_pt.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_ru.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_sk.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_sl.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_sv.dart | Adds listFilter_usersFirst getter (generated). |
| lib/l10n/app_localizations_uk.dart | Adds listFilter_usersFirst getter + Ukrainian string updates (generated). |
| lib/l10n/app_localizations_zh.dart | Adds listFilter_usersFirst getter (generated). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I'll take a look later today. |
Clamp both _cachedContactsUnreadTotal and _cachedChannelsUnreadTotal to >= 0 after decrementing in markContactRead() and markChannelRead(). This prevents the totals from going negative if the cache drifts out-of-sync, which could cause UI badges to display incorrect values.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…hed contacts unread total
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
lib/connector/meshcore_connector.dart:427
- The clamp upper bound here is misleading. Since you're subtracting
previousCountfrom_cachedContactsUnreadTotal, the result will always be less than or equal to_cachedContactsUnreadTotal, making the upper bound unnecessary. Consider usingmax(0, _cachedContactsUnreadTotal - previousCount)instead for clarity. The same applies to line 444 for channels.
_cachedContactsUnreadTotal = (_cachedContactsUnreadTotal - previousCount).clamp(0, _cachedContactsUnreadTotal);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Please resolve above mentioned issues then mark comment resolved, be sure to run dart format .and flutter analyze and resolve all issues(BEFORE COMMIT AND PUSH) as previously mentioned.
Localizations great
I like this filtering feature.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
moved to draft until ready for review |
|
@pioneer are you still planning on working on this? |
|
Yes, sorry, will update it very soon. |
|
when you do, can you split out the contacts first thing, as we have filters for that and may be adding a 'chats' tab in future. |
When contacts are removed in removeContact, _handleContact, or _handleContactAdvert, subtract their unread count from _cachedContactsUnreadTotal immediately so badge counts reflect the true total without waiting for a full reload.
Resolved conflicts by accepting refactored state management from main: - list_filter_widget.dart: Adopt sealed class pattern for filter actions - contacts_screen.dart: Move state to UiViewStateService instead of local setState - device_screen.dart: Accept deletion (consolidated into other screens in main) Main branch includes significant improvements: - TCP and USB transport support - Service-based state management with UiViewStateService - Translation support with message translation buttons - Signal UI consistency improvements - Additional language support (hu, ja, ko) - Comprehensive test coverage - Discovery screen refactoring
|
Removed the "users on top" feature, to keep this PR clean. |
|
I'll test this out |
|
Also removed Ukrainian translations, as it'd be better to have them in a separate PR. |
ya we decided that translations from english can be skipped for submissions to dev then we can translate before release |
|
Just missed the contacts screen, so if you are on contacts the unread badges don't show. only on channels and map. Which makes me think we should refactor that bottom nav bar into a widget at a later date. |
…r the lists; fixed unread indicator wasn't on all screens
|
Fixed the contacts stuff, and I thought the total unread for all chats/channels be messy, so replaced it with just a red dot. Checked from my side, so waiting for feedback. |
|
looks better, I agree. just going to test again on linux and then read over it all |
446564
left a comment
There was a problem hiding this comment.
lgtm, we can always make use of the actual count later or use it in other places. tested on android and linux.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d3c7d8e43a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| final allChannels = _channels.isNotEmpty ? _channels : _cachedChannels; | ||
| _cachedChannelsUnreadTotal = allChannels.fold( |
There was a problem hiding this comment.
Recompute unread total from current channel sync result
_recalculateCachedChannelsUnreadTotal falls back to _cachedChannels whenever _channels is empty, but _cleanupChannelSync(completed: true) now invokes this before _completeChannelSync replaces _cachedChannels with the newly synced list. If a sync result contains no non-empty channels (so _channels is empty), the total is computed from stale pre-sync cache data and the Channels tab badge can remain non-zero even after channels were cleared.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Codex couldn't complete this request. Try again later.
There was a problem hiding this comment.
Bottom tabs (Contacts, Channels) didn't show whether there are new messages in channels or in direct messages. Now, when any channel has a new message, the Channels tab receives a red dot unread badge. Same for Contacts.