Skip to content

Conversation

@monicamuyama
Copy link

@monicamuyama monicamuyama commented Aug 21, 2025

Added a share functionality for the analytics

  • Edited the analytics specifics page to include the share button and share functionality for air quality in a location of interest

Summary by CodeRabbit

  • New Features
    • Share the current site’s air quality directly from the Analytics screen via the system share sheet, including a branded image and subject.
  • Style
    • Updated the Analytics header to use a share icon, with refined colors and spacing.
  • Chores
    • Streamlined Android build configuration and manifest related to API keys and flavors.
    • Removed obsolete Android build setup and improved secrets management by excluding sensitive files from version control.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 21, 2025

📝 Walkthrough

Walkthrough

Android build config was simplified by ignoring secrets.properties, commenting out Maps API key logic and product flavors, updating the manifest placeholder, and removing settings.gradle.kts. Flutter app adds a share action in AnalyticsSpecifics, introduces new imports, and updates pubspec with share/image/path_provider dependencies and a new logo asset.

Changes

Cohort / File(s) Summary
Android build/config
src/mobile-v3/android/.gitignore, src/mobile-v3/android/app/build.gradle, src/mobile-v3/android/app/src/main/AndroidManifest.xml, src/mobile-v3/android/settings.gradle.kts
Ignore android/secrets.properties; comment out Google Maps API key retrieval and product flavors; change manifest meta-data value to ${MAPS_API_KEY}; remove settings.gradle.kts (pluginManagement, plugins, include(":app")).
Flutter widget (Analytics)
src/mobile-v3/lib/src/app/dashboard/widgets/analytics_specifics.dart
Add _shareAirQualityData method; replace header close/location with share button; update title color; add imports for sharing, SVG, path provider, services, and dart:io.
Flutter project config
src/mobile-v3/pubspec.yaml
Add dependencies: share_plus, path_provider, image; add asset assets/images/airQo_logo.png; minor whitespace tweak.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Widget as AnalyticsSpecifics
  participant FS as Temp File System
  participant Assets as Flutter Assets
  participant Share as Share Sheet

  User->>Widget: Tap share icon
  activate Widget
  Widget->>Assets: Load AirQo logo (PNG)
  Assets-->>Widget: Byte data (logo)
  Widget->>FS: Write logo to temp file
  FS-->>Widget: File path
  Widget->>Share: Share.shareXFiles(text, subject, file)
  deactivate Widget
  Note over Share,User: System presents native share UI (new interaction)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

A tap to share the air we breathe,
A logo saved, a message sheathe.
Gradle trims its winding ways,
Flavors fade to simpler days.
Keys reshaped, configs align—
One tap, one share, the data shines.

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@monicamuyama
Copy link
Author

@Baalmart @Mozart299 , please review my pr, thanks

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (8)
src/mobile-v3/android/app/src/main/AndroidManifest.xml (1)

11-13: Align comment with Secrets Gradle Plugin usage; placeholder change looks good

You’ve switched the value to ${MAPS_API_KEY}, which is what the Secrets Gradle Plugin expects. The TODO above is now misleading—keys come from secrets.properties, not inline edits.

Apply this edit to clarify:

-        <!-- TODO: Add your Google Maps API key here -->
+        <!-- Google Maps API key is provided by the Secrets Gradle Plugin.
+             Define MAPS_API_KEY in android/secrets.properties (ignored by VCS). -->
src/mobile-v3/pubspec.yaml (2)

23-23: Trim trailing spaces to satisfy linters/CI

YAMLlint flagged trailing spaces on these lines.

-  
+
-  path_provider: '^2.1.1' 
+  path_provider: '^2.1.1'

Also applies to: 36-36


35-37: Sanity-check new dependencies and surface area

  • share_plus and path_provider versions look reasonable. No immediate conflicts with current minSdk (21) or targetSdk (35).
  • The image package was added but isn’t used in analytics_specifics.dart (sharing uses rootBundle + File). If not used elsewhere, consider removing to reduce APK size.

