Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a new feature that visually enhances app categorization by displaying emojis next to category names. Users can enable or disable this feature through a new setting. The visual design of app cards has been updated to accommodate these emojis, moving from gradient backgrounds to a more streamlined solid color and border presentation. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (31)
📝 WalkthroughWalkthroughA new category emoji feature is introduced, replacing category-color gradient rendering with emoji-based visual indicators. The implementation includes a settings toggle, emoji utility for category-to-emoji mapping, updated app tile rendering, and category header styling with conditional emoji display. Changes
Sequence DiagramsequenceDiagram
actor User
participant SettingsUI as Settings UI
participant SettingsProvider
participant AppsPage
participant CategoryEmojis
User->>SettingsUI: Toggle "Show category emojis"
SettingsUI->>SettingsProvider: set showCategoryEmojis(true)
SettingsProvider->>SettingsProvider: Save preference & notifyListeners()
AppsPage->>AppsPage: Rebuild on notification
AppsPage->>SettingsProvider: Check showCategoryEmojis
alt showCategoryEmojis enabled
AppsPage->>CategoryEmojis: getEmojiForCategory(category)
CategoryEmojis->>CategoryEmojis: Exact/partial match or default
CategoryEmojis-->>AppsPage: Return emoji
AppsPage->>AppsPage: Render emoji overlay on app tiles
AppsPage->>AppsPage: Prefix category headers with emoji
else disabled
AppsPage->>AppsPage: Show tiles without emojis
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces a nice feature to display emojis for app categories. The implementation is mostly solid, with changes across the UI, settings, and a new utility for emoji mapping. I've identified a few areas for improvement:
- In
category_emojis.dart, the partial matching logic can be made more robust and deterministic. - There's some unused code in
settings_provider.dartthat can be cleaned up. - In
apps.dart, there's a redundant provider call that should be removed to follow best practices.
My detailed comments are below. Addressing these points will improve the code's correctness and maintainability.
| void setCategoryEmojis(Map<String, String> emojis, {AppsProvider? appsProvider}) { | ||
| if (appsProvider != null) { | ||
| List<App> changedApps = appsProvider | ||
| .getAppValues() | ||
| .map((a) { | ||
| var n1 = a.app.categories.length; | ||
| a.app.categories.removeWhere((c) => !emojis.keys.contains(c)); | ||
| return n1 > a.app.categories.length ? a.app : null; | ||
| }) | ||
| .where((element) => element != null) | ||
| .map((e) => e as App) | ||
| .toList(); | ||
| if (changedApps.isNotEmpty) { | ||
| appsProvider.saveApps(changedApps); | ||
| } | ||
| } | ||
| prefs?.setString('categoryEmojis', jsonEncode(emojis)); | ||
| notifyListeners(); | ||
| } | ||
|
|
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
lib/utils/category_emojis.dart (2)
128-142: Performance:sortedKeysis recomputed on every lookup.For apps with many categories, this creates a new sorted list on each
getEmojiForCategorycall. Consider caching the sorted keys as a static field.⚡ Cache sorted keys for better performance
+ static final List<String> _sortedKeys = _emojiMap.keys.toList() + ..sort((a, b) => b.length.compareTo(a.length)); + static String getEmojiForCategory(String category) { // Try exact match first String? emoji = _emojiMap[category.toLowerCase()]; if (emoji != null) return emoji; // Try partial match - final sortedKeys = _emojiMap.keys.toList(); - sortedKeys.sort((a, b) => b.length.compareTo(a.length)); - for (final key in sortedKeys) { + for (final key in _sortedKeys) { if (category.toLowerCase().contains(key)) return _emojiMap[key]!; } // Return default emoji return _emojiMap['default']!; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/utils/category_emojis.dart` around lines 128 - 142, getEmojiForCategory currently rebuilds and sorts the key list on every call (the local variable sortedKeys); to fix, add a cached static List<String> (e.g. _sortedEmojiKeys or _cachedSortedKeysByLength) computed once from _emojiMap.keys (lowercased) and sorted by descending length, then update getEmojiForCategory to use that cached list instead of recomputing sortedKeys; keep the exact matching on _emojiMap[category.toLowerCase()] and the loop that checks category.toLowerCase().contains(key) but iterate over the new cached static list and fall back to _emojiMap['default'] as before.
1-4: Consider usingMapinstead ofHashMap.
HashMapfromdart:collectionprovides no benefit here since:
- Regular Dart
Mapliterals already use hash-based implementation- The iteration order concern is moot since you sort keys anyway in partial matching
♻️ Simplify to regular Map
-import 'dart:collection'; - class CategoryEmojis { - static final HashMap<String, String> _emojiMap = HashMap.from({ + static final Map<String, String> _emojiMap = { // Social & Communication 'social': '💬', // ... rest of entries ... 'default': '📱', - }); + };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/utils/category_emojis.dart` around lines 1 - 4, The _emojiMap currently uses HashMap from dart:collection even though a plain Map is sufficient; replace HashMap<String, String> with Map<String, String> (or use a const/Map literal) for _emojiMap in class CategoryEmojis, update the initialization to Map.from({...}) or a direct map literal, and remove the unused dart:collection import to simplify the code and keep identical behavior (keys still sorted later for partial matching).lib/pages/apps.dart (3)
760-775: Emoji overlay may have accessibility concerns.The emoji overlay uses a hardcoded
Colors.black.withOpacity(0.7)background which doesn't adapt to theme changes. Consider using theme-aware colors for better consistency and accessibility:🎨 Use theme-aware background
decoration: BoxDecoration( - color: Colors.black.withOpacity(0.7), + color: Theme.of(context).colorScheme.surfaceContainerHighest.withValues(alpha: 0.9), borderRadius: BorderRadius.circular(8), ),Also applies to: 1004-1020
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/pages/apps.dart` around lines 760 - 775, Replace the hardcoded background color in the emoji overlay with a theme-aware color: where the Positioned/Container currently uses Colors.black.withOpacity(0.7), read ThemeData (e.g., Theme.of(context).colorScheme.surface or background plus an opacity) and apply that with appropriate opacity and an accessible contrast (consider using Theme.of(context).colorScheme.onSurface for text color or switch to a darker/lighter overlay based on Theme.of(context).brightness); update the Container decoration and Text style references around categoryEmojis and settingsProvider.showCategoryEmojis to use these theme-based colors so the overlay adapts to light/dark themes and maintains contrast.
1044-1052: RedundantsettingsProviderlookup viacontext.read.Line 1045 creates a new
settingsProvidervariable usingcontext.read<SettingsProvider>(), butsettingsProvideris already available from thebuildmethod scope (line 217). This creates unnecessary overhead and shadows the existing variable.♻️ Remove redundant provider lookup
capFirstChar(String str) => str[0].toUpperCase() + str.substring(1); - final settingsProvider = context.read<SettingsProvider>(); final categoryName = listedCategories[index] ?? tr('noCategory'); String displayText = capFirstChar(categoryName); if (settingsProvider.showCategoryEmojis && listedCategories[index] != null) { final emoji = CategoryEmojis.getEmojiForCategory(listedCategories[index]!); displayText = '$emoji $displayText'; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/pages/apps.dart` around lines 1044 - 1052, The code redundantly calls context.read<SettingsProvider>() into a local settingsProvider at the widget item level while an instance named settingsProvider already exists in the outer build scope; remove the local lookup (the variable on the line creating settingsProvider in this diff) and update the block that uses it (the if that checks showCategoryEmojis and the emoji lookup via CategoryEmojis.getEmojiForCategory) to use the existing outer settingsProvider variable instead so there is no shadowing or extra provider lookup.
656-657: Replace deprecatedwithOpacity()withwithValues(alpha:).
Color.withOpacity()is deprecated in Flutter 3.27.0+. Update the outline border colors at lines 656 and 797 to usewithValues(alpha:)instead.♻️ Update to non-deprecated API
border: Border.all( - color: Theme.of(context).colorScheme.outline.withOpacity(0.2), + color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.2), ),Apply at lines 656 and 797.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/pages/apps.dart` around lines 656 - 657, Replace uses of Theme.of(context).colorScheme.outline.withOpacity(...) with the non-deprecated API by calling withValues(alpha: ...) on the same Theme.of(context).colorScheme.outline color; compute the alpha as the 0–255 integer equivalent of the previous opacity (e.g. opacity * 255 rounded) so the visual opacity is preserved, and update both occurrences that call .withOpacity (the ones operating on Theme.of(context).colorScheme.outline).lib/providers/settings_provider.dart (1)
271-272: Potential exception on malformed JSON.If the stored
categoryEmojispreference contains malformed JSON,jsonDecodewill throw aFormatException. Consider wrapping in a try-catch with fallback to empty map, consistent with defensive practices.🛡️ Proposed defensive handling
Map<String, String> get categoryEmojis => - Map<String, String>.from(jsonDecode(prefs?.getString('categoryEmojis') ?? '{}')); + () { + try { + return Map<String, String>.from(jsonDecode(prefs?.getString('categoryEmojis') ?? '{}')); + } catch (e) { + return <String, String>{}; + } + }();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/providers/settings_provider.dart` around lines 271 - 272, The getter Map<String, String> get categoryEmojis currently calls jsonDecode directly and can throw a FormatException on malformed stored JSON; wrap the jsonDecode call in a try-catch inside categoryEmojis, return an empty Map<String, String> as a safe fallback on any exception, and optionally validate the decoded value is a Map before casting to avoid type errors (log the exception if you have a logger).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@assets/translations/en.json`:
- Line 250: The new translation key "showCategoryEmojis" has been added to
en.json but is missing from many other locale files; update each listed locale
(e.g., vi.json, zh.json, tr.json, pt.json, zh-Hant-TW.json, uk.json, ru.json,
sv.json, pl.json, pt-BR.json, nl.json, ko.json, ja.json, ml.json, id.json,
it.json, he.json, gl.json, fr.json, fa.json, et.json, hu.json, es.json, de.json,
cs.json, da.json, en-EO.json, ca.json, ar.json, bs.json) by adding the
"showCategoryEmojis" key with an appropriate translated string matching the
style/tone of that locale; ensure the key name is identical
("showCategoryEmojis"), insert it in the same JSON object structure as other
keys, validate JSON syntax after edit, and keep translations consistent with the
English source in en.json.
In `@lib/pages/apps.dart`:
- Around line 1004-1020: The emoji overlay Positioned block that checks
categoryEmojis.isNotEmpty && settingsProvider.showCategoryEmojis is currently
placed inside the inner Stack/InkWell (rendering it tappable); move that
Positioned widget out of the inner Stack and place it as a sibling inside the
outer Stack (the parent Stack that wraps the grid tile) so it is rendered above
the tile but outside the InkWell, preserving the same Container/decoration/Text
content and conditional check to keep visual behavior identical while preventing
emoji taps from triggering navigation.
In `@lib/providers/settings_provider.dart`:
- Around line 274-292: The setCategoryEmojis method is incorrectly removing
categories from App instances when an emoji map lacks certain category keys;
remove the mutation logic so emojis do not control app categories. Specifically,
delete or bypass the block that iterates appsProvider.getAppValues(), the lambda
that calls App.app.categories.removeWhere(...), and the conditional
appsProvider.saveApps(changedApps) call; instead just persist the emoji map via
prefs.setString('categoryEmojis', jsonEncode(emojis)) and call notifyListeners()
(leave appsProvider parameter accepted but do not mutate apps).
---
Nitpick comments:
In `@lib/pages/apps.dart`:
- Around line 760-775: Replace the hardcoded background color in the emoji
overlay with a theme-aware color: where the Positioned/Container currently uses
Colors.black.withOpacity(0.7), read ThemeData (e.g.,
Theme.of(context).colorScheme.surface or background plus an opacity) and apply
that with appropriate opacity and an accessible contrast (consider using
Theme.of(context).colorScheme.onSurface for text color or switch to a
darker/lighter overlay based on Theme.of(context).brightness); update the
Container decoration and Text style references around categoryEmojis and
settingsProvider.showCategoryEmojis to use these theme-based colors so the
overlay adapts to light/dark themes and maintains contrast.
- Around line 1044-1052: The code redundantly calls
context.read<SettingsProvider>() into a local settingsProvider at the widget
item level while an instance named settingsProvider already exists in the outer
build scope; remove the local lookup (the variable on the line creating
settingsProvider in this diff) and update the block that uses it (the if that
checks showCategoryEmojis and the emoji lookup via
CategoryEmojis.getEmojiForCategory) to use the existing outer settingsProvider
variable instead so there is no shadowing or extra provider lookup.
- Around line 656-657: Replace uses of
Theme.of(context).colorScheme.outline.withOpacity(...) with the non-deprecated
API by calling withValues(alpha: ...) on the same
Theme.of(context).colorScheme.outline color; compute the alpha as the 0–255
integer equivalent of the previous opacity (e.g. opacity * 255 rounded) so the
visual opacity is preserved, and update both occurrences that call .withOpacity
(the ones operating on Theme.of(context).colorScheme.outline).
In `@lib/providers/settings_provider.dart`:
- Around line 271-272: The getter Map<String, String> get categoryEmojis
currently calls jsonDecode directly and can throw a FormatException on malformed
stored JSON; wrap the jsonDecode call in a try-catch inside categoryEmojis,
return an empty Map<String, String> as a safe fallback on any exception, and
optionally validate the decoded value is a Map before casting to avoid type
errors (log the exception if you have a logger).
In `@lib/utils/category_emojis.dart`:
- Around line 128-142: getEmojiForCategory currently rebuilds and sorts the key
list on every call (the local variable sortedKeys); to fix, add a cached static
List<String> (e.g. _sortedEmojiKeys or _cachedSortedKeysByLength) computed once
from _emojiMap.keys (lowercased) and sorted by descending length, then update
getEmojiForCategory to use that cached list instead of recomputing sortedKeys;
keep the exact matching on _emojiMap[category.toLowerCase()] and the loop that
checks category.toLowerCase().contains(key) but iterate over the new cached
static list and fall back to _emojiMap['default'] as before.
- Around line 1-4: The _emojiMap currently uses HashMap from dart:collection
even though a plain Map is sufficient; replace HashMap<String, String> with
Map<String, String> (or use a const/Map literal) for _emojiMap in class
CategoryEmojis, update the initialization to Map.from({...}) or a direct map
literal, and remove the unused dart:collection import to simplify the code and
keep identical behavior (keys still sorted later for partial matching).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 74a14da4-3e78-4e51-8e7e-ef6d54591b04
📒 Files selected for processing (5)
assets/translations/en.jsonlib/pages/apps.dartlib/pages/settings.dartlib/providers/settings_provider.dartlib/utils/category_emojis.dart
| "versionDetection": "Version detection", | ||
| "standardVersionDetection": "Standard version detection", | ||
| "groupByCategory": "Group by category", | ||
| "showCategoryEmojis": "Show category emojis", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all translation files and check for the new key
fd -e json . assets/translations/ --exec grep -L "showCategoryEmojis" {} \;Repository: omeritzics/Updatium
Length of output: 987
Add showCategoryEmojis translation key to all locale files.
The new showCategoryEmojis key has been added to en.json but is missing from 30+ other locale files: vi.json, zh.json, tr.json, pt.json, zh-Hant-TW.json, uk.json, ru.json, sv.json, pl.json, pt-BR.json, nl.json, ko.json, ja.json, ml.json, id.json, it.json, he.json, gl.json, fr.json, fa.json, et.json, hu.json, es.json, de.json, cs.json, da.json, en-EO.json, ca.json, ar.json, and bs.json. Add this key with an appropriate translation to each file.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@assets/translations/en.json` at line 250, The new translation key
"showCategoryEmojis" has been added to en.json but is missing from many other
locale files; update each listed locale (e.g., vi.json, zh.json, tr.json,
pt.json, zh-Hant-TW.json, uk.json, ru.json, sv.json, pl.json, pt-BR.json,
nl.json, ko.json, ja.json, ml.json, id.json, it.json, he.json, gl.json, fr.json,
fa.json, et.json, hu.json, es.json, de.json, cs.json, da.json, en-EO.json,
ca.json, ar.json, bs.json) by adding the "showCategoryEmojis" key with an
appropriate translated string matching the style/tone of that locale; ensure the
key name is identical ("showCategoryEmojis"), insert it in the same JSON object
structure as other keys, validate JSON syntax after edit, and keep translations
consistent with the English source in en.json.
There was a problem hiding this comment.
🚫 CI Build Failed
The automated build process failed. Please review the build logs and fix the issues before requesting another review.
Next steps:
- Check the build logs for specific errors
- Fix the identified issues
- Push your fixes to this branch
- The CI will automatically re-run
Once the build passes, this review will be dismissed automatically.
Summary by CodeRabbit
Release Notes