Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/ipad 17 testing #5

Merged
merged 14 commits into from
Feb 2, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/deploy-documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
steps:
- name: Print job info
run: |
echo "The job was automatically triggered by a ${{ github.event_name }} event and is now running on a ${{ runner.os }} server."
echo "The job was triggered by a ${{ github.event_name }} event and is now running on a ${{ runner.os }} server."
echo "The repository is ${{ github.repository }} and the branch is ${{ github.ref }}."
echo "Available XCode versions:"
sudo ls -1 /Applications | grep "Xcode"
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: "Run tests"
run-name: ${{ github.actor }} is running tests
on: [push]
jobs:
run-tests:
runs-on: macos-14
steps:
- name: Print job info
run: |
echo "The job was triggered by a ${{ github.event_name }} event and is now running on a ${{ runner.os }} server."
echo "The repository is ${{ github.repository }} and the branch is ${{ github.ref }}."
echo "Available XCode versions:"
sudo ls -1 /Applications | grep "Xcode"
echo "Selected XCode version:"
/usr/bin/xcodebuild -version

- name: Check out repository code
uses: actions/checkout@v4

- name: Run the tests
run: xcodebuild -scheme StreamDeckKit-Package test -destination "platform=iOS Simulator,name=iPhone 15,OS=latest" | xcpretty
4 changes: 2 additions & 2 deletions Example/Example App/StreamDeckHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ class StreamDeckHandler {
case let .rotaryEncoderRotation(index, rotation):
print("Rotary \(index) rotation \"\(rotation)\" on \(device.infoText).")

case let .touch(x, y):
print("Did touch at (x:\(x), y:\(y)) on \(device.infoText).")
case let .touch(point):
print("Did touch at (\(point.debugDescription)) on \(device.infoText).")

case .fling:
print("Did fling to \(event.direction) on \(device.infoText).")
Expand Down
23 changes: 23 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"pins" : [
{
"identity" : "swift-snapshot-testing",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-snapshot-testing",
"state" : {
"revision" : "8e68404f641300bfd0e37d478683bb275926760c",
"version" : "1.15.2"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax.git",
"state" : {
"revision" : "64889f0c732f210a935a0ad7cda38f77f876262d",
"version" : "509.1.1"
}
}
],
"version" : 2
}
13 changes: 12 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ let package = Package(
targets: ["StreamDeckSimulator"]
)
],
dependencies: [
.package(
url: "https://github.com/pointfreeco/swift-snapshot-testing",
from: "1.12.0"
),
],
targets: [
.target(
name: "StreamDeckSimulator",
Expand All @@ -40,7 +46,12 @@ let package = Package(
),
.testTarget(
name: "StreamDeckSDKTests",
dependencies: ["StreamDeckKit"]
dependencies: [
"StreamDeckKit",
"StreamDeckLayout",
"StreamDeckSimulator",
.product(name: "SnapshotTesting", package: "swift-snapshot-testing")
]
)
]
)
4 changes: 4 additions & 0 deletions Sources/StreamDeckKit/AsyncQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ final class AsyncQueue<Element> {
private var queue = [Element]()
private var continuations = [UnsafeContinuation<Element, Error>]()

var count: Int {
lock.withLock { queue.count }
}

func enqueue(_ element: Element) {
lock.withLock {
guard continuations.isEmpty else {
Expand Down
31 changes: 25 additions & 6 deletions Sources/StreamDeckKit/Extensions/StreamDeck+OperationQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extension StreamDeck {
case setFullscreenImage(image: UIImage, scaleAspectFit: Bool)
case setTouchAreaImage(image: UIImage, at: CGRect, scaleAspectFit: Bool)
case fillDisplay(color: UIColor)
case task(() async -> Void)
case close

var isDrawingOperation: Bool {
Expand All @@ -38,10 +39,12 @@ extension StreamDeck {
}

func enqueueOperation(_ operation: Operation) {
guard !isClosed else { return }

var wasReplaced = false

switch operation {
case .setInputEventHandler, .setBrightness:
case .setInputEventHandler, .setBrightness, .task:
break

case let .setImageOnKey(_, key, _):
Expand Down Expand Up @@ -77,10 +80,15 @@ extension StreamDeck {
private func run(_ operation: Operation) async {
switch operation {
case let .setInputEventHandler(handler):
await MainActor.run { client.setInputEventHandler(handler) }
guard !didSetInputEventHandler else { return }

await MainActor.run {
client.setInputEventHandler(handler)
didSetInputEventHandler = true
}

case let .setBrightness(brightness):
client.setBrightness(brightness)
client.setBrightness(min(max(brightness, 0), 100))

case let .setImageOnKey(image, key, scaleAspectFit):
guard let keySize = capabilities.keySize,
Expand Down Expand Up @@ -114,19 +122,30 @@ extension StreamDeck {
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0

color.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
client.fillDisplay(red: UInt8(255 * red), green: UInt8(255 * green), blue: UInt8(255 * blue))

client.fillDisplay(
red: UInt8(min(255 * red, 255)),
green: UInt8(min(255 * green, 255)),
blue: UInt8(min(255 * blue, 255))
)
} else {
fakeFillDisplay(color)
}

case .close:
client.close()
case let .task(task):
await task()

case .close:
for handler in closeHandlers {
await handler()
}

client.close()
isClosed = true

operationsQueue.removeAll()
operationsTask?.cancel()
}
}
Expand Down
29 changes: 12 additions & 17 deletions Sources/StreamDeckKit/Models/InputEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,33 +39,28 @@ public enum InputEvent: Equatable {
case rotaryEncoderRotation(index: Int, rotation: Int)

/// Signals a touch on the touch strip of e.g. a Stream Deck Plus.
/// - Parameters:
/// - x: The horizontal position of the touch event.
/// - y: The vertical position of the touch event.
case touch(x: Int, y: Int)
case touch(CGPoint)

/// Signals a swipe-like gesture on the touch strip of e.g. a Stream Deck Plus.
/// - Parameters:
/// - startX: The horizontal start position of the fling.
/// - startY: The vertical start position of the fling.
/// - endX: The horizontal end position of the fling.
/// - endY: The vertical end position of the fling.
/// - start: The start position of the fling.
/// - end: The end position of the fling.
///
/// The intensity of the gesture can be calculated by getting the distance between start and end-point.
case fling(startX: Int, startY: Int, endX: Int, endY: Int)
case fling(start: CGPoint, end: CGPoint)

/// The direction of a ``fling(startX:startY:endX:endY:)`` event.
///
/// When the event is anything but a fling, ``Direction-swift.enum/none`` will be returned.
public var direction: Direction {
switch self {
case let .fling(startX, startY, endX, endY):
guard startX != endX || startY != endY else {
case let .fling(start, end):
guard start != end else {
return .none
}

let diffX = startX - endX
let diffY = startY - endY
let diffX = start.x - end.x
let diffY = start.y - end.y

if abs(diffX) > abs(diffY) {
return diffX < 0 ? .right : .left
Expand All @@ -89,10 +84,10 @@ extension InputEvent: CustomStringConvertible {
return "InputEvent.rotaryEncoderPress(index: \(index), pressed: \(pressed))"
case let .rotaryEncoderRotation(index, rotation):
return "InputEvent.rotaryEncoderRotation(index: \(index), rotation: \(rotation))"
case let .touch(x, y):
return "InputEvent.touch(x: \(x), y: \(y))"
case let .fling(startX, startY, endX, endY):
return "InputEvent.fling(startX: \(startX), startY: \(startY), endX: \(endX), endY: \(endY))"
case let .touch(point):
return "InputEvent.touch(x: \(point.x), y: \(point.y))"
case let .fling(start, end):
return "InputEvent.fling(start: \(start.x),\(start.y), end: \(end.x),\(end.y))"
}
}

Expand Down
18 changes: 14 additions & 4 deletions Sources/StreamDeckKit/Models/StreamDeck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ public final class StreamDeck {
public let info: DeviceInfo
/// Capabilities and features of the device.
public let capabilities: DeviceCapabilities
/// Check if this device was closed. If true, all operations are silently ignored.
public internal(set) var isClosed: Bool = false

let operationsQueue = AsyncQueue<Operation>()
var operationsTask: Task<Void, Never>?
var didSetInputEventHandler = false

private let inputEventsSubject = PassthroughSubject<InputEvent, Never>()

Expand All @@ -42,9 +45,9 @@ public final class StreamDeck {
/// Set a handler to handle key-presses, touches and other events.
public var inputEventHander: InputEventHandler? {
didSet {
if inputEventHander != nil {
subscribeToInputEvents()
}
guard inputEventHander != nil else { return }

subscribeToInputEvents()
}
}

Expand Down Expand Up @@ -76,6 +79,8 @@ public final class StreamDeck {
}

private func subscribeToInputEvents() {
guard !didSetInputEventHandler else { return }

enqueueOperation(.setInputEventHandler { [weak self] event in
self?.handleInputEvent(event)
})
Expand Down Expand Up @@ -143,7 +148,12 @@ public final class StreamDeck {
/// the image will be scaled to fill the whole `rect`.
///
/// The image will be scaled to fit the dimensions of the given rectangle.
public func setTouchAreaImage(_ image: UIImage, at rect: CGRect, scaleAspectFit: Bool = true) {
public func setTouchAreaImage(_ image: UIImage, at rect: CGRect? = nil, scaleAspectFit: Bool = true) {
guard capabilities.hasSetImageOnXYSupport,
let touchDisplayRect = capabilities.touchDisplayRect
else { return }

let rect = rect ?? .init(origin: .zero, size: touchDisplayRect.size)
enqueueOperation(.setTouchAreaImage(image: image, at: rect, scaleAspectFit: scaleAspectFit))
}

Expand Down
10 changes: 8 additions & 2 deletions Sources/StreamDeckKit/StreamDeckClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,17 @@ final class StreamDeckClient: StreamDeckClientProtocol {
}

case SDInputEventTypeTouch.rawValue:
inputEventHandler?(.touch(x: Int(event.touch.x), y: Int(event.touch.y)))
inputEventHandler?(.touch(.init(
x: Int(event.touch.x),
y: Int(event.touch.y))
))

case SDInputEventTypeFling.rawValue:
let fling = event.fling
inputEventHandler?(.fling(startX: Int(fling.startX), startY: Int(fling.startY), endX: Int(fling.endX), endY: Int(fling.endY)))
inputEventHandler?(.fling(
start: .init(x: Int(fling.startX), y: Int(fling.startY)),
end: .init(x: Int(fling.endX), y: Int(fling.endY))
))
default:
return
}
Expand Down
6 changes: 5 additions & 1 deletion Sources/StreamDeckLayout/Environment+Ext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import SwiftUI
public struct StreamDeckViewContextKey: EnvironmentKey {

public static var defaultValue: StreamDeckViewContext = .init(
device: StreamDeck(client: StreamDeckClientMock(), info: .init(), capabilities: .init()),
device: StreamDeck(
client: StreamDeckClientDummy(),
info: .init(),
capabilities: .init()
),
dirtyMarker: .background,
size: .zero
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
//
// File.swift
//
// StreamDeckClientDummy.swift
//
//
// Created by Roman Schlagowsky on 05.01.24.
//

import Combine
import Foundation
import StreamDeckCApi
import StreamDeckKit

public final class StreamDeckClientMock: StreamDeckClientProtocol {
final class StreamDeckClientDummy: StreamDeckClientProtocol {
public init() {}
public func setInputEventHandler(_ handler: @escaping InputEventHandler) {}
public func setBrightness(_ brightness: Int) {}
Expand Down
52 changes: 0 additions & 52 deletions Sources/StreamDeckLayout/Views/StreamDeckDialLayout.swift

This file was deleted.

Loading