Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,21 @@ jobs:
- name: Checkout code
uses: actions/checkout@v6

- name: Install xcbeautify
run: brew install xcbeautify

- name: Build and Test
run: |
set -o pipefail
xcodebuild test \
-project wled.xcodeproj \
-scheme wled \
-destination 'platform=iOS Simulator,name=iPhone 17,OS=latest' \
-skipPackagePluginValidation \
-skipMacroValidation \
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
-resultBundlePath TestResults.xcresult \
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO \
2>&1 | xcbeautify --report junit --report-path . --junit-report-filename junit.xml

lint:
name: Run Lint
Expand Down
5 changes: 5 additions & 0 deletions wled/View/DeviceListItemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ struct DeviceListItemView: View {
Toggle("Turn On/Off", isOn: isOnBinding)
.labelsHidden()
.frame(alignment: .trailing)
// On iOS 16, tapping the Toggle also triggers the parent row's .onTapGesture.
// This empty handler "consumes" the SwiftUI tap at the child level,
// while the underlying UISwitch still receives the UIKit event.
// This can be removed once the minimum deployment target is iOS 17+.
.onTapGesture { }
Comment thread
Moustachauve marked this conversation as resolved.
}

Slider(
Expand Down
7 changes: 6 additions & 1 deletion wled/ViewModel/DeviceWebsocketListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ class DeviceWebsocketListViewModel: NSObject, ObservableObject, NSFetchedResults
private var activeClients: [String: ClientWrapper] = [:]
private var isPaused = false
private var backgroundTask: Task<Void, Never>?

/// Delay before disconnecting websockets after entering background.
/// Exposed as `internal` so tests can override with a shorter value.
var backgroundDisconnectDelay: Duration = .seconds(2)

/// Amount of time after a device becomes offline before it is considered offline.
private let offlineGracePeriod: TimeInterval = 60
Expand Down Expand Up @@ -265,9 +269,10 @@ class DeviceWebsocketListViewModel: NSObject, ObservableObject, NSFetchedResults
func onPause() {
print("[ListVM] onPause: Scheduling disconnect.")
backgroundTask?.cancel()
let delay = backgroundDisconnectDelay
backgroundTask = Task { @MainActor [weak self] in
do {
try await Task.sleep(for: .seconds(2))
try await Task.sleep(for: delay)
} catch {
// Task was cancelled (user came back quickly)
return
Expand Down
3 changes: 2 additions & 1 deletion wledTests/DeviceWebsocketListViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@

@Test func testInitialLoadingAndSorting() async throws {
// 1. Setup mock data
let device1 = createDevice(name: "Z Device", mac: "01", isHidden: false)

Check warning on line 20 in wledTests/DeviceWebsocketListViewModelTests.swift

View workflow job for this annotation

GitHub Actions / Run Unit Tests

initialization of immutable value 'device1' was never used; consider replacing with assignment to '_' or removing it

Check warning on line 20 in wledTests/DeviceWebsocketListViewModelTests.swift

View workflow job for this annotation

GitHub Actions / Run Unit Tests

initialization of immutable value 'device1' was never used; consider replacing with assignment to '_' or removing it
let device2 = createDevice(name: "A Device", mac: "02", isHidden: false)

Check warning on line 21 in wledTests/DeviceWebsocketListViewModelTests.swift

View workflow job for this annotation

GitHub Actions / Run Unit Tests

initialization of immutable value 'device2' was never used; consider replacing with assignment to '_' or removing it

Check warning on line 21 in wledTests/DeviceWebsocketListViewModelTests.swift

View workflow job for this annotation

GitHub Actions / Run Unit Tests

initialization of immutable value 'device2' was never used; consider replacing with assignment to '_' or removing it
let device3 = createDevice(name: "Hidden Device", mac: "03", isHidden: true)

Check warning on line 22 in wledTests/DeviceWebsocketListViewModelTests.swift

View workflow job for this annotation

GitHub Actions / Run Unit Tests

initialization of immutable value 'device3' was never used; consider replacing with assignment to '_' or removing it

Check warning on line 22 in wledTests/DeviceWebsocketListViewModelTests.swift

View workflow job for this annotation

GitHub Actions / Run Unit Tests

initialization of immutable value 'device3' was never used; consider replacing with assignment to '_' or removing it
try context.save()

let viewModel = DeviceWebsocketListViewModel(context: context)
Expand Down Expand Up @@ -105,6 +105,7 @@
try context.save()

let viewModel = DeviceWebsocketListViewModel(context: context)
viewModel.backgroundDisconnectDelay = .milliseconds(100)
let mockClient = ManualMockWebsocketClient(device: device)
viewModel.makeClient = { _ in mockClient }

Expand All @@ -115,7 +116,7 @@

// Simulate going to background and staying there
viewModel.onPause()
try await Task.sleep(for: .seconds(4)) // Wait well past the 2s delay (generous for CI)
try await Task.sleep(for: .milliseconds(500)) // Wait well past the 100ms delay

// Device should now be disconnected
#expect(mockClient.deviceState.websocketStatus == .disconnected)
Expand Down
Loading