Please run locally:

  • flutter pub outdated
  • rg -n "package:image" -g "!/build/" src/mobile-v3/lib
    If unused, drop it:
-  image: ^4.1.3

Also applies to: 82-82

src/mobile-v3/lib/src/app/dashboard/widgets/analytics_specifics.dart (2)

70-100: Harden share flow: better error handling, stable temp path, and optional richer message

Current flow works, but a few small tweaks will make it sturdier and a bit cleaner:

  • Use a stable filename in the temp dir to avoid unbounded temp files on repeated shares.
  • Prefer debugPrint (or your logger) over print; optionally surface a SnackBar on failure.
  • Catch PlatformException explicitly (common from platform channels).
  • Optional: if you have a canonical site link/deeplink, include siteId so the share feels personal.

Apply:

   void _shareAirQualityData() async {
-    try {
+    try {
       final location = _getLocationDescription(widget.measurement);
-      //final locationId = widget.measurement.siteId ?? '';
-      final deepLink =
-          'https://airqo.net/products/mobile-app';
+      final siteId = widget.measurement.siteDetails?.id;
+      // TODO: replace with a canonical deeplink if available, e.g.,
+      // final deepLink = 'https://airqo.net/analytics?siteId=$siteId';
+      final deepLink = 'https://airqo.net/products/mobile-app';
 
       final shareText = '''
 Check out the Air Quality of $location on the AirQo app!
 👉 $deepLink
 ''';
-      // Load AirQo logo from assets
-      final byteData = await rootBundle.load('assets/images/airQo_logo.png');
+      // Load AirQo logo from assets (registered in pubspec)
+      final byteData = await rootBundle.load('assets/images/airQo_logo.png');
 
-      final tempDir = await getTemporaryDirectory();
-      final logoFile = await File(
-              '${tempDir.path}/airqo_logo_${DateTime.now().millisecondsSinceEpoch}.png')
-          .writeAsBytes(
-        byteData.buffer.asUint8List(),
-      );
+      final tempDir = await getTemporaryDirectory();
+      final logoFile = File('${tempDir.path}/airqo_logo.png');
+      if (!await logoFile.exists()) {
+        await logoFile.writeAsBytes(byteData.buffer.asUint8List());
+      }
 
       // Share with logo and text
       await Share.shareXFiles(
         [XFile(logoFile.path)],
         text: shareText,
         subject: 'Air Quality Update from AirQo',
       );
-    } catch (e) {
-      print("Error sharing data: $e");
+    } on PlatformException catch (e) {
+      debugPrint('Share failed: ${e.message}');
+      if (!mounted) return;
+      ScaffoldMessenger.of(context).showSnackBar(
+        const SnackBar(content: Text('Unable to share right now. Please try again.')),
+      );
+    } catch (e, st) {
+      debugPrint('Error sharing data: $e\n$st');
     }
   }

131-154: Improve accessibility and consider navigation regression from removing “close”

  • Accessibility: wrap the tappable SVG with Tooltip/Semantics for screen readers.
  • UX: the prior close action seems removed; verify there’s still an obvious way to dismiss this sheet/page.

Proposed tweak with a Tooltip:

-                        InkWell(
+                        Tooltip(message: 'Share'),
+                        InkWell(
                           onTap: _shareAirQualityData,
                           borderRadius: BorderRadius.circular(20),
                           child: Container(
                             padding: const EdgeInsets.all(8),
                             child: SvgPicture.asset(
                               "assets/icons/share-icon.svg",

If a close/back affordance was intentionally removed, all good. If not, consider reintroducing it next to the share icon.

src/mobile-v3/android/app/build.gradle (3)

106-123: Product flavors commented out — confirm this won’t break distribution variants

With flavors disabled, dev/prod separation (e.g., different appIdSuffix, keys) is gone. If that’s intentional, all good. If you still need variants, consider reintroducing minimal flavors that only carry manifestPlaceholders or appIdSuffix.


26-41: Dead code: properties loading blocks are now unused

appProperties and secretsProperties are loaded but never referenced after removing manual key wiring. You can drop these for a cleaner script.

-def appProperties = new Properties()
-def appPropertiesFile = rootProject.file('key.properties')
-if (appPropertiesFile.exists()) {
-    appPropertiesFile.withReader('UTF-8') { reader ->
-        appProperties.load(reader)
-    }
-}
-
-def secretsProperties = new Properties()
-def secretsPropertiesFile = rootProject.file('secrets.properties')
-if (secretsPropertiesFile.exists()) {
-    secretsPropertiesFile.withReader('UTF-8') { reader ->
-        secretsProperties.load(reader)
-    }
-}
+// Removed unused appProperties and secretsProperties loaders (keys provided via Secrets Plugin)

50-59: Verify Secrets Plugin and MAPS_API_KEY Resolution

Quick validation shows:

  • The com.google.android.libraries.mapsplatform.secrets-gradle-plugin is applied in app/build.gradle.
  • Your AndroidManifest.xml references the placeholder ${MAPS_API_KEY} as expected.
  • A settings.gradle file exists under src/mobile-v3/android.

Since you’ve removed the manual googleMapApiKey lookups in favor of the Secrets Gradle Plugin, make sure that:

  • Your CI pipelines and every developer’s machine include a secrets.properties (or local.defaults.properties) defining MAPS_API_KEY (and MAPS_API_KEY_DEV if you use a separate dev key).
  • Without these files, the app will compile but crash or misconfigure maps at runtime—silent failures are hard to debug.

Optional: To fail fast on CI and catch missing keys early (without re-adding full flavor logic), you could inject a lightweight check in your Gradle configuration, for example in app/build.gradle before your android { … } block:

// Fail build if MAPS_API_KEY isn’t defined by the Secrets plugin
if (!project.hasProperty('MAPS_API_KEY')) {
    throw new GradleException(
        "Missing MAPS_API_KEY: add it to secrets.properties or local.defaults.properties"
    )
}

This will immediately alert you in CI of a missing key without duplicating your old lookup logic.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0a0c1cf and 895bb93.

⛔ Files ignored due to path filters (2)
  • src/mobile-v3/assets/images/airQo_logo.png is excluded by !**/*.png
  • src/mobile-v3/pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • src/mobile-v3/android/.gitignore (1 hunks)
  • src/mobile-v3/android/app/build.gradle (3 hunks)
  • src/mobile-v3/android/app/src/main/AndroidManifest.xml (1 hunks)
  • src/mobile-v3/android/settings.gradle.kts (0 hunks)
  • src/mobile-v3/lib/src/app/dashboard/widgets/analytics_specifics.dart (3 hunks)
  • src/mobile-v3/pubspec.yaml (4 hunks)
💤 Files with no reviewable changes (1)
  • src/mobile-v3/android/settings.gradle.kts
🧰 Additional context used
🪛 YAMLlint (1.37.1)
src/mobile-v3/pubspec.yaml

[error] 23-23: trailing spaces

(trailing-spaces)


[error] 36-36: trailing spaces

(trailing-spaces)

🔇 Additional comments (3)
src/mobile-v3/android/.gitignore (1)

8-8: No action needed—secrets.properties is already ignored

The git check-ignore output confirms that src/mobile-v3/android/secrets.properties is being ignored by the /android/secrets.properties pattern in src/mobile-v3/.gitignore (line 66), so there’s no risk of accidentally committing API keys. You can safely disregard the original suggestion to adjust the pattern in src/mobile-v3/android/.gitignore.

Likely an incorrect or invalid review comment.

src/mobile-v3/pubspec.yaml (1)

119-119: Asset registration matches usage

assets/images/airQo_logo.png is correctly registered and matches the path used by the sharing code. LGTM.

src/mobile-v3/lib/src/app/dashboard/widgets/analytics_specifics.dart (1)

126-126: Color token change

Changing to AppColors.boldHeadlineColor4 is fine; just confirm this token meets contrast requirements against all supported themes/backgrounds.

@monicamuyama
Copy link
Author

@2phonebabykeem could you review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants