Skip to content

Conversation

@bgoncal
Copy link
Member

@bgoncal bgoncal commented Jan 12, 2026

Summary

Screenshots

Link to pull request in Documentation repository

Documentation: home-assistant/companion.home-assistant#

Any other notes

@bgoncal bgoncal self-assigned this Jan 12, 2026
Copilot AI review requested due to automatic review settings January 12, 2026 19:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request refactors the MJPEG camera player implementation by extracting business logic into a dedicated ViewModel and reorganizing files into an MJPEG subfolder. The refactoring simplifies the architecture by replacing a UIViewControllerRepresentable wrapper with a pure SwiftUI implementation using an ObservableObject ViewModel pattern.

Changes:

  • Created CameraMJPEGPlayerViewModel to handle MJPEG streaming logic and state management
  • Simplified CameraMJPEGPlayerView to use SwiftUI with the new ViewModel instead of UIViewControllerRepresentable
  • Reorganized files into Sources/App/Cameras/CameraPlayer/MJPEG/ subfolder for better code organization

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
Sources/App/Cameras/CameraPlayer/MJPEG/CameraMJPEGPlayerViewModel.swift New ViewModel containing MJPEG streaming logic, state management, and API interactions
Sources/App/Cameras/CameraPlayer/MJPEG/CameraMJPEGPlayerView.swift Refactored SwiftUI view using the new ViewModel pattern instead of UIKit wrapper
Sources/App/Cameras/CameraPlayer/CameraMJPEGPlayerView.swift Deleted old implementation that used UIViewControllerRepresentable
HomeAssistant.xcodeproj/project.pbxproj Updated Xcode project structure to include new ViewModel and reorganized file structure

Comment on lines +51 to +54
DispatchQueue.main.async { [weak self] in
self?.isLoading = false
self?.hasStarted = false
}
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The isLoading and hasStarted flags are being set to false in the pipe callback regardless of whether the stream successfully started or encountered an error. When the stream URL is successfully obtained and startStream is called, these flags are immediately reset before the stream actually begins. This means isLoading will be false even if the stream hasn't received its first frame yet, potentially showing incorrect loading state to the user.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Comment on lines 42 to 43
DispatchQueue.main.async { [weak self] in
self?.hasStarted = false
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

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

The hasStarted flag is being modified from a background thread without being dispatched to the main thread, even though this class is marked @mainactor. The assignment on line 43 should be wrapped in a DispatchQueue.main.async block to maintain thread safety.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Copy link
Contributor

Copilot AI commented Jan 12, 2026

@bgoncal I've opened a new pull request, #4214, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Jan 12, 2026

@bgoncal I've opened a new pull request, #4215, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Jan 12, 2026

@bgoncal I've opened a new pull request, #4216, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 2 commits January 12, 2026 21:05
…acks (#4216)

## Summary
The `CameraMJPEGPlayerViewModel` class is marked `@MainActor` but was
accessing MainActor-isolated properties from background thread callbacks
without proper synchronization. This creates race conditions and
potential crashes.

**Changes:**
- Wrapped `startStream()` method call in `DispatchQueue.main.async` when
invoked from background `.pipe` callback
- Wrapped `errorMessage` property assignment in
`DispatchQueue.main.async` in the rejected case
- Removed redundant `hasStarted = false` assignment that could race with
the cleanup block

All MainActor-isolated members are now accessed exclusively on the main
thread.

## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
N/A - Internal thread safety fix with no UI changes

## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
N/A - Internal implementation change

## Any other notes
This PR merges into #4213 and addresses feedback from
#4213 (comment)

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: bgoncal <[email protected]>
…4215)

## Summary
Addresses thread safety issue where `hasStarted` flag was being modified
from background threads despite `@MainActor` annotation on the class.

**Changes:**
- Replace direct `hasStarted = false` assignment in error handler with
`stop()` call to ensure flag modification happens on main thread
- All `hasStarted` modifications now properly dispatched to main thread
via `DispatchQueue.main.async` or through `@MainActor` methods

## Screenshots
N/A - Internal state management change with no UI impact

## Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#

## Any other notes
This is a stacked PR that merges into #4213 to address review feedback
from
#4213 (comment)

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
@codecov
Copy link

codecov bot commented Jan 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@3f27274). Learn more about missing BASE report.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4213   +/-   ##
=======================================
  Coverage        ?   44.85%           
=======================================
  Files           ?      250           
  Lines           ?    14414           
  Branches        ?        0           
=======================================
  Hits            ?     6466           
  Misses          ?     7948           
  Partials        ?        0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bgoncal bgoncal changed the title Simplify CameraView MPEG Simplify CameraView MJPEG Jan 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants