Skip to content

Conversation

@magweter
Copy link
Owner

@magweter magweter commented Jul 23, 2025

Summary by CodeRabbit

  • New Features

    • Added customizable display texts for various states (available, transitioning, reserved, check-in) and an option to hide meeting titles on displays for Pro users.
    • Introduced a new display customization page with a user-friendly form for Pro subscribers.
    • Added a new brush icon for UI enhancement.
  • Improvements

    • Updated translations for consistency and added a new "meeting" key in all supported languages.
    • Enhanced dashboard and display creation UI with clearer upgrade prompts and tooltips for non-Pro users.
    • Simplified booking action and display settings management for easier customization.
  • Bug Fixes

    • Corrected SQLite database mount path in the upgrade guide.
  • Documentation

    • Clarified Pro plan free trial details in pricing documentation.
  • Chores

    • Updated app version to 1.2.0+8.

@coderabbitai
Copy link

coderabbitai bot commented Jul 23, 2025

Walkthrough

This update introduces customizable display texts and a privacy toggle for meeting titles in both backend and frontend. It adds new fields and methods for display settings, updates API resources, and provides UI for Pro users to edit display messages. Pro-related UI logic is streamlined, and several localization, documentation, and test adjustments are included.

Changes

Files / Areas Change Summary
app/lib/components/action_panel.dart, app/lib/components/calendar_modal.dart Simplified booking method call; added controller and service imports.
app/lib/controllers/dashboard_controller.dart Refactored to use global variables for device/display/settings; added customization logic; updated method signatures.
app/lib/models/display_settings_model.dart Added new fields for customizable texts and privacy toggle; updated (de)serialization.
app/lib/translations/translations.dart Added 'meeting' key to locales; standardized 'check-in' hyphenation.
app/pubspec.yaml Bumped version to 1.2.0+8.
backend/app/Helpers/DisplaySettings.php Added getters/setters for customizable texts and privacy toggle.
backend/app/Http/Controllers/DisplayController.php Removed Pro license check for 'room' feature in store method.
backend/app/Http/Controllers/DisplaySettingsController.php Added customization view/update methods for display settings.
backend/app/Http/Requests/UpdateDisplayCustomizationRequest.php Introduced new form request class for validating customization updates.
backend/app/Http/Resources/API/DisplayResource.php Removed 'display_name' from API response.
backend/app/Http/Resources/API/DisplaySettingsResource.php Added new fields for customizable texts and privacy toggle to API response.
backend/app/Models/Display.php Added convenience accessors for new display settings.
backend/resources/views/components/icons/brush.blade.php Added new SVG brush icon component.
backend/resources/views/pages/dashboard.blade.php Updated Pro banner and button logic; unified upgrade prompts; improved tooltips.
backend/resources/views/pages/displays/create.blade.php Simplified room search method UI; removed Pro-related conditions.
backend/resources/views/pages/displays/customization.blade.php New Blade view for display customization (Pro only).
backend/routes/web.php Added routes for display customization view and update.
backend/tests/Feature/DisplaySettingsApiTest.php Removed assertion for 'display_name' in API test.
docs/PRICING.md, docs/UPGRADE_GUIDE.md Clarified free trial terms; corrected SQLite Docker volume path.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WebApp
    participant DisplaySettingsController
    participant DisplaySettings
    participant DB

    User->>WebApp: Access customization page (GET /displays/{id}/customization)
    WebApp->>DisplaySettingsController: customization(display)
    DisplaySettingsController->>DisplaySettings: Fetch settings
    DisplaySettings->>DB: Query settings
    DB-->>DisplaySettings: Settings data
    DisplaySettings-->>DisplaySettingsController: Settings object
    DisplaySettingsController-->>WebApp: Render customization form

    User->>WebApp: Submit customization form (PUT /displays/{id}/customization)
    WebApp->>DisplaySettingsController: updateCustomization(request, display)
    DisplaySettingsController->>DisplaySettings: Update or delete settings
    DisplaySettings->>DB: Write settings
    DB-->>DisplaySettings: Success/failure
    DisplaySettings-->>DisplaySettingsController: Result
    DisplaySettingsController-->>WebApp: Redirect with status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

In fields of code, a rabbit hops,
Custom texts for rooms—it never stops!
Pro users now can tweak and play,
With meeting titles tucked away.
A brush of change, a banner new—
The dashboard’s brighter, clearer too!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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 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

Documentation and Community

  • 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.

@codecov-commenter
Copy link

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 34.24658% with 48 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...app/Http/Controllers/DisplaySettingsController.php 0.00% 28 Missing ⚠️
backend/app/Helpers/DisplaySettings.php 50.00% 10 Missing ⚠️
...ttp/Requests/UpdateDisplayCustomizationRequest.php 0.00% 10 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link

@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: 3

🔭 Outside diff range comments (1)
app/lib/controllers/dashboard_controller.dart (1)

30-46: Avoid making onInit async - potential timing issues

Making onInit() async can cause issues because GetX doesn't await controller initialization. This could lead to race conditions where the controller is used before initialization completes.

-  void onInit() async {
+  void onInit() {
     super.onInit();

     updateTime();
     
     // Check if display ID is set, redirect to display page if not
     final displayIdResult = AuthService.instance.getCurrentDisplayId();
     if (displayIdResult == null) {
       Get.offAll(() => const DisplayPage());
       return;
     } else {
       displayId.value = displayIdResult;
     }

     initializeTimers();
-    await fetchDisplayData();
+    fetchDisplayData();

     loading.value = false;
   }
🧹 Nitpick comments (7)
docs/UPGRADE_GUIDE.md (1)

11-13: Confirm mount-precedence does not unintentionally shadow files inside storage/.

Mounting the whole directory (storage_data:/var/www/html/storage) and then a bind-mount for a single file inside the same target path relies on Docker’s “more specific mount wins” rule.
While this usually works, it can surprise operators if additional files are later added to storage/ on the host and silently hidden by the named volume, or vice-versa if the compose order is changed.

Consider either

  1. Dropping the directory-level volume if all you need is the SQLite file, or
  2. Moving the file outside storage/ (e.g. ./database.sqlite:/var/www/html/database.sqlite) to avoid overlapping mounts.

At minimum, add a short note explaining why two overlapping mounts are intentional and safe.

app/lib/translations/translations.dart (1)

50-51: Minor inconsistency in check-in text formatting.

The English locale uses hyphens in 'check_in_now' and 'check_in', but other locales don't follow this pattern consistently. Consider standardizing the formatting across all locales for consistency.

backend/app/Http/Requests/UpdateDisplayCustomizationRequest.php (1)

17-23: Consider making the boolean field nullable for consistency.

The validation rules look good overall. However, consider whether show_meeting_title should be nullable|boolean for consistency with the text fields and to handle cases where the field might not be provided.

The 64-character limit for text fields is reasonable for display purposes.

-            'show_meeting_title' => 'boolean',
+            'show_meeting_title' => 'nullable|boolean',
app/lib/models/display_settings_model.dart (1)

41-41: Questionable return type change for toJson method.

The return type changed from Map<String, dynamic> to Map<String, dynamic>? but the method implementation still returns a non-null map. This change seems unnecessary and potentially misleading.

Consider reverting the return type to Map<String, dynamic> since the method never returns null:

- Map<String, dynamic>? toJson() {
+ Map<String, dynamic> toJson() {
backend/app/Http/Controllers/DisplaySettingsController.php (1)

139-139: Consider documenting the boolean field behavior.

The show_meeting_title field is always set regardless of checkbox state, defaulting to false when unchecked. This is correct behavior for checkboxes but could benefit from a brief comment explaining the always-set approach.

Consider adding a comment to clarify the boolean handling:

+ // Always set show_meeting_title (defaults to false if checkbox unchecked)
  $updated = $updated && DisplaySettings::setShowMeetingTitle($display, $request->boolean('show_meeting_title'));
backend/resources/views/pages/dashboard.blade.php (1)

265-277: Consider consolidating the duplicate upgrade logic.

The empty state contains duplicate conditional logic for both self-hosted and non-self-hosted scenarios that render identical disabled buttons. This could be simplified for better maintainability.

Consider consolidating the duplicate upgrade logic:

- @if(! $isSelfHosted && auth()->user()->shouldUpgrade())
-     <span class="inline-flex items-center rounded-md bg-gray-100 px-3 py-2 text-center text-sm font-semibold text-gray-400 shadow-sm ring-1 ring-inset ring-gray-200 cursor-not-allowed" title="Upgrade to Pro to create more displays">
-         <x-icons.plus class="h-5 w-5 mr-1" /> Create new display <span class="ml-2 inline-flex items-center rounded-md bg-blue-50 px-1.5 py-0.5 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-600">Pro</span>
-     </span>
- @elseif($isSelfHosted && auth()->user()->shouldUpgrade())
-     <span class="inline-flex items-center rounded-md bg-gray-100 px-3 py-2 text-center text-sm font-semibold text-gray-400 shadow-sm ring-1 ring-inset ring-gray-200 cursor-not-allowed" title="Upgrade to Pro to create more displays">
-         <x-icons.plus class="h-5 w-5 mr-1" /> Create new display <span class="ml-2 inline-flex items-center rounded-md bg-blue-50 px-1.5 py-0.5 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-600">Pro</span>
-     </span>
+ @if(auth()->user()->shouldUpgrade())
+     <span class="inline-flex items-center rounded-md bg-gray-100 px-3 py-2 text-center text-sm font-semibold text-gray-400 shadow-sm ring-1 ring-inset ring-gray-200 cursor-not-allowed" title="Upgrade to Pro to create more displays">
+         <x-icons.plus class="h-5 w-5 mr-1" /> Create new display <span class="ml-2 inline-flex items-center rounded-md bg-blue-50 px-1.5 py-0.5 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-600">Pro</span>
+     </span>
backend/app/Helpers/DisplaySettings.php (1)

113-116: Consider providing default values for text getters

The text getter methods return null when settings don't exist, which could lead to null reference issues in consuming code. Consider either:

  1. Providing sensible default values (e.g., 'Available', 'Transitioning', etc.)
  2. Clearly documenting that these methods return nullable strings so callers handle null cases appropriately
 public static function getAvailableText(Display $display): ?string
 {
-    return self::getSetting($display, 'text_available');
+    return self::getSetting($display, 'text_available', 'Available');
 }

Also applies to: 122-125, 131-134, 140-143

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 70748cc and 934c83f.

📒 Files selected for processing (21)
  • app/lib/components/action_panel.dart (1 hunks)
  • app/lib/components/calendar_modal.dart (1 hunks)
  • app/lib/controllers/dashboard_controller.dart (8 hunks)
  • app/lib/models/display_settings_model.dart (2 hunks)
  • app/lib/translations/translations.dart (5 hunks)
  • app/pubspec.yaml (1 hunks)
  • backend/app/Helpers/DisplaySettings.php (2 hunks)
  • backend/app/Http/Controllers/DisplayController.php (0 hunks)
  • backend/app/Http/Controllers/DisplaySettingsController.php (2 hunks)
  • backend/app/Http/Requests/UpdateDisplayCustomizationRequest.php (1 hunks)
  • backend/app/Http/Resources/API/DisplayResource.php (0 hunks)
  • backend/app/Http/Resources/API/DisplaySettingsResource.php (1 hunks)
  • backend/app/Models/Display.php (1 hunks)
  • backend/resources/views/components/icons/brush.blade.php (1 hunks)
  • backend/resources/views/pages/dashboard.blade.php (5 hunks)
  • backend/resources/views/pages/displays/create.blade.php (1 hunks)
  • backend/resources/views/pages/displays/customization.blade.php (1 hunks)
  • backend/routes/web.php (1 hunks)
  • backend/tests/Feature/DisplaySettingsApiTest.php (0 hunks)
  • docs/PRICING.md (1 hunks)
  • docs/UPGRADE_GUIDE.md (1 hunks)
💤 Files with no reviewable changes (3)
  • backend/tests/Feature/DisplaySettingsApiTest.php
  • backend/app/Http/Controllers/DisplayController.php
  • backend/app/Http/Resources/API/DisplayResource.php
🧰 Additional context used
🧬 Code Graph Analysis (1)
backend/app/Http/Resources/API/DisplaySettingsResource.php (3)
backend/app/Models/Display.php (5)
  • getAvailableText (146-149)
  • getTransitioningText (151-154)
  • getReservedText (156-159)
  • getCheckInText (161-164)
  • getShowMeetingTitle (166-169)
backend/app/Helpers/DisplaySettings.php (5)
  • getAvailableText (113-116)
  • getTransitioningText (122-125)
  • getReservedText (131-134)
  • getCheckInText (140-143)
  • getShowMeetingTitle (150-153)
backend/app/Http/Resources/API/DisplayResource.php (2)
  • DisplayResource (8-24)
  • toArray (15-23)
🔇 Additional comments (25)
docs/PRICING.md (1)

10-10: Documentation clarity improvement looks good.

The updated trial description is more specific and accurate, clarifying that the free trial applies to the Pro plan and requires registration.

backend/resources/views/pages/displays/create.blade.php (1)

112-117: UI simplification looks good and aligns with backend changes.

The removal of Pro-related conditional logic for the "Connect by Room" feature creates a cleaner, more straightforward user experience. This change is consistent with the backend controller updates that removed Pro enforcement for room functionality.

app/pubspec.yaml (1)

19-19: Appropriate version bump for new features.

The minor version increment from 1.1.2 to 1.2.0 correctly reflects the new display customization features and refactorings mentioned in the PR.

app/lib/components/action_panel.dart (1)

49-49: Method call update aligns with controller refactoring.

The simplified bookRoom(min) call is consistent with the controller method signature changes that moved the localized "reserved" text handling into the controller itself. This reduces coupling and simplifies the component interface.

backend/app/Http/Resources/API/DisplaySettingsResource.php (1)

23-27: LGTM! Well-structured addition of display customization fields.

The new fields are properly integrated into the API resource and align with the backend implementation. The method calls delegate appropriately to the Display model's convenience methods.

app/lib/translations/translations.dart (1)

60-60: LGTM! Consistent addition of 'meeting' translations.

The new 'meeting' translation key is properly added to all supported locales with appropriate translations.

Also applies to: 116-116, 172-172, 228-228, 284-284

backend/resources/views/components/icons/brush.blade.php (1)

1-18: LGTM! Well-implemented SVG icon component.

The brush icon follows Laravel Blade component conventions correctly:

  • Uses {{ $attributes }} for dynamic attribute binding
  • Uses currentColor for theme-aware coloring
  • Proper SVG structure with appropriate viewBox

The SVG path appears to be a valid vector definition for a brush icon.

backend/routes/web.php (1)

80-84: LGTM! Well-structured routes for display customization.

The new routes follow Laravel conventions and are properly placed within the authenticated middleware group. The RESTful naming pattern is consistent with existing routes.

Ensure that the DisplaySettingsController methods handle proper authorization, especially since this appears to be a Pro feature.

backend/app/Http/Requests/UpdateDisplayCustomizationRequest.php (1)

9-13: LGTM! Proper authorization delegation to controller.

The authorization logic correctly delegates to the controller, which is appropriate for complex authorization scenarios like Pro feature access.

backend/app/Models/Display.php (1)

146-169: Well-structured convenience methods following established patterns.

The new display customization accessor methods are implemented consistently with the existing pattern in this class. They provide clean encapsulation by delegating to the DisplaySettings helper class while maintaining the model's interface.

backend/resources/views/pages/displays/customization.blade.php (4)

6-17: Proper Pro feature gating with clear user guidance.

The conditional rendering effectively restricts access to Pro users while providing clear messaging and navigation for non-Pro users. The upgrade prompt is informative and actionable.


35-37: Secure form implementation with proper CSRF protection.

The form correctly implements CSRF protection and method spoofing for the PUT request, following Laravel security best practices.


43-43: Robust input handling with proper fallbacks.

The input field correctly uses old() for form persistence on validation errors and falls back to the DisplaySettings helper method for initial values. The maxlength="64" attribute provides client-side validation.


61-61: Proper boolean checkbox handling.

The checkbox implementation correctly handles the boolean value using Laravel's ternary operator for the checked attribute, with proper fallback to the DisplaySettings helper method.

app/lib/models/display_settings_model.dart (2)

7-11: Well-designed field additions with appropriate nullability.

The new customization fields are properly typed with nullable strings for optional text values and a required boolean for the meeting title visibility. This design allows flexibility while maintaining clear semantics.


37-37: Sensible default for privacy setting.

The default value of true for showMeetingTitle is appropriate as it maintains existing behavior when the setting is not explicitly configured, ensuring backwards compatibility.

backend/app/Http/Controllers/DisplaySettingsController.php (3)

88-99: Proper authorization and Pro access control.

The method correctly implements authorization checks and Pro user validation with appropriate error messaging and redirection. This follows the established security pattern in the controller.


111-136: Robust text field update logic with proper cleanup.

The implementation correctly handles both setting and deleting text values based on input presence using Laravel's filled() helper. The logic appropriately deletes settings when fields are empty, preventing storage of empty values.


141-145: Appropriate error handling and user feedback.

The error handling correctly uses back() for form errors and provides proper success redirection with flash messages. The redirect to the customization route maintains user context.

backend/resources/views/pages/dashboard.blade.php (3)

32-60: Improved Pro upgrade banner with better visual hierarchy.

The new indigo-themed banner is more visually prominent and provides comprehensive information about Pro features. The structured layout with icon, content, and CTA button creates better user engagement than the previous implementation.


77-82: Consistent Pro feature gating with clear user feedback.

The conditional rendering effectively prevents non-Pro users from accessing premium features while providing clear tooltips explaining the upgrade requirement. The disabled styling with appropriate cursor indicates the unavailable state.


232-245: Unified approach to Pro feature access controls.

The display action buttons (customization and settings) consistently implement the Pro gating pattern with disabled spans for non-Pro users. The tooltips provide clear messaging about feature availability.

backend/app/Helpers/DisplaySettings.php (1)

149-157: LGTM!

The show meeting title toggle methods are well-implemented with appropriate default value for backward compatibility.

app/lib/controllers/dashboard_controller.dart (2)

66-66: Good null-safe implementation

The updated getters properly handle potential null values with appropriate fallbacks, maintaining backward compatibility.

Also applies to: 74-79, 256-256, 260-260, 277-277, 281-281, 285-285


312-322: Well-structured helper methods

The new helper methods properly implement the meeting title privacy feature with good separation of concerns and null safety.

Comment on lines +6 to +7
import 'package:spacepad/controllers/dashboard_controller.dart';
import 'package:spacepad/services/auth_service.dart';
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Verify that these imports are actually used.

The new imports for DashboardController and AuthService don't appear to be referenced anywhere in the current code. Ensure these imports are necessary and being used, or remove them if they're not needed to avoid dead imports.


🏁 Script executed:

#!/bin/bash
# Description: Check if the imported classes are actually used in this file
# Expected: Should find usage of DashboardController or AuthService if imports are needed

# Search for usage of DashboardController in the calendar modal file
rg -A 3 -B 3 "DashboardController|AuthService" app/lib/components/calendar_modal.dart

Length of output: 87


Remove unused imports in calendar_modal.dart

It looks like the imports for DashboardController and AuthService aren’t referenced anywhere in app/lib/components/calendar_modal.dart. To keep the code clean, please either:

  • Remove these two import lines if they’re not needed
  • Or add the intended usage for DashboardController and AuthService into this file

Locations to update:

  • app/lib/components/calendar_modal.dart, lines 6–7
🤖 Prompt for AI Agents
In app/lib/components/calendar_modal.dart at lines 6 to 7, the imports for
DashboardController and AuthService are not used anywhere in the file. To fix
this, remove these two import lines to clean up the code and avoid unnecessary
dependencies.

Comment on lines +21 to +24
// Global variables for device, display, and settings
DeviceModel? globalCurrentDevice;
DisplayModel? globalDisplay;
DisplaySettingsModel? globalSettings;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reconsider the global variable design pattern

The introduction of instance variables prefixed with "global" raises several concerns:

  1. The "global" prefix is misleading since these are instance variables, not truly global
  2. This creates a potential synchronization issue with the reactive AuthService.currentDevice
  3. Risk of stale data if these aren't updated in sync with the reactive state

Consider using the existing reactive pattern consistently or rename these variables to better reflect their scope.

-  // Global variables for device, display, and settings
-  DeviceModel? globalCurrentDevice;
-  DisplayModel? globalDisplay;
-  DisplaySettingsModel? globalSettings;
+  // Cached references for quick access
+  DeviceModel? _cachedDevice;
+  DisplayModel? _cachedDisplay;
+  DisplaySettingsModel? _cachedSettings;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Global variables for device, display, and settings
DeviceModel? globalCurrentDevice;
DisplayModel? globalDisplay;
DisplaySettingsModel? globalSettings;
// Cached references for quick access
DeviceModel? _cachedDevice;
DisplayModel? _cachedDisplay;
DisplaySettingsModel? _cachedSettings;
🤖 Prompt for AI Agents
In app/lib/controllers/dashboard_controller.dart around lines 21 to 24, the
variables named with a "global" prefix are instance variables, not truly global,
which is misleading and risks stale data due to lack of synchronization with
AuthService.currentDevice. To fix this, either remove these variables and rely
directly on the reactive AuthService.currentDevice for consistent state
management, or rename these variables to reflect their actual scope and ensure
they are updated reactively in sync with AuthService.currentDevice to avoid
stale data issues.

Comment on lines +201 to 219
// Update global device, display, and settings
if (AuthService.instance.currentDevice.value != null) {
AuthService.instance.currentDevice.value!.display = displayData.display;
globalCurrentDevice = AuthService.instance.currentDevice.value;
globalCurrentDevice!.display = displayData.display;
globalDisplay = globalCurrentDevice!.display;
globalSettings = globalDisplay?.settings;

AuthService.instance.currentDevice.refresh();
}

// Update events
events.value = displayData.events
.where((e) => e.status != EventStatus.cancelled)
.map((e) {
e.summary = getDisplayableSummary(e);
return e;
})
.toList();
} catch (e) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Avoid direct mutation of AuthService state

This code directly mutates the AuthService.currentDevice display property, which could cause unexpected side effects and breaks encapsulation.

Consider updating through a proper service method rather than direct mutation:

       // Update global device, display, and settings
       if (AuthService.instance.currentDevice.value != null) {
         globalCurrentDevice = AuthService.instance.currentDevice.value;
-        globalCurrentDevice!.display = displayData.display;
         globalDisplay = displayData.display;
         globalSettings = globalDisplay?.settings;
-
-        AuthService.instance.currentDevice.refresh();
+        // Update through service if needed
+        AuthService.instance.updateDeviceDisplay(displayData.display);
       }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In app/lib/controllers/dashboard_controller.dart around lines 201 to 219, the
code directly mutates the display property of
AuthService.instance.currentDevice.value, which breaks encapsulation and may
cause side effects. To fix this, avoid direct mutation by creating a method in
AuthService to update the currentDevice's display and related properties safely.
Replace the direct assignments with calls to this method, ensuring the state is
updated through controlled service logic.

@magweter magweter merged commit 54fc61e into main Jul 23, 2025
4 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Nov 9, 2025
@coderabbitai coderabbitai bot mentioned this pull request Nov 29, 2025
@coderabbitai coderabbitai bot mentioned this pull request Jan 11, 2026
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