Skip to content

Productivity and DevEx improvements#4

Open
bez4pieci wants to merge 6 commits into
mainfrom
productivity
Open

Productivity and DevEx improvements#4
bez4pieci wants to merge 6 commits into
mainfrom
productivity

Conversation

@bez4pieci
Copy link
Copy Markdown
Owner

@bez4pieci bez4pieci commented Jul 5, 2025

Summary by CodeRabbit

  • New Features

    • Added live code injection (hot-reloading) support for all main views, enabling instant UI updates during development without rebuilding the app.
    • Integrated the Inject Swift package to facilitate hot-reloading functionality.
  • Improvements

    • Updated app configuration to allow flexible use of Firebase Cloud Functions emulator via environment variables.
    • Enhanced documentation with clearer architecture details, build instructions, and hot-reloading setup guidance.
  • Refactor

    • Simplified app settings management by converting AppSettings from a class to a struct and removing it as a global environment object.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jul 5, 2025

Walkthrough

This update introduces live code injection (hot-reloading) to the SwiftUI app by integrating the Inject package, updating project configuration, and modifying multiple views to support runtime code updates. It also refines cloud functions configuration and emulator support, simplifies app settings management, and updates documentation to reflect these development enhancements.

Changes

File(s) Change Summary
README.md Clarified architecture, added cloud function deployment/emulation steps, and documented hot-reloading setup.
When.xcodeproj/project.pbxproj
When.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
Added Inject Swift package, updated build settings, linker flags, and integrated dependency into app target.
When.xcodeproj/xcshareddata/xcschemes/When App.xcscheme Added -FIRDebugDisabled launch argument and updated environment variable for cloud functions emulator.
When/Config/AppConfig.swift Replaced bvgApiAuthorization with new cloud functions emulator config and region constants.
When/Models/AppSettings.swift Changed AppSettings from ObservableObject class to plain struct; updated documentation.
When/DeparturesApp.swift Removed AppSettings environment object from app and preview.
When/Services/TransportService.swift Updated Firebase Functions region config and emulator setup to use new config struct and environment variable.
When/Views/Main.swift Imported Inject globally, added injection observer, enabled injection, and updated preview environment.
When/Views/MainHeader.swift
When/Views/NoStation.swift
When/Views/StationTab.swift
Added injection observer property and enabled injection for live code updates.
When/Views/DepartureBoard.swift
When/Views/StationSettings.swift
When/Views/StationSearchField.swift
When/Views/StationSearchResults.swift
Added injection observer and enabled injection for hot-reloading in multiple views.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant InjectionIII as InjectionIII App
    participant App as SwiftUI App
    participant Inject as Inject Package

    Dev->>InjectionIII: Edit SwiftUI code and save
    InjectionIII->>App: Trigger code injection event
    App->>Inject: Observe injection via @ObserveInjection
    Inject->>App: Notifies affected views to redraw
    App->>Dev: Updated UI reflects code changes instantly
Loading

Poem

🐇
With a hop and a skip, new code comes alive,
Hot-reloading magic helps features arrive!
No more rebuilds, just tweak and inject—
SwiftUI views redraw, as you’d expect.
Cloud configs are clearer, emulator’s in play,
This bunny’s delighted—what a dev-friendly day!

✨ Finishing Touches
  • 📝 Generate Docstrings

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

Copy link
Copy Markdown

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

🧹 Nitpick comments (3)
README.md (1)

61-65: Improve documentation clarity for hot reloading setup.

The hot reloading documentation is helpful but could be refined:

Consider this improved wording to address the static analysis hint:

-   - With both Inject and InjectionIII running, you can make changes to your SwiftUI views and see updates in the simulator without rebuilding the entire app.
+   - With both Inject and InjectionIII running, you can modify SwiftUI views and see live updates in the simulator without rebuilding the entire app.

Also consider adding a note about when to use hot reloading (e.g., "Use this during active development for faster iteration cycles").

When/Views/Main.swift (2)

2-2: Remove @_exported unless re-exporting is intentionally needed.

The @_exported attribute re-exports the Inject module to any code that imports this file. Unless you specifically need other modules to access Inject through this import, use a regular import instead.

-@_exported import Inject
+import Inject

2-2: Consider wrapping injection code in DEBUG conditionals.

While the injection setup is correctly implemented, consider wrapping the injection-related code in #if DEBUG conditionals to ensure it doesn't ship in production builds. This is a common practice for development-only features.

+#if DEBUG
 @_exported import Inject
+#endif
+#if DEBUG
     @ObserveInjection var redraw
+#endif
         }
+#if DEBUG
         .enableInjection()
+#endif

Also applies to: 7-7, 99-99

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ab326cb and ff15faf.

📒 Files selected for processing (6)
  • README.md (1 hunks)
  • When.xcodeproj/project.pbxproj (12 hunks)
  • When.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved (2 hunks)
  • When.xcodeproj/xcshareddata/xcschemes/When App.xcscheme (1 hunks)
  • When/Components/DepartureBoard.swift (2 hunks)
  • When/Views/Main.swift (2 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md

[style] ~64-~64: Consider shortening or rephrasing this to strengthen your wording.
Context: ...nject and InjectionIII running, you can make changes to your SwiftUI views and see updates in t...

(MAKE_CHANGES)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cursor BugBot
🔇 Additional comments (7)
When.xcodeproj/project.pbxproj (2)

20-20: Inject package integration looks well-configured.

The Inject Swift package has been properly added with appropriate build settings:

  • Debug-only linker flags for interposition
  • Correct frontend command line emission settings
  • Main app target only (widget excluded appropriately)

Also applies to: 146-146, 263-263


580-584: Verify linker flags are debug-only.

The -Xlinker -interposable flags are correctly added only to debug builds. This is important for performance as these flags can impact release build optimization.

Also applies to: 667-670

When.xcodeproj/xcshareddata/xcschemes/When App.xcscheme (1)

54-57: Clarify the relationship between Firebase debug flag and Inject integration.

The addition of -FIRDebugDisabled seems unrelated to the main objective of adding hot reloading with Inject. Could you explain:

  1. Why this Firebase change is included in this PR?
  2. Does this flag interact with the injection framework in any way?

Consider separating unrelated changes into different PRs for better traceability.

When/Components/DepartureBoard.swift (2)

5-5: Inject integration is correctly implemented.

The @ObserveInjection property wrapper and .enableInjection() modifier are properly added according to the Inject package documentation.

Also applies to: 22-22


5-5: Remove obsolete suggestion: MainView already supports injection
The review’s premise—that only DepartureBoard has injection support—is outdated.

  • When/Views/Main.swift already declares @ObserveInjection var redraw.
  • No other struct …: View definitions without @ObserveInjection were found.

Likely an incorrect or invalid review comment.

When.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved (1)

85-93: Package resolution correctly reflects Inject dependency.

The Package.resolved file properly includes the Inject package at version 1.5.2 with the correct revision hash. This auto-generated file accurately reflects the dependency changes.

When/Views/Main.swift (1)

7-7: LGTM! Proper injection setup implementation.

The @ObserveInjection property wrapper and .enableInjection() view modifier are correctly implemented following the Inject package's standard usage pattern. This will enable hot reloading functionality during development.

Also applies to: 99-99

Comment on lines +750 to +757
1395660E2E19CA0000329958 /* XCRemoteSwiftPackageReference "Inject" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/krzysztofzablocki/Inject.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.5.2;
};
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify Inject package version and security considerations.

The minimum version 1.5.2 appears reasonable, but please ensure:

  1. This version doesn't have known security vulnerabilities
  2. The package is only included in debug builds in production

Also applies to: 793-797


🏁 Script executed:

#!/bin/bash
# Check if Inject package is properly excluded from release builds
echo "Checking if Inject is properly configured for debug-only usage..."

# Search for any conditional compilation or debug-only usage of Inject
rg -A 3 -B 3 "import Inject|@ObserveInjection|enableInjection" --type swift

# Check build configurations to ensure Inject isn't in release
rg -A 5 -B 5 "Release.*Inject" When.xcodeproj/project.pbxproj

Length of output: 1835


Enforce Debug-Only Injection & Audit Inject v1.5.2

Please scope all Inject hooks to debug builds and perform a security review of v1.5.2:

• Wrap every @ObserveInjection and .enableInjection() behind #if DEBUG in:
– When/Views/Main.swift
– When/Components/DepartureBoard.swift
• Restrict the Inject package dependency to your debug scheme or target configuration in Xcode so it isn’t bundled in production releases.
• Verify Inject v1.5.2 against known security advisories (e.g. GitHub Security Advisories, Snyk) to ensure no CVEs apply.

Example change in your Swift views:

- @_exported import Inject
- @ObserveInjection var redraw
-
-     .enableInjection()
+ #if DEBUG
+ @_exported import Inject
+ @ObserveInjection var redraw
+
+     .enableInjection()
+ #endif

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

🤖 Prompt for AI Agents
In When.xcodeproj/project.pbxproj around lines 750 to 757, the Inject package is
currently included without restricting it to debug builds. To fix this, modify
the Xcode project settings to include the Inject package only in the debug
scheme or target configuration, ensuring it is not bundled in production
releases. Additionally, in When/Views/Main.swift and
When/Components/DepartureBoard.swift, wrap all uses of @ObserveInjection and
.enableInjection() inside #if DEBUG conditional compilation blocks to enforce
debug-only injection. Finally, perform a security review of Inject v1.5.2
against known advisories to confirm no vulnerabilities affect your project.

Copy link
Copy Markdown

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fd059c5 and 939a3b4.

📒 Files selected for processing (7)
  • When/Components/DepartureBoard.swift (3 hunks)
  • When/Components/MainHeader.swift (2 hunks)
  • When/Components/NoStation.swift (2 hunks)
  • When/Components/StationSearchField.swift (2 hunks)
  • When/Components/StationSearchResults.swift (2 hunks)
  • When/Components/StationTab.swift (2 hunks)
  • When/Views/StationSettings.swift (4 hunks)
✅ Files skipped from review due to trivial changes (2)
  • When/Components/StationSearchField.swift
  • When/Components/MainHeader.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • When/Components/DepartureBoard.swift
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cursor BugBot
🔇 Additional comments (5)
When/Components/NoStation.swift (1)

50-50: Injection implementation looks correct.

The .enableInjection() modifier is properly placed on the root ScrollView, following the standard pattern for the Inject package.

When/Components/StationSearchResults.swift (1)

5-5: Injection implementation is consistent and correct.

The injection pattern is properly implemented with @ObserveInjection property and .enableInjection() modifier on the root view. This follows the same correct pattern as other components in the codebase.

Also applies to: 34-34

When/Components/StationTab.swift (1)

6-6: Injection implementation is consistent and well-placed.

The injection setup follows the established pattern correctly, with the property at the top of the struct and the modifier on the root ScrollView.

Also applies to: 79-79

When/Views/StationSettings.swift (2)

7-7: Injection correctly implemented for main view.

The injection setup is properly implemented on the main StationSettingsView with the standard pattern.

Also applies to: 33-33


119-119: Injection correctly implemented for content view.

The injection setup is properly implemented on the private StationSettingsContentView as well. Having injection on both the parent and child views makes sense since they are separate SwiftUI views, and most of the UI logic resides in the content view.

Also applies to: 223-223

import SwiftUI

struct NoStation: View {
@ObserveInjection var redraw
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify Inject package import is available.

The @ObserveInjection property wrapper is used but I don't see a corresponding import for the Inject package. Please ensure the necessary import is present.


🏁 Script executed:

#!/bin/bash
# Check if there's a missing import for the Inject package
rg -A 5 -B 5 "import.*Inject" 

# Also check if injection symbols are available globally
ast-grep --pattern 'import $_' --lang swift | head -20

Length of output: 1518


Add missing Inject import in NoStation.swift

The @ObserveInjection wrapper comes from the Inject package but isn’t imported in When/Components/NoStation.swift. Please add:

--- a/When/Components/NoStation.swift
+++ b/When/Components/NoStation.swift
@@ 1,3 +1,4 @@
+ import Inject
import SwiftUI
import SwiftData
…

This ensures @ObserveInjection is recognized.

📝 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
@ObserveInjection var redraw
import Inject
import SwiftUI
import SwiftData
🤖 Prompt for AI Agents
In When/Components/NoStation.swift at line 5, the @ObserveInjection property
wrapper is used but the Inject package is not imported. Add the import statement
for Inject at the top of the file to ensure @ObserveInjection is recognized and
the code compiles correctly.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Bug: AppStorage Initialization Issue

The AppSettings struct is no longer instantiated, preventing its init() method from running. This leaves userDeviceId uninitialized (empty) for new installations. Furthermore, directly modifying an @AppStorage property within a struct's init() is not supported by Swift.

When/Models/AppSettings.swift#L3-L13

struct AppSettings {
/// Identify the user's device with a random UUID
@AppStorage("userDeviceId") var userDeviceId: String = ""
init() {
if userDeviceId.isEmpty {
userDeviceId = UUID().uuidString
}
}
}

Fix in CursorFix in Web


BugBot free trial expires on July 22, 2025
You have used $0.00 of your $50.00 spend limit so far. Manage your spend limit in the Cursor dashboard.

Was this report helpful? Give feedback by reacting with 👍 or 👎

Copy link
Copy Markdown

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

♻️ Duplicate comments (1)
When/Views/NoStation.swift (1)

5-5: Verify that the Inject package is properly imported.

Same issue as in MainHeader.swift - the @ObserveInjection property wrapper requires importing the Inject package.

🧹 Nitpick comments (2)
When/Config/AppConfig.swift (2)

3-11: Good struct design, but consider improving initializer flexibility.

The struct design is clean and follows Swift conventions. However, the initializer only allows customization of the enabled parameter while host and port use hardcoded defaults.

Consider adding an overloaded initializer for more flexibility:

 struct CloudFunctionsEmulatorConfig {
     var enabled: Bool
     var host: String = "localhost"
     var port: Int = 5001

     init(enabled: Bool) {
         self.enabled = enabled
     }
+    
+    init(enabled: Bool, host: String, port: Int) {
+        self.enabled = enabled
+        self.host = host
+        self.port = port
+    }
 }

This would allow customization of host and port when needed while maintaining the convenience of the simple initializer.


22-29: Robust emulator configuration with minor improvement suggestion.

The computed property implementation is well-structured with proper conditional compilation and environment variable checking. The documentation comment is helpful.

Consider making the environment variable check case-insensitive for better developer experience:

 static var cloudFunctionsEmulator: CloudFunctionsEmulatorConfig {
     #if DEBUG
-        if ProcessInfo.processInfo.environment["CLOUD_FUNCTIONS_EMULATOR"] == "YES" {
+        if ProcessInfo.processInfo.environment["CLOUD_FUNCTIONS_EMULATOR"]?.uppercased() == "YES" {
             return CloudFunctionsEmulatorConfig(enabled: true)
         }
     #endif
     return CloudFunctionsEmulatorConfig(enabled: false)
 }

This would accept variations like "yes", "Yes", or "YES" in the environment variable.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 939a3b4 and 155bbdb.

📒 Files selected for processing (9)
  • When/Config/AppConfig.swift (1 hunks)
  • When/Models/AppSettings.swift (1 hunks)
  • When/Services/TransportService.swift (1 hunks)
  • When/Views/DepartureBoard.swift (3 hunks)
  • When/Views/MainHeader.swift (2 hunks)
  • When/Views/NoStation.swift (2 hunks)
  • When/Views/StationSearchField.swift (2 hunks)
  • When/Views/StationSearchResults.swift (2 hunks)
  • When/Views/StationTab.swift (2 hunks)
✅ Files skipped from review due to trivial changes (4)
  • When/Views/StationSearchResults.swift
  • When/Views/StationSearchField.swift
  • When/Views/StationTab.swift
  • When/Views/DepartureBoard.swift
🚧 Files skipped from review as they are similar to previous changes (2)
  • When/Models/AppSettings.swift
  • When/Services/TransportService.swift
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cursor BugBot
🔇 Additional comments (5)
When/Config/AppConfig.swift (1)

19-19: LGTM! Clean configuration constant.

The static constant is well-named and follows Swift naming conventions. The region value "europe-west1" appears to be a valid Firebase Functions region.

When/Views/MainHeader.swift (2)

54-54: LGTM! Hot-reloading implementation is correctly positioned.

The .enableInjection() modifier is properly placed at the end of the view modifier chain, which is the correct approach for the Inject package.


5-5: LGTM: Consistent implementation of live code injection.

The implementation follows the standard pattern for the Inject package with proper property wrapper usage and view modifier chaining. The changes are minimal and focused on enabling hot-reloading functionality.

Also applies to: 54-54

When/Views/NoStation.swift (2)

50-50: LGTM! Consistent hot-reloading implementation.

The implementation matches the pattern used in MainHeader.swift and is correctly positioned in the view modifier chain.


5-5: LGTM: Proper implementation of live code injection.

The implementation correctly uses the @ObserveInjection property wrapper and .enableInjection() modifier to enable hot-reloading functionality. The changes are minimal and non-intrusive to the existing view logic.

Also applies to: 50-50

import SwiftUI

struct MainHeader: View {
@ObserveInjection var redraw
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify that the Inject package is properly imported.

The @ObserveInjection property wrapper requires importing the Inject package, but no import statement is visible in this file.


🏁 Script executed:

#!/bin/bash
# Check if Inject package is imported globally or in a framework
rg -A 5 -B 5 "import.*Inject" 

Length of output: 325


🏁 Script executed:

#!/bin/bash
# Locate and display the contents of MainHeader.swift
file_path=$(fd -e swift MainHeader.swift)
echo "File found at: $file_path"
echo "---- File Contents ----"
sed -n '1,200p' "$file_path"

Length of output: 5865


Add missing import Inject to MainHeader.swift

Swift import directives are file-local, so even though you have a re-exported import in Main.swift, any file using @ObserveInjection must explicitly import the Inject package.

Please update When/Views/MainHeader.swift:

 import PhosphorSwift
 import SwiftUI
+import Inject

 struct MainHeader: View {
     @ObserveInjection var redraw
     …
📝 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
@ObserveInjection var redraw
import PhosphorSwift
import SwiftUI
import Inject
struct MainHeader: View {
@ObserveInjection var redraw
🤖 Prompt for AI Agents
In When/Views/MainHeader.swift at line 5, the file uses the @ObserveInjection
property wrapper but is missing the required import statement for the Inject
package. Add the line 'import Inject' at the top of the file to explicitly
import the Inject module, ensuring the @ObserveInjection attribute is recognized
and the code compiles correctly.

🛠️ Refactor suggestion

Consider conditional compilation for debug builds only.

The live code injection functionality should ideally be limited to debug builds to avoid shipping development tools to production. Consider wrapping the injection-related code in conditional compilation directives.

Apply this pattern to limit injection to debug builds:

+#if DEBUG
 @ObserveInjection var redraw
+#endif

And for the modifier:

 .onDisappear {
     liveIconTimer?.invalidate()
     liveIconTimer = nil
 }
+#if DEBUG
 .enableInjection()
+#endif

Also applies to: 54-54

🤖 Prompt for AI Agents
In When/Views/MainHeader.swift at lines 5 and 54, the @ObserveInjection property
and related injection code should be wrapped in conditional compilation
directives to restrict them to debug builds only. Use #if DEBUG and #endif
around these lines to ensure the live code injection functionality is excluded
from production builds, preventing development tools from shipping in release
versions.

💡 Verification agent

🧩 Analysis chain

Verify import statement for Inject package.

The @ObserveInjection property wrapper requires the Inject package to be imported. Ensure the import statement is present or that the package is configured for automatic importing.

Let me check if the import statement is needed:


🏁 Script executed:

#!/bin/bash
# Description: Check if Inject package import is needed by searching for existing imports
# Expected: Should find import statements for Inject package in Swift files

# Search for Inject import statements in the codebase
rg -n "import.*Inject" --type swift

# Search for other files that use @ObserveInjection to see if they have imports
rg -n "@ObserveInjection" --type swift -A 2 -B 2

Length of output: 3038


Include explicit import Inject in MainHeader.swift

The @ObserveInjection property wrapper is defined in the Inject package, and Swift imports are file-scoped. Although When/Views/Main.swift uses

@_exported import Inject

that only re-exports the module for external clients—it doesn’t automatically import Inject into other files. You must add:

import Inject

to the top of any file that references @ObserveInjection (including When/Views/MainHeader.swift).

Additionally, to ensure hot-reload code isn’t shipped in production, wrap both the property wrapper and the view modifier in debug-only conditionals:

// In When/Views/MainHeader.swift
import SwiftUI
import Inject

struct MainHeader: View {
    #if DEBUG
    @ObserveInjection var redraw
    #endif
    // …
}

// In When/Views/Main.swift
var body: some Scene {
    WindowGroup {
        ContentView()
        #if DEBUG
        .enableInjection()
        #endif
    }
}

• When/Views/MainHeader.swift: add import Inject above other imports and guard @ObserveInjection with #if DEBUG.
• When/Views/Main.swift: wrap .enableInjection() in #if DEBUG.

🤖 Prompt for AI Agents
In When/Views/MainHeader.swift at line 5, add an explicit `import Inject`
statement at the top of the file to ensure the `@ObserveInjection` property
wrapper is recognized. Also, wrap the `@ObserveInjection var redraw` declaration
inside `#if DEBUG` and `#endif` to prevent hot-reload code from being included
in production builds. Additionally, in When/Views/Main.swift, wrap the
`.enableInjection()` call inside `#if DEBUG` and `#endif` to restrict it to
debug builds only.

import SwiftUI

struct NoStation: View {
@ObserveInjection var redraw
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consistent implementation with same considerations as MainHeader.swift.

The live code injection implementation is consistent with other files in the PR. The same considerations apply:

  1. Verify that the Inject package import statement is present or automatically imported
  2. Consider conditional compilation for debug builds only to prevent shipping development tools to production

Apply conditional compilation pattern:

+#if DEBUG
 @ObserveInjection var redraw
+#endif

And:

 .onScrollGeometryChange(for: CGFloat.self) { geometry in
     return geometry.contentOffset.y + geometry.contentInsets.top
 } action: { _, new in
     offset.wrappedValue = new
 }
+#if DEBUG
 .enableInjection()
+#endif

Also applies to: 50-50


To verify whether the Inject import is present (and consistent with MainHeader.swift), let’s inspect the top of both files:


🏁 Script executed:

#!/bin/bash
# Locate and print the first 20 lines of NoStation.swift
file=$(fd NoStation.swift)
echo "=== $file ==="
sed -n '1,20p' "$file"

# Locate and print the first 20 lines of MainHeader.swift
file2=$(fd MainHeader.swift)
echo "=== $file2 ==="
sed -n '1,20p' "$file2"

Length of output: 1451


To confirm whether the @ObserveInjection and .enableInjection() helpers are defined locally (and thus don’t require an external import) or come from a package you need to import, let’s locate any Injection-related files and your SPM manifest:


🏁 Script executed:

#!/bin/bash
# 1. Show your SPM manifest if present
pkg_file=$(fd Package.swift | head -n1)
if [[ -n "$pkg_file" ]]; then
  echo "=== $pkg_file ==="
  sed -n '1,200p' "$pkg_file"
else
  echo "No Package.swift found"
fi

# 2. Find any local Injection*.swift definitions
echo "=== Injection*.swift files ==="
fd -t f -i "Injection*.swift"

# 3. Search for ObserveInjection / enableInjection definitions
echo "=== ObserveInjection definitions ==="
rg -n "struct ObserveInjection" || echo "— no local property-wrapper found —"

echo "=== enableInjection definitions ==="
rg -n "func enableInjection" || echo "— no local view modifier found —"

Length of output: 600


Add missing Inject import and guard live‐code injection to DEBUG builds

The @ObserveInjection property wrapper and .enableInjection() modifier aren’t defined locally, so you need to import the module that provides them (for example, import Inject). Also, wrap both the property wrapper and the view modifier in #if DEBUG blocks so they’re excluded from production builds.

Locations to update (both in When/Views/NoStation.swift and When/Views/MainHeader.swift):

  • At the top, add the injection import:

    import PhosphorSwift
    import SwiftUI
    import Inject     // ← add this (or the correct module name)
  • Around the property wrapper:

     struct NoStation: View {
    -    @ObserveInjection var redraw
    +  #if DEBUG
  • @ObserveInjection var redraw
    
  • #endif

- Around the view modifier:
```diff
     ScrollView {
       // …
     }
+  #if DEBUG
       .enableInjection()
+  #endif
🤖 Prompt for AI Agents
In When/Views/NoStation.swift at line 5, the @ObserveInjection property wrapper
is used without importing its defining module. Add the appropriate import
statement (e.g., import Inject) at the top of the file along with existing
imports. Then, wrap the @ObserveInjection property declaration and any usage of
the .enableInjection() view modifier in #if DEBUG ... #endif blocks to ensure
they are only included in debug builds and excluded from production.

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.

1 participant