Skip to content

Commit 6778441

Browse files
authored
Capture pixel screenshots implementation on iOS (#99)
1 parent 30539ad commit 6778441

File tree

5 files changed

+37
-17
lines changed

5 files changed

+37
-17
lines changed

platform/swift/source/CoreLogger.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,10 @@ extension CoreLogger: CoreLogging {
8787
)
8888
}
8989

90-
func logSessionReplayScreenshot(screen: SessionReplayCapture, duration: TimeInterval) {
90+
func logSessionReplayScreenshot(screen: SessionReplayCapture?, duration: TimeInterval) {
91+
let fields = screen.flatMap { screen in self.convertFields(fields: ["screen_px": screen]) } ?? []
9192
self.underlyingLogger.logSessionReplayScreenshot(
92-
fields: self.convertFields(fields: ["screen": screen]),
93+
fields: fields,
9394
duration: duration
9495
)
9596
}

platform/swift/source/CoreLogging.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ protocol CoreLogging: AnyObject {
5555

5656
/// Writes a session replay screen log.
5757
///
58-
/// - parameter screen: The captured screenshot.
58+
/// - parameter screen: The captured screenshot. `nil` if screenshot couldn't be taken.
5959
/// - parameter duration: The duration of time the preparation of the log took.
60-
func logSessionReplayScreenshot(screen: SessionReplayCapture, duration: TimeInterval)
60+
func logSessionReplayScreenshot(screen: SessionReplayCapture?, duration: TimeInterval)
6161

6262
/// Writes a resource utilization log.
6363
///

platform/swift/source/replay/SessionReplayTarget.swift

+28-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
@_implementationOnly import CapturePassable
99
import Foundation
10+
import UIKit
1011

1112
final class SessionReplayTarget {
1213
private let queue = DispatchQueue.serial(withLabelSuffix: "ReplayController", target: .default)
@@ -41,14 +42,32 @@ extension SessionReplayTarget: CapturePassable.SessionReplayTarget {
4142
}
4243

4344
func captureScreenshot() {
44-
// TODO: Implement
45-
// DispatchQueue.main.async { [weak self] in
46-
// self?.queue.async {
47-
// self?.logger?.logSessionReplayScreenshot(
48-
// screen: SessionReplayCapture(data: Data()),
49-
// duration: 0
50-
// )
51-
// }
52-
// }
45+
DispatchQueue.main.async {
46+
guard let window = UIApplication.shared.sessionReplayWindows().first else {
47+
self.logger?.logSessionReplayScreenshot(
48+
screen: nil,
49+
duration: 0
50+
)
51+
return
52+
}
53+
54+
let layer = window.layer
55+
let bounds = UIScreen.main.bounds.size
56+
57+
self.queue.async { [weak self] in
58+
let start = Uptime()
59+
let format = UIGraphicsImageRendererFormat()
60+
format.scale = 1.0
61+
62+
let renderer = UIGraphicsImageRenderer(size: bounds, format: format)
63+
let jpeg = renderer.jpegData(withCompressionQuality: 0.1) { context in
64+
layer.render(in: context.cgContext)
65+
}
66+
self?.logger?.logSessionReplayScreenshot(
67+
screen: SessionReplayCapture(data: jpeg),
68+
duration: Uptime().timeIntervalSince(start)
69+
)
70+
}
71+
}
5372
}
5473
}

test/platform/swift/unit_integration/core/bridge/SessionReplayTargetTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ final class SessionReplayTargetTests: XCTestCase {
3030
func testEmitsSessionReplayScreenLog() {
3131
let expectation = self.expectation(description: "screen log is emitted")
3232

33-
self.logger.logSessionReplayScreen = expectation
33+
self.logger.logSessionReplayScreenExpectation = expectation
3434
self.target.captureScreen()
3535

3636
XCTAssertEqual(.completed, XCTWaiter().wait(for: [expectation], timeout: 0.5))

test/platform/swift/unit_integration/mocks/MockCoreLogging.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public final class MockCoreLogging {
4444
public var logResourceUtilizationExpectation: XCTestExpectation?
4545

4646
public private(set) var sessionReplayScreenLogs = [SessionReplayScreenLog]()
47-
public var logSessionReplayScreen: XCTestExpectation?
47+
public var logSessionReplayScreenExpectation: XCTestExpectation?
4848

4949
public var shouldLogAppUpdateEvent = false
5050

@@ -115,10 +115,10 @@ extension MockCoreLogging: CoreLogging {
115115
self.sessionReplayScreenLogs.append(SessionReplayScreenLog(
116116
screen: screen, duration: duration)
117117
)
118-
self.logSessionReplayScreen?.fulfill()
118+
self.logSessionReplayScreenExpectation?.fulfill()
119119
}
120120

121-
public func logSessionReplayScreenshot(screen _: SessionReplayCapture, duration _: TimeInterval) {}
121+
public func logSessionReplayScreenshot(screen _: SessionReplayCapture?, duration _: TimeInterval) {}
122122

123123
public func logResourceUtilization(fields: Fields, duration: TimeInterval) {
124124
self.resourceUtilizationLogs.append(ResourceUtilizationLog(fields: fields, duration: duration))

0 commit comments

Comments
 (0)