Skip to content

Commit 70ae0e9

Browse files
authored
Bug report setting (#29)
1 parent 61ede64 commit 70ae0e9

6 files changed

Lines changed: 73 additions & 23 deletions

File tree

Snap-O/ADB/ADBExec.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@ struct ADBExec: Sendable {
2424
func startScreenrecord(
2525
deviceID: String,
2626
bitRateMbps: Int = 8,
27-
timeLimitSeconds: Int = 60 * 60 * 3
27+
timeLimitSeconds: Int = 60 * 60 * 3,
28+
bugReport: Bool = false
2829
) async throws -> RecordingSession {
2930
let sizeHint = try? await displaySize(deviceID: deviceID)
3031
let remote = "/data/local/tmp/snapo_recording_\(UUID().uuidString).mp4"
3132
let command = makeScreenRecordCommand(
3233
bitRateMbps: bitRateMbps,
3334
timeLimitSeconds: timeLimitSeconds,
3435
size: sizeHint,
35-
destination: remote
36+
destination: remote,
37+
bugReport: bugReport
3638
)
3739

3840
let connection = try await makeConnection()
@@ -308,11 +310,13 @@ struct ADBExec: Sendable {
308310
timeLimitSeconds: Int,
309311
size: String?,
310312
destination: String,
311-
outputFormat: String? = nil
313+
outputFormat: String? = nil,
314+
bugReport: Bool = false
312315
) -> String {
313316
var command = "screenrecord --bit-rate \(bitRateMbps * 1_000_000) --time-limit \(timeLimitSeconds)"
314317
if let outputFormat, !outputFormat.isEmpty { command += " --output-format=\(outputFormat)" }
315318
if let size, !size.isEmpty { command += " --size \(size)" }
319+
if bugReport { command += " --bugreport" }
316320
command += " \(destination)"
317321
return command
318322
}

Snap-O/App/AppSettings.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,21 @@ final class AppSettings: ObservableObject {
77

88
@Published var showTouchesDuringCapture: Bool {
99
didSet {
10-
UserDefaults.standard.set(showTouchesDuringCapture, forKey: Self.key)
10+
UserDefaults.standard.set(showTouchesDuringCapture, forKey: Self.showTouchesKey)
1111
}
1212
}
1313

14-
private static let key = "showTouchesDuringCapture"
14+
@Published var recordAsBugReport: Bool {
15+
didSet {
16+
UserDefaults.standard.set(recordAsBugReport, forKey: Self.bugReportKey)
17+
}
18+
}
19+
20+
private static let showTouchesKey = "showTouchesDuringCapture"
21+
private static let bugReportKey = "recordAsBugReport"
1522

1623
init() {
17-
showTouchesDuringCapture = UserDefaults.standard.object(forKey: Self.key) as? Bool ?? true
24+
showTouchesDuringCapture = UserDefaults.standard.object(forKey: Self.showTouchesKey) as? Bool ?? true
25+
recordAsBugReport = UserDefaults.standard.object(forKey: Self.bugReportKey) as? Bool ?? false
1826
}
1927
}

Snap-O/App/CaptureService.swift

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ actor CaptureService {
1212
private var lastCaptureTimestamp: Date? // Keeps filenames unique when captures share a real timestamp.
1313
private var showTouchesOverrides: [String: Task<Bool?, Never>] = [:]
1414

15-
init(adb: ADBService, fileStore: FileStore, deviceTracker: DeviceTracker) {
15+
init(
16+
adb: ADBService,
17+
fileStore: FileStore,
18+
deviceTracker: DeviceTracker
19+
) {
1620
self.adb = adb
1721
self.fileStore = fileStore
1822
self.deviceTracker = deviceTracker
@@ -55,14 +59,18 @@ actor CaptureService {
5559
func startRecordings(for devices: [Device]) async -> ([String: RecordingSession], Error?) {
5660
var sessions: [String: RecordingSession] = [:]
5761
var encounteredError: Error?
62+
let targetBugReport = await AppSettings.shared.recordAsBugReport
5863

5964
await withTaskGroup(of: (String, Result<RecordingSession, Error>).self) { group in
65+
let exec = await adb.exec()
6066
for device in devices {
6167
group.addTask {
62-
let exec = await self.adb.exec()
68+
await self.beginShowTouchesOverride(deviceID: device.id)
6369
do {
64-
let session = try await exec.startScreenrecord(deviceID: device.id)
65-
await self.beginShowTouchesOverride(deviceID: device.id)
70+
let session = try await exec.startScreenrecord(
71+
deviceID: device.id,
72+
bugReport: targetBugReport
73+
)
6674
return (device.id, .success(session))
6775
} catch {
6876
await self.scheduleRestoreShowTouches(deviceID: device.id)
@@ -147,8 +155,9 @@ actor CaptureService {
147155
}
148156

149157
func startLivePreview(for deviceID: String) async throws -> LivePreviewSession {
158+
beginShowTouchesOverride(deviceID: deviceID)
159+
150160
do {
151-
beginShowTouchesOverride(deviceID: deviceID)
152161
return try await LivePreviewSession(deviceID: deviceID, adb: adb)
153162
} catch {
154163
await scheduleRestoreShowTouches(deviceID: deviceID)
@@ -197,10 +206,10 @@ actor CaptureService {
197206
guard showTouchesOverrides[deviceID] == nil else { return }
198207

199208
let task = Task<Bool?, Never> {
209+
let targetValue = await AppSettings.shared.showTouchesDuringCapture
210+
let exec = await adb.exec()
200211
do {
201-
let exec = await adb.exec()
202212
let originalValue = try await exec.getShowTouches(deviceID: deviceID)
203-
let targetValue = await AppSettings.shared.showTouchesDuringCapture
204213
if originalValue != targetValue {
205214
try await exec.setShowTouches(deviceID: deviceID, enabled: targetValue)
206215
}
@@ -217,10 +226,10 @@ actor CaptureService {
217226
}
218227

219228
private func scheduleRestoreShowTouches(deviceID: String) async {
220-
guard let state = showTouchesOverrides.removeValue(forKey: deviceID) else { return }
229+
guard let task = showTouchesOverrides.removeValue(forKey: deviceID) else { return }
221230
let exec = await adb.exec()
222231
Task.detached(priority: .utility) {
223-
let originalValue = await state.value
232+
let originalValue = await task.value
224233
guard let originalValue else { return }
225234
do {
226235
try await exec.setShowTouches(deviceID: deviceID, enabled: originalValue)

Snap-O/App/SnapOCommands.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ struct SnapOCommands: Commands {
114114
.disabled(!hasAlternativeMedia)
115115
Divider()
116116
Toggle("Show Touches During Capture", isOn: $settings.showTouchesDuringCapture)
117+
Toggle("Record Screen as Bug Report", isOn: $settings.recordAsBugReport)
117118
}
118119
CommandMenu("ADB") {
119120
Button("Set ADB path…") {

Snap-O/CaptureWindow/CaptureToolbar.swift

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import SwiftUI
22

33
struct CaptureToolbar: ToolbarContent {
44
@ObservedObject var controller: CaptureWindowController
5+
@ObservedObject var settings: AppSettings
56

67
var body: some ToolbarContent {
78
if controller.isRecording {
@@ -14,6 +15,7 @@ struct CaptureToolbar: ToolbarContent {
1415
}
1516
} else {
1617
IdleToolbarControls(
18+
settings: settings,
1719
screenshot: { Task { await controller.captureScreenshots() } },
1820
canCaptureNow: controller.canCaptureNow,
1921
startRecording: { Task { await controller.startRecording() } },
@@ -26,6 +28,8 @@ struct CaptureToolbar: ToolbarContent {
2628

2729
@ViewBuilder
2830
private func recordingControls() -> some View {
31+
let bugReportEnabled = settings.recordAsBugReport
32+
2933
if controller.isProcessing {
3034
ProgressView()
3135
.progressViewStyle(.circular)
@@ -37,7 +41,7 @@ struct CaptureToolbar: ToolbarContent {
3741
Button {
3842
Task { await controller.stopRecording() }
3943
} label: {
40-
Label("Stop", systemImage: "stop.fill")
44+
Label("Stop Recording", systemImage: bugReportEnabled ? "ant.fill" : "stop.fill")
4145
.fontWeight(.semibold)
4246
.padding(.horizontal, 8)
4347
.padding(.vertical, 6)
@@ -70,6 +74,7 @@ struct CaptureToolbar: ToolbarContent {
7074
}
7175

7276
struct IdleToolbarControls: ToolbarContent {
77+
@ObservedObject var settings: AppSettings
7378
let screenshot: @MainActor () -> Void
7479
let canCaptureNow: Bool
7580
let startRecording: @MainActor () -> Void
@@ -88,13 +93,35 @@ struct IdleToolbarControls: ToolbarContent {
8893
.help("New Screenshot (⌘R)")
8994
.disabled(!canCaptureNow)
9095

91-
Button {
92-
startRecording()
93-
} label: {
94-
Label("Record", systemImage: "record.circle")
96+
if settings.recordAsBugReport {
97+
Menu {
98+
Button("Disable Bug Report Mode") {
99+
settings.recordAsBugReport = false
100+
}
101+
} label: {
102+
Label("Record", systemImage: "ant.circle")
103+
} primaryAction: {
104+
startRecording()
105+
}
106+
.overlay(alignment: .bottomTrailing) {
107+
Image(systemName: "chevron.down")
108+
.font(.system(size: 5, weight: .bold))
109+
.offset(x: -6, y: -2)
110+
}
111+
.padding(.horizontal, -3)
112+
.menuIndicator(.hidden)
113+
.menuStyle(.button)
114+
.help("Start Recording Bug Report (⌘⇧R)")
115+
.disabled(!canStartRecordingNow)
116+
} else {
117+
Button {
118+
startRecording()
119+
} label: {
120+
Label("Record", systemImage: "record.circle")
121+
}
122+
.help("Start Recording (⌘⇧R)")
123+
.disabled(!canStartRecordingNow)
95124
}
96-
.help("Start Recording (⌘⇧R)")
97-
.disabled(!canStartRecordingNow)
98125

99126
Button {
100127
startLivePreview()

Snap-O/CaptureWindow/CaptureWindow.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import SwiftUI
22

33
struct CaptureWindow: View {
44
@StateObject private var controller = CaptureWindowController()
5+
@StateObject private var settings = AppSettings.shared
56

67
var body: some View {
78
ZStack {
@@ -40,7 +41,7 @@ struct CaptureWindow: View {
4041
.frame(width: 0, height: 0)
4142
)
4243
.toolbar {
43-
CaptureToolbar(controller: controller)
44+
CaptureToolbar(controller: controller, settings: settings)
4445

4546
if let progress = controller.captureProgressText {
4647
ToolbarItem(placement: .status) {

0 commit comments

Comments
 (0)