Add Atlassian Statuspage Outage Integration#174
Conversation
- Added StatuspageService for fetching and managing outage data. - Implemented StatusOutage model to represent outage details. - Created OutageDialog for displaying outage information. - Added OutageBanner widget to show active outages across the app. - Integrated polling mechanism to check for outages every minute. - Updated WearOS screens to handle and display outage information. - Added configuration for Statuspage API in statuspage_config.dart. - Implemented tests for StatusOutage model and its parsing logic.
|
Warning Rate limit exceeded@aadishsamir123 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 56 seconds before requesting another review. ⌛ 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. 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds Atlassian Statuspage integration: new StatuspageService with polling, StatusOutage/IncidentUpdate models, config and global navigator key, phone/web outage banner and fullscreen dialog, WearOS outage screen and header behavior, startup initialization (poll-on-start), Sentry-wrapped error reporting, tests, and an added Changes
Sequence Diagram(s)sequenceDiagram
participant App as App Startup
participant Service as StatuspageService
participant API as Statuspage API
participant Sentry as Sentry
participant UI as UI Layer
App->>Service: startPolling()
activate Service
Service->>Service: immediate fetchCurrentOutage()
Service->>API: GET /incidents or summary.json
alt Unresolved incidents
API-->>Service: incidents JSON
Service->>API: GET /components (affected)
API-->>Service: components JSON
Service->>Service: build StatusOutage, set currentOutage
else No incidents
API-->>Service: summary JSON
Service->>Service: derive indicator -> StatusOutage.none() or predictive
end
alt Fetch error
Service->>Sentry: capture exception + hint
Service->>Service: return StatusOutage.none()
end
Service->>UI: notify via ValueNotifier
UI->>UI: rebuild Banner/Dialog
Note over Service: schedule next poll (1 min)
deactivate Service
sequenceDiagram
participant User as User
participant Banner as OutageBanner / Header
participant Nav as App Navigator (AppNavigation.navigatorKey)
participant Dialog as OutageDialog / WearOutageScreen
participant Service as StatuspageService
Banner->>User: renders when currentOutage.active
User->>Banner: tap
Banner->>Nav: push fullscreen Dialog
activate Dialog
User->>Dialog: tap dismiss/close
Dialog->>Service: markDialogDismissed()
Service->>Service: set session flag
Dialog->>Nav: pop
deactivate Dialog
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Pre-merge checks✅ Passed checks (3 passed)
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.
Actionable comments posted: 9
🧹 Nitpick comments (9)
test/unit/services/statuspage_service_test.dart (1)
4-25: Consider expanding test coverage.The existing tests are well-structured and follow the AAA pattern. However, the test coverage is limited to basic model parsing. Based on learnings, 70%+ coverage is expected for services and 80%+ for models.
Consider adding:
- Edge cases for
StatusOutage.fromJson(missing fields, malformed data)- Tests for
StatuspageService.fetchCurrentOutage()with mocked HTTP responses- Error handling scenarios (network failures, API errors)
Would you like me to generate additional test cases for the StatusOutage model and StatuspageService?
lib/widgets/status/outage_banner.dart (2)
19-26: Consider removing redundant Timer.The
Timer.periodicthat callssetStateevery minute appears redundant. TheValueListenableBuilderon line 36 already rebuilds the widget wheneverStatuspageService.currentOutagechanges. The Timer forces unnecessary rebuilds when there's no data change.If the intent is to refresh relative timestamps or similar, consider a more targeted approach.
🔎 Proposed simplification
class _OutageBannerState extends State<OutageBanner> { late final ValueNotifier<StatusOutage?> _notifier; - Timer? _timer; @override void initState() { super.initState(); _notifier = StatuspageService.currentOutage; - _timer = Timer.periodic(const Duration(minutes: 1), (_) { - if (mounted) setState(() {}); - }); } - @override - void dispose() { - _timer?.cancel(); - super.dispose(); - }
157-175: Consider extracting shared formatting utilities.
_formatComponentsis duplicated inOutageDialog(with slightly different thresholds: 3 vs 4 items). Consider extracting these to a shared utility inStatusOutagemodel or a dedicated formatter class for consistency.lib/screens/status/outage_dialog.dart (1)
157-165: Consider showing local time for better user context.Times are displayed in UTC, which is consistent but may be less intuitive for users. Consider showing local time (with timezone indicator) or adding relative time (e.g., "2 hours ago") for better UX.
lib/main.dart (1)
163-175: Consider SafeArea for the OutageBanner positioning.The banner is positioned at
top: 0, which may cause it to render under the system status bar on devices with notches or cutouts. Consider wrapping it in aSafeAreaor usingMediaQuery.of(context).padding.topto avoid overlap with system UI.🔎 Proposed fix
builder: (context, child) { return Stack( children: [ if (child != null) child, - const Positioned( + Positioned( top: 0, left: 0, right: 0, - child: OutageBanner(), + child: SafeArea( + bottom: false, + child: const OutageBanner(), + ), ), ], ); },lib/wear/screens/wear_outage_screen.dart (2)
7-15: UnusedisPredictiveparameter.The
isPredictivefield is declared but never referenced in the widget's build method. Either remove it if not needed, or implement the intended behavior (e.g., different UI/messaging for predictive outages).🔎 If not needed, remove the parameter
class WearOutageScreen extends StatefulWidget { final StatusOutage outage; - final bool isPredictive; const WearOutageScreen({ super.key, required this.outage, - this.isPredictive = false, });
36-38: Redundant ternary expression.Both branches of the ternary return
Colors.black, making the condition pointless. Simplify to a direct assignment.🔎 Proposed fix
return Scaffold( - backgroundColor: - mode == WearMode.active ? Colors.black : Colors.black, + backgroundColor: Colors.black, body: RotaryScrollbar(lib/services/platform/statuspage_service.dart (2)
101-112: Degraded status usesDateTime.now()forstartedAt.When inferring an outage from the summary indicator (no unresolved incident),
startedAtis set toDateTime.now(). This means each poll will reset the start time rather than preserving when the degradation actually began. Consider caching the first-seen timestamp or leaving it as a sentinel value.
129-138: Silent error handling in_fetchAffectedComponents.The empty
catch (_) {}block at line 136 swallows all errors without logging or Sentry capture. While this is supplementary data, consider at least logging in debug mode for diagnosability.🔎 Proposed fix
static Future<List<String>> _fetchAffectedComponents(Uri summaryUrl) async { try { final resp = await http.get(summaryUrl); if (resp.statusCode == 200) { final data = json.decode(resp.body) as Map<String, dynamic>; return _extractAffectedComponentsFromSummary(data); } - } catch (_) {} + } catch (e) { + if (kDebugMode) { + print('Failed to fetch affected components: $e'); + } + } return const []; }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pubspec.lockis excluded by!**/*.lock
📒 Files selected for processing (14)
.github/copilot-instructions.md.vscode/launch.jsonlib/config/statuspage_config.dartlib/core/navigation_service.dartlib/main.dartlib/models/status_outage.dartlib/screens/status/outage_dialog.dartlib/services/platform/statuspage_service.dartlib/wear/screens/wear_list_groups_screen.dartlib/wear/screens/wear_outage_screen.dartlib/wear/wear_main.dartlib/widgets/status/outage_banner.dartpubspec.yamltest/unit/services/statuspage_service_test.dart
💤 Files with no reviewable changes (1)
- .vscode/launch.json
🧰 Additional context used
📓 Path-based instructions (10)
**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Wrap all service layer errors with Sentry.captureException() including contextual hints via Hint.withMap()
Files:
lib/config/statuspage_config.dartlib/core/navigation_service.dartlib/wear/wear_main.dartlib/widgets/status/outage_banner.dartlib/wear/screens/wear_outage_screen.dartlib/screens/status/outage_dialog.dartlib/services/platform/statuspage_service.dartlib/models/status_outage.darttest/unit/services/statuspage_service_test.dartlib/wear/screens/wear_list_groups_screen.dartlib/main.dart
lib/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
lib/**/*.dart: Use FieldValue.serverTimestamp() for createdAt/updatedAt Firebase timestamp fields
Use StreamBuilder and StreamBuilder for real-time Firebase Firestore sync instead of Provider/ChangeNotifier
Use camelCase for variable names, snake_case for file names, and PascalCase for class names
Use 'completed' field name (not 'checked') and 'addedAt' timestamp (not 'createdAt') for item Firebase fields
Query recycled_items subcollection for deleted items instead of filtering items with deleted field
Files:
lib/config/statuspage_config.dartlib/core/navigation_service.dartlib/wear/wear_main.dartlib/widgets/status/outage_banner.dartlib/wear/screens/wear_outage_screen.dartlib/screens/status/outage_dialog.dartlib/services/platform/statuspage_service.dartlib/models/status_outage.dartlib/wear/screens/wear_list_groups_screen.dartlib/main.dart
lib/wear/wear_main.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use wear_main.dart as the explicit entry point for WearOS flavor builds with --target flag
Files:
lib/wear/wear_main.dart
lib/wear/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use standard CircularProgressIndicator() for loading states in WearOS screens instead of CustomLoadingSpinner()
Files:
lib/wear/wear_main.dartlib/wear/screens/wear_outage_screen.dartlib/wear/screens/wear_list_groups_screen.dart
lib/widgets/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Create reusable components in lib/widgets/ directory, following naming pattern lib/widgets/{component_name}_widget.dart
Files:
lib/widgets/status/outage_banner.dart
lib/screens/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
lib/screens/**/*.dart: Use CustomLoadingSpinner() from /widgets/loading_spinner.dart for phone/web loading indicators
Use SingleTickerProviderStateMixin with AnimationController for animations in screen widgets
Files:
lib/screens/status/outage_dialog.dart
lib/services/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
lib/services/**/*.dart: Implement services as static utility classes without singletons or instance creation
Use Firestore queries and StreamBuilder directly for list/item CRUD operations instead of ListGroupsService
Create service files in lib/services/ directory with business logic and Firebase interactions
Files:
lib/services/platform/statuspage_service.dart
test/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
test/**/*.dart: Write unit tests following the AAA pattern (Arrange → Act → Assert) with descriptive test names
Mock Firebase using test_utils.dart helpers and mockito for external dependencies, avoid real Firestore calls in tests
Files:
test/unit/services/statuspage_service_test.dart
test/unit/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Write unit tests for services, models, and utilities with 70%+ coverage for services, 80%+ for models, and 75%+ for utilities
Files:
test/unit/services/statuspage_service_test.dart
lib/main.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Initialize Sentry with 100% trace/profile sample rate in main.dart for error tracking across the phone app
Files:
lib/main.dart
🧠 Learnings (25)
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/wear/wear_main.dart : Use wear_main.dart as the explicit entry point for WearOS flavor builds with --target flag
Applied to files:
lib/wear/wear_main.dartlib/wear/screens/wear_outage_screen.dartlib/wear/screens/wear_list_groups_screen.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/wear/**/*.dart : Use standard CircularProgressIndicator() for loading states in WearOS screens instead of CustomLoadingSpinner()
Applied to files:
lib/wear/wear_main.dartlib/wear/screens/wear_outage_screen.dartlib/wear/screens/wear_list_groups_screen.dart
📚 Learning: 2025-12-15T14:57:06.412Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.412Z
Learning: Applies to lib/services/connectivity_service.dart : Monitor network state and show offline dialog via ConnectivityService, handle Firestore offline persistence
Applied to files:
lib/wear/wear_main.dartlib/widgets/status/outage_banner.dartlib/screens/status/outage_dialog.dart.github/copilot-instructions.mdlib/services/platform/statuspage_service.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/screens/*.dart : Create full-page UI screens in lib/screens/ directory following the pattern lib/screens/{screen_name}.dart
Applied to files:
lib/wear/wear_main.dartlib/wear/screens/wear_outage_screen.dartlib/screens/status/outage_dialog.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/screens/**/*.dart : Use CustomLoadingSpinner() from /widgets/loading_spinner.dart for phone/web loading indicators
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/screens/**/*.dart : Use SingleTickerProviderStateMixin with AnimationController for animations in screen widgets
Applied to files:
lib/wear/wear_main.dartlib/wear/screens/wear_outage_screen.dartlib/wear/screens/wear_list_groups_screen.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.412Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.412Z
Learning: Applies to lib/screens/user_insights.dart : Implement user-level insights in UserInsightsScreen accessible from home drawer, showing aggregate stats across all user's lists
Applied to files:
lib/wear/wear_main.dartlib/wear/screens/wear_list_groups_screen.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/main.dart : Initialize Sentry with 100% trace/profile sample rate in main.dart for error tracking across the phone app
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to test/widgets/**/*.dart : Write widget tests for screens and reusable components with 60%+ coverage goal, using testWidgets and WidgetTester
Applied to files:
lib/wear/wear_main.dart.github/copilot-instructions.mdlib/main.dart
📚 Learning: 2025-12-15T14:57:06.412Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.412Z
Learning: Applies to lib/services/home_widget_service.dart : Use HomeWidgetService.updateWidget() to sync shopping list data to Android home widget via home_widget package
Applied to files:
lib/wear/wear_main.dartlib/wear/screens/wear_list_groups_screen.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Update copilot-instructions.md with new features, architectural patterns, and important conventions for future AI agent guidance
Applied to files:
.github/copilot-instructions.md
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Separate shared services and models are used across both phone and WearOS flavors despite having separate entry points
Applied to files:
.github/copilot-instructions.md
📚 Learning: 2025-12-15T14:57:06.412Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.412Z
Learning: Applies to lib/services/smart_suggestions_service.dart : Implement on-device ML via TFLite for item suggestions trained from user history, with async training and cached immediate results
Applied to files:
.github/copilot-instructions.md
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to test/unit/**/*.dart : Write unit tests for services, models, and utilities with 70%+ coverage for services, 80%+ for models, and 75%+ for utilities
Applied to files:
.github/copilot-instructions.mdtest/unit/services/statuspage_service_test.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Implement testing alongside code; write tests before merge and ensure flutter test passes locally
Applied to files:
.github/copilot-instructions.md
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to test/**/*.dart : Mock Firebase using test_utils.dart helpers and mockito for external dependencies, avoid real Firestore calls in tests
Applied to files:
.github/copilot-instructions.mdtest/unit/services/statuspage_service_test.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to test/**/*.dart : Write unit tests following the AAA pattern (Arrange → Act → Assert) with descriptive test names
Applied to files:
.github/copilot-instructions.mdtest/unit/services/statuspage_service_test.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Mock Firebase and external dependencies in tests using test_utils.dart helpers and mockito; never make real Firestore calls in automated tests
Applied to files:
.github/copilot-instructions.mdtest/unit/services/statuspage_service_test.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/services/**/*.dart : Implement services as static utility classes without singletons or instance creation
Applied to files:
lib/services/platform/statuspage_service.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/services/**/*.dart : Create service files in lib/services/ directory with business logic and Firebase interactions
Applied to files:
test/unit/services/statuspage_service_test.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.412Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.412Z
Learning: Applies to lib/screens/list_insights.dart : Implement list-level insights in ListInsightsScreen as a navigation tab (index 1 between Items and Options) with donut chart animations
Applied to files:
lib/wear/screens/wear_list_groups_screen.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/services/**/*.dart : Use Firestore queries and StreamBuilder directly for list/item CRUD operations instead of ListGroupsService
Applied to files:
lib/wear/screens/wear_list_groups_screen.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/services/list_groups_service.dart : Use ListGroupsService for group operations (CRUD, reordering, list-group associations), not for direct list/item CRUD
Applied to files:
lib/wear/screens/wear_list_groups_screen.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/widgets/**/*.dart : Create reusable components in lib/widgets/ directory, following naming pattern lib/widgets/{component_name}_widget.dart
Applied to files:
lib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/**/*.dart : Use StreamBuilder<QuerySnapshot> and StreamBuilder<DocumentSnapshot> for real-time Firebase Firestore sync instead of Provider/ChangeNotifier
Applied to files:
lib/main.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Build Phone Flavor
- GitHub Check: Build Web (WASM)
- GitHub Check: Tests & Coverage
- GitHub Check: Build WearOS Flavor
- GitHub Check: Seer Code Review
- GitHub Check: Build WearOS (Debug)
- GitHub Check: Build Web (WASM)
- GitHub Check: Build Phone (Debug)
🔇 Additional comments (13)
lib/core/navigation_service.dart (1)
1-6: LGTM!Clean implementation of a global navigation key for context-free dialog navigation. This is a standard Flutter pattern for showing dialogs from services or other non-widget code.
lib/config/statuspage_config.dart (1)
1-11: LGTM!Well-documented configuration with sensible defaults. The 1-minute polling interval is appropriate for avoiding rate limits while still providing timely outage notifications.
lib/widgets/status/outage_banner.dart (1)
47-58: LGTM with note on null context handling.The null check on
AppNavigation.navigatorKey.currentContextis good defensive coding. The silent no-op when context is null is acceptable since this edge case is rare in practice.lib/wear/screens/wear_list_groups_screen.dart (1)
429-435: LGTM!Clean use of a private extension to add the helper method without cluttering the main class.
lib/screens/status/outage_dialog.dart (3)
6-9: LGTM!Well-structured
StatelessWidgetwith clear constructor and required outage parameter.
218-269: LGTM!Clean implementation of the updates section. Limiting to 5 updates prevents UI overflow, and the icon mapping for different statuses provides good visual cues.
271-291: LGTM!Helper methods are clean and well-implemented. Note:
_formatComponentstruncates at 4 items here vs 3 inOutageBanner—this is reasonable given the dialog has more display space.lib/main.dart (1)
66-67: LGTM! Early polling initialization.Starting the Statuspage polling early in
main()ensures outage detection begins before the UI is fully rendered, which is appropriate for this use case.lib/wear/screens/wear_outage_screen.dart (1)
21-28: LGTM! Proper resource management and dialog dismissal.The
ScrollControlleris correctly disposed, and the close action properly marks the dialog as dismissed before popping the route, ensuring session state is tracked correctly.Also applies to: 136-138
lib/models/status_outage.dart (1)
22-57: LGTM! Well-structured immutable model.The
StatusOutageclass has clear field definitions, sensible defaults, and thenone()factory provides a clean way to represent an inactive/empty state.lib/services/platform/statuspage_service.dart (1)
10-19: LGTM! Well-structured static service with proper Sentry integration.The service follows the static utility class pattern per coding guidelines. Error handling in
_fetchAndUpdateandfetchCurrentOutagecorrectly captures exceptions with Sentry and includes contextual hints. The ValueNotifier pattern forcurrentOutageenables reactive UI updates.Also applies to: 21-30, 37-52
.github/copilot-instructions.md (2)
145-160: LGTM! Comprehensive documentation for the Statuspage integration.The documentation clearly describes the service, config, model, and UI components across phone/web and WearOS. Includes relevant file paths, polling behavior, and error handling expectations. This follows the guideline to update copilot-instructions.md with new features.
436-437: LGTM! Testing responsibilities updated.Appropriately references the location of Statuspage-related unit tests and reminds developers to check coverage.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (3)
lib/wear/wear_main.dart (2)
40-49: LGTM — Error handling properly implemented.The
startPolling()call is now wrapped in try-catch with Sentry error reporting and contextual hints, addressing the previous review concern. This follows the coding guidelines for service layer error wrapping.
128-151: LGTM — Outage check properly handles errors and tracks dismissal.Both previous concerns have been addressed:
- Wrapped in try-catch with Sentry error reporting and contextual hints
- Uses
.then()callback to ensuremarkDialogDismissed()is called when the dialog closes (via button or barrier tap)lib/models/status_outage.dart (1)
13-20: LGTM — Defensive date parsing implemented.The
fromJsonmethod now usesDateTime.tryParse()with a fallback toDateTime.now(), addressing the previous review concern aboutDateTime.parse()throwing on malformed input. This prevents crashes from unexpected API data formats.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
lib/main.dartlib/models/status_outage.dartlib/services/platform/statuspage_service.dartlib/wear/screens/wear_list_groups_screen.dartlib/wear/wear_main.dartpubspec.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
- lib/wear/screens/wear_list_groups_screen.dart
- pubspec.yaml
🧰 Additional context used
📓 Path-based instructions (6)
lib/wear/wear_main.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use wear_main.dart as the explicit entry point for WearOS flavor builds with --target flag
Files:
lib/wear/wear_main.dart
lib/wear/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use standard CircularProgressIndicator() for loading states in WearOS screens instead of CustomLoadingSpinner()
Files:
lib/wear/wear_main.dart
**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Wrap all service layer errors with Sentry.captureException() including contextual hints via Hint.withMap()
Files:
lib/wear/wear_main.dartlib/services/platform/statuspage_service.dartlib/main.dartlib/models/status_outage.dart
lib/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
lib/**/*.dart: Use FieldValue.serverTimestamp() for createdAt/updatedAt Firebase timestamp fields
Use StreamBuilder and StreamBuilder for real-time Firebase Firestore sync instead of Provider/ChangeNotifier
Use camelCase for variable names, snake_case for file names, and PascalCase for class names
Use 'completed' field name (not 'checked') and 'addedAt' timestamp (not 'createdAt') for item Firebase fields
Query recycled_items subcollection for deleted items instead of filtering items with deleted field
Files:
lib/wear/wear_main.dartlib/services/platform/statuspage_service.dartlib/main.dartlib/models/status_outage.dart
lib/services/**/*.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
lib/services/**/*.dart: Implement services as static utility classes without singletons or instance creation
Use Firestore queries and StreamBuilder directly for list/item CRUD operations instead of ListGroupsService
Create service files in lib/services/ directory with business logic and Firebase interactions
Files:
lib/services/platform/statuspage_service.dart
lib/main.dart
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Initialize Sentry with 100% trace/profile sample rate in main.dart for error tracking across the phone app
Files:
lib/main.dart
🧠 Learnings (17)
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/wear/wear_main.dart : Use wear_main.dart as the explicit entry point for WearOS flavor builds with --target flag
Applied to files:
lib/wear/wear_main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/wear/**/*.dart : Use standard CircularProgressIndicator() for loading states in WearOS screens instead of CustomLoadingSpinner()
Applied to files:
lib/wear/wear_main.dart
📚 Learning: 2025-12-15T14:57:06.412Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.412Z
Learning: Applies to lib/services/connectivity_service.dart : Monitor network state and show offline dialog via ConnectivityService, handle Firestore offline persistence
Applied to files:
lib/wear/wear_main.dartlib/services/platform/statuspage_service.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to **/*.dart : Wrap all service layer errors with Sentry.captureException() including contextual hints via Hint.withMap()
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/main.dart : Initialize Sentry with 100% trace/profile sample rate in main.dart for error tracking across the phone app
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/screens/*.dart : Create full-page UI screens in lib/screens/ directory following the pattern lib/screens/{screen_name}.dart
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/screens/**/*.dart : Use CustomLoadingSpinner() from /widgets/loading_spinner.dart for phone/web loading indicators
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/screens/**/*.dart : Use SingleTickerProviderStateMixin with AnimationController for animations in screen widgets
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.412Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.412Z
Learning: Applies to lib/screens/user_insights.dart : Implement user-level insights in UserInsightsScreen accessible from home drawer, showing aggregate stats across all user's lists
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to test/widgets/**/*.dart : Write widget tests for screens and reusable components with 60%+ coverage goal, using testWidgets and WidgetTester
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.412Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.412Z
Learning: Applies to lib/services/home_widget_service.dart : Use HomeWidgetService.updateWidget() to sync shopping list data to Android home widget via home_widget package
Applied to files:
lib/wear/wear_main.dartlib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/services/**/*.dart : Implement services as static utility classes without singletons or instance creation
Applied to files:
lib/services/platform/statuspage_service.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/**/*.dart : Use FieldValue.serverTimestamp() for createdAt/updatedAt Firebase timestamp fields
Applied to files:
lib/services/platform/statuspage_service.dartlib/models/status_outage.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/services/**/*.dart : Create service files in lib/services/ directory with business logic and Firebase interactions
Applied to files:
lib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/widgets/**/*.dart : Create reusable components in lib/widgets/ directory, following naming pattern lib/widgets/{component_name}_widget.dart
Applied to files:
lib/main.dart
📚 Learning: 2025-12-15T14:57:06.411Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.411Z
Learning: Applies to lib/**/*.dart : Use StreamBuilder<QuerySnapshot> and StreamBuilder<DocumentSnapshot> for real-time Firebase Firestore sync instead of Provider/ChangeNotifier
Applied to files:
lib/main.dart
📚 Learning: 2025-12-15T14:57:06.412Z
Learnt from: CR
Repo: ASDev-Official/shopsync PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-15T14:57:06.412Z
Learning: Applies to lib/**/*.dart : Use 'completed' field name (not 'checked') and 'addedAt' timestamp (not 'createdAt') for item Firebase fields
Applied to files:
lib/models/status_outage.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Build WearOS Flavor
- GitHub Check: Build Phone Flavor
- GitHub Check: Tests & Coverage
- GitHub Check: Build Web (WASM)
- GitHub Check: Build WearOS (Debug)
- GitHub Check: Build Phone (Debug)
- GitHub Check: Build Web (WASM)
🔇 Additional comments (6)
lib/main.dart (1)
163-175: LGTM — Global outage banner properly integrated.The
MaterialApp.buildercorrectly overlays theOutageBannerat the top of all screens using aStacklayout. The null check forchildis appropriate.lib/services/platform/statuspage_service.dart (4)
10-19: LGTM — Service structure follows coding guidelines.The service correctly implements static utility class pattern without singletons. The session-based dialog dismissal tracking using a static boolean is appropriate for this use case.
Based on coding guidelines, services should be implemented as static utility classes without singletons or instance creation.
21-35: LGTM — Polling lifecycle properly managed.The polling implementation correctly:
- Performs an immediate fetch before starting periodic polling
- Cancels existing timer before creating a new one to prevent leaks
- Provides cleanup via
stopPolling()
54-146: LGTM — Robust error handling and defensive parsing.This implementation addresses all previous review concerns:
- HTTP requests now include 5-second timeouts (lines 62, 112) to prevent indefinite hangs
- Uses
DateTime.tryParse()(lines 76-77, 79) instead ofDateTime.parse()to handle malformed timestamps- Logs Sentry warnings when date parsing fails (lines 82-91) with contextual hints
- Falls back to
StatusOutage.none()on all error paths
148-173: LGTM — Helper methods use safe fallback pattern.The helper methods correctly:
_fetchAffectedComponents: Returns an empty list on any error, which is a safe default for component listings_extractAffectedComponentsFromSummary: Performs pure data extraction with null-safe operatorsThe empty catch block (line 156) is acceptable here since the method returns a safe fallback value.
lib/models/status_outage.dart (1)
23-58: LGTM — Well-designed data model.The
StatusOutageclass is well-structured:
- All fields properly typed with appropriate nullable/non-nullable distinctions
- The
none()factory provides a clean way to represent "no outage" state- Default values for collections prevent null-related issues
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
… dialog dismissal in outage handling
This pull request introduces a comprehensive Atlassian Statuspage outage integration to the app, enabling real-time outage detection, user notification via dialogs and banners, and robust error handling. It adds new models, services, and UI components for both phone/web and WearOS platforms, and ensures polling is performed efficiently and safely. The integration is reflected in the app’s startup flow, UI overlays, and documentation, with supporting configuration and testing instructions.
Statuspage Outage Integration
StatuspageService), with error reporting to Sentry and session-based dialog tracking. [1] [2]status_outage.dart.statuspage_config.dart).User Interface Enhancements
MaterialApp.builder, and a fullscreen closable outage dialog (OutageDialog) that appears once per app run when an outage is active. [1] [2]AppNavigationinnavigation_service.dart).Documentation and Testing
Other Changes
.vscode/launch.json).Summary by CodeRabbit
New Features
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